自己制作软键盘的几个关键技术解析
2011-05-23 16:23
316 查看
在嵌入式应用和一些安全软件中经常需要不通过物理键盘输入,虽然微软提供了也一个软键盘,但这个软件盘不能定制界面不能自动感应当前光标是否处于输入状态,所以有时候我们还是需要自己来实现这个软键盘。本文将讲解自己实现软键盘时涉及到的几个关键技术。
如上图所示,虽然软键盘在记事本的前面,但光标仍然在记事本上。
要实现这个技术,我们必须要把当前窗体设置为浮动工具条才行。这里我给出 C# Winform 的实现方法:
如上代码就是将 Winform 指定为浮动工具条窗体。只要在winform 的类中重载 CreateParams 函数,并按上述代码编写就可以了。
要实现这个功能,我们能想到的最直接的方法是 windows 是否会在当前处于输入状态下时发一个什么事件,或者通过什么钩子程序来实现。但我研究了很久,没有找到这种方法。如果哪位知道这种方法,不妨在回复中告诉我。
我目前找到的方法是定时询问 windows 的当前窗体是否处于输入状态(http://www.my400800.cn)。
如上面代码所示
首先我们通过 GetForegroundWindows API 得到当前窗体的句柄。然后我们再通过 GetGUIThreadInfo 得到当前窗体的一些属性。这些属性在 GUITHREADINFO 中定义
上面是 GUITHREADINFO
结构。我们可以通过这个信息得到当前窗体中当前焦点的子窗口句柄,当前获得光标的子窗口句柄,当前正激活的子窗体句柄等等。这里我们只要用到当前获得光标
的子窗口句柄,就是 hwndCaret 。如果hwndCaret 不为0,则表示当前窗体处于可输入状态。
相关API函数的 C# 定义如下:
System.Windows.Forms.SendKeys.Send
这个函数很简单,而且微软的帮助也很全面了,我这里就不多说了。
另外我们还可以用更加底层的 API 函数来模拟键盘的输入
这个函数是 keybd_event,关于这个函数的使用,微软的帮助也写的很清楚,这里也不重述了。
一、浮动窗体的实现
软键盘的窗体和普通窗体不一样,这个窗体在成为当前窗体时,不会影响其它进程的窗体的光标焦点。也就是说虽然这个窗体现在为当前激活的前台窗体,但光标仍然停在其他进程的窗体上。如上图所示,虽然软键盘在记事本的前面,但光标仍然在记事本上。
要实现这个技术,我们必须要把当前窗体设置为浮动工具条才行。这里我给出 C# Winform 的实现方法:
private const int WS_EX_TOOLWINDOW = 0x00000080; private const int WS_EX_NOACTIVATE = 0x08000000; protected override CreateParams CreateParams { get { CreateParams cp = base.CreateParams; cp.ExStyle |= (WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW); cp.Parent = IntPtr.Zero; // Keep this line only if you used UserControl return cp; //return base.CreateParams; } }
如上代码就是将 Winform 指定为浮动工具条窗体。只要在winform 的类中重载 CreateParams 函数,并按上述代码编写就可以了。
二、如何检测当前处于输入状态
在一些嵌入式设备中,我们没有物理键盘,所有的输入都是通过触摸屏和软键盘输入。那么这个时候,我们必须要做到只有处于输入状态时才弹出软键盘,否则如果软键盘一直在界面上,既不美观也妨碍其他程序的正常使用。要实现这个功能,我们能想到的最直接的方法是 windows 是否会在当前处于输入状态下时发一个什么事件,或者通过什么钩子程序来实现。但我研究了很久,没有找到这种方法。如果哪位知道这种方法,不妨在回复中告诉我。
我目前找到的方法是定时询问 windows 的当前窗体是否处于输入状态(http://www.my400800.cn)。
IntPtr hWnd = GetForegroundWindow(); uint processId; uint threadid = GetWindowThreadProcessId(hWnd, out processId); GUITHREADINFO lpgui = new GUITHREADINFO(); lpgui.cbSize = Marshal.SizeOf(lpgui); if (GetGUIThreadInfo(threadid, ref lpgui)) { if (lpgui.hwndCaret != 0) { return hWnd; } }
如上面代码所示
首先我们通过 GetForegroundWindows API 得到当前窗体的句柄。然后我们再通过 GetGUIThreadInfo 得到当前窗体的一些属性。这些属性在 GUITHREADINFO 中定义
public struct GUITHREADINFO { public int cbSize; public int flags; public int hwndActive; public int hwndFocus; public int hwndCapture; public int hwndMenuOwner; public int hwndMoveSize; public int hwndCaret; public System.Drawing.Rectangle rcCaret; }
上面是 GUITHREADINFO
结构。我们可以通过这个信息得到当前窗体中当前焦点的子窗口句柄,当前获得光标的子窗口句柄,当前正激活的子窗体句柄等等。这里我们只要用到当前获得光标
的子窗口句柄,就是 hwndCaret 。如果hwndCaret 不为0,则表示当前窗体处于可输入状态。
相关API函数的 C# 定义如下:
[DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetGUIThreadInfo(uint idThread, ref GUITHREADINFO lpgui); [DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll", SetLastError = true)] static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
三、模拟键盘输入
模拟键盘输入比较简单,.Net 提供了一个静态函数来模拟键盘输入System.Windows.Forms.SendKeys.Send
这个函数很简单,而且微软的帮助也很全面了,我这里就不多说了。
另外我们还可以用更加底层的 API 函数来模拟键盘的输入
[DllImport("user32.dll")] static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);
这个函数是 keybd_event,关于这个函数的使用,微软的帮助也写的很清楚,这里也不重述了。
相关文章推荐
- 自己制作软键盘的几个关键技术解析
- C#实现软键盘的几个关键技术介绍
- 实现软键盘的几个关键技术
- 实现软键盘的几个关键技术(转载)
- 自己做的几个小软件(数学工具和游戏),用C/C#制作,用到许多相关的C#技术细节,可以免费提供下载,感兴趣的,来看一下
- 互联网DSP广告系统架构及关键技术解析 | 广告行业资深架构师亲述
- 小博老师解析Java核心技术点-验证码制作
- 从一个实战项目来看一下React Native开发的几个关键技术点
- [z]C#使用WebBrowser制作网页游戏辅助工具关键技术分析
- 实时视频传输的关键技术 H.264 全解析
- redis数据库中的几个关键结构体解析
- Java封装C++类的几个关键技术点
- 大数据治理关键技术解析
- Premiere制作VCD视频几个关键设置
- Windows平台下C++插件系统实现的几个关键技术问题及其解决思路
- 我记录网站综合系统 -- 技术原理解析[番外篇:自己做Stopwatch]
- 看了几个技术入股的帖子,忍不住写个自己亲身经历吧
- C++PE文件格式解析类(轻松制作自己的PE文件解析器)
- Windows平台下C++插件系统实现的几个关键技术问题及其解决思路
- 学习FLASH制作动画的关键技术点