屏幕键盘关闭按钮事件?

Ger*_*ans 6 winapi dllimport tablet on-screen-keyboard windows-8

在应用程序中,我在平板电脑上运行时使用屏幕键盘(OSK).我们创建了一个名为OSK的类,它有一个show和hide方法.

当用户按下屏幕键盘上的"输入"时,osk会隐藏.问题是当用户使用关闭(x)按钮关闭OSK时.OSK隐藏了,但是当发生这种情况时,有些事情需要在UI中进行更改.

有没有办法(一个事件或类似的东西)知道用户何时按下OSK上的关闭按钮?

我将展示一些我用于显示和隐藏OSK的代码.显示的代码在Oxygene中(但它看起来很像C#我认为)

首先我们有一些dllImports:

[DllImport("user32.dll", SetLastError := true)]
class method PostMessage(hWnd: IntPtr; Msg: UInt32; wParam, lParam: IntPtr): Boolean; external;
[DllImport("user32.dll", SetLastError := true)]
class method FindWindow(lpClassName, lpWindowName: String): IntPtr; external; 
Run Code Online (Sandbox Code Playgroud)

在show方法中有这样的代码:

  using p := new Process do
  begin
    p.StartInfo.UseShellExecute := true;
    p.StartInfo.FileName := 'C:\Program Files\Common Files\Microsoft Shared\ink\TabTip.exe';
    p.Start();
  end; 
Run Code Online (Sandbox Code Playgroud)

在Hide方法中,下一个代码用于隐藏OSK:

      var oskWindow := FindWindow("IPTip_Main_Window", nil);
      var WM_SYSCOMMAND  := 274;
      var SC_CLOSE := 61536;
      PostMessage(oskWindow, WM_SYSCOMMAND, SC_CLOSE, 0);
Run Code Online (Sandbox Code Playgroud)

更新:找到一个适用于Windows 7的工作解决方案....不适用于Windows 8(我需要什么)

这就是我在Windows 7中解决问题的方法:主要思想是在OSK类中,我在显示osk时启动Dispatchertimer.现在,如果osk窗口可见,则检查每秒.如果是这样,则会触发一个可以在多个地方处理的事件.(我还检查了计时器中的_firstshown布尔值,因为有时需要一段时间才能显示osk.

这是我如何做到的:首先我做了一个IsWindowVisible方法的dllImport

[DllImport("user32.dll", CharSet:=CharSet.Auto)]
class method IsWindowVisible(hWnd:IntPtr):Boolean; external;
Run Code Online (Sandbox Code Playgroud)

在OSK.Show我启动计时器并将_firstShown设置为false(因为它可能需要一段时间才能显示osk)在此之前我将计时器间隔设置为1秒并向timer.Tick添加了一个eventhandlerf:

  _timer.Interval := new TimeSpan(0,0,1);
  _timer.Tick += new EventHandler(_timer_Tick);
Run Code Online (Sandbox Code Playgroud)

这是_timer_tick中的代码:

class method OSK._timer_Tick(sender: Object; e: EventArgs);
begin
  var oskWindow := FindWindow("IPTip_Main_Window", nil);
  var IsOSKOpen := IsWindowVisible(oskWindow);

  if not _firstShown then begin
      if IsOSKOpen then _firstShown := true;

      exit;
  end;
  if not IsOSKOpen then begin        
      OSKClosed(nil,new EventArgs());      
      _timer.Stop();
      _firstShown := false;
  end;
end;
Run Code Online (Sandbox Code Playgroud)

很高兴当我的开发机器(Windows 7)工作时,快乐是短暂的,因为当我在平板电脑(Windows 8)上测试时,它无法正常工作.计时器等工作正常,它看起来像Windows 8不处理iswindowVisible方法.

无论如何所有的帮助非常感谢

Ger*_*ans 2

终于找到了使用注册表解决我的问题的方法。osk 使用名为 UserClosed 的注册表项。如果用户关闭操作系统,则用户关闭的注册表项将为 1。

因此,首先要做的就是将此注册表项设置为 0(在 App.Xaml.cs 中重写 OnStartup)

    var regKeyUserClosed := Registry.CurrentUser.OpenSubKey("Software\Microsoft\TabletTip\1.7",true);
    regKeyUserClosed.SetValue("UserClosed",0);
Run Code Online (Sandbox Code Playgroud)

现在,当应用程序启动时,注册表项设置为 0。

现在,当调用 osk 时,计时器就会启动,在每次滴答时,我们需要查看注册表项是否为 1(用户已关闭 OSK),如果是,我们会触发事件,停止计时器并将注册表项设置回 0。

这是我的新timer_tick方法:

   class method OSK._timer_Tick(sender: Object; e: EventArgs);
begin

var regKeyUserClosed := Registry.CurrentUser.OpenSubKey("Software\Microsoft\TabletTip\1.7",true);

  var UserClosed := Convert.ToInt32(regKeyUserClosed.GetValue("UserClosed"));

  if UserClosed.Equals(1) then begin 

  OSKClosed(nil,new EventArgs()); 

  _timer.Stop();

  regKeyUserClosed.SetValue("UserClosed",0);

  end; 

end;
Run Code Online (Sandbox Code Playgroud)