实现软键盘的几个关键技术
2011-05-20 06:28
274 查看
作者:eaglet
转载请注明出处
在嵌入式应用和一些安全软件中经常需要不通过物理键盘输入,虽然微软提供了也一个软键盘,但这个软件盘不能定制界面不能自动感应当前光标是否处于输入状态,所以有时候我们还是需要自己来实现这个软键盘。本文将讲解自己实现软键盘时涉及到的几个关键技术。
如上图所示,虽然软键盘在记事本的前面,但光标仍然在记事本上。
要实现这个技术,我们必须要把当前窗体设置为浮动工具条才行。这里我给出 C# Winform 的实现方法:
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
如上代码就是将 Winform 指定为浮动工具条窗体。只要在winform 的类中重载 CreateParams 函数,并按上述代码编写就可以了。
要实现这个功能,我们能想到的最直接的方法是 windows 是否会在当前处于输入状态下时发一个什么事件,或者通过什么钩子程序来实现。但我研究了很久,没有找到这种方法。如果哪位知道这种方法,不妨在回复中告诉我。
我目前找到的方法是定时询问 windows 的当前窗体是否处于输入状态。
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
如上面代码所示
首先我们通过 GetForegroundWindows API 得到当前窗体的句柄。然后我们再通过 GetGUIThreadInfo 得到当前窗体的一些属性。这些属性在 GUITHREADINFO 中定义
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
上面是 GUITHREADINFO 结构。我们可以通过这个信息得到当前窗体中当前焦点的子窗口句柄,当前获得光标的子窗口句柄,当前正激活的子窗体句柄等等。这里我们只要用到当前获得光标的子窗口句柄,就是 hwndCaret 。如果hwndCaret 不为0,则表示当前窗体处于可输入状态。
相关API函数的 C# 定义如下:
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
System.Windows.Forms.SendKeys.Send
这个函数很简单,而且微软的帮助也很全面了,我这里就不多说了。
另外我们还可以用更加底层的 API 函数来模拟键盘的输入
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
这个函数是 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; } }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
如上代码就是将 Winform 指定为浮动工具条窗体。只要在winform 的类中重载 CreateParams 函数,并按上述代码编写就可以了。
二、如何检测当前处于输入状态
在一些嵌入式设备中,我们没有物理键盘,所有的输入都是通过触摸屏和软键盘输入。那么这个时候,我们必须要做到只有处于输入状态时才弹出软键盘,否则如果软键盘一直在界面上,既不美观也妨碍其他程序的正常使用。要实现这个功能,我们能想到的最直接的方法是 windows 是否会在当前处于输入状态下时发一个什么事件,或者通过什么钩子程序来实现。但我研究了很久,没有找到这种方法。如果哪位知道这种方法,不妨在回复中告诉我。
我目前找到的方法是定时询问 windows 的当前窗体是否处于输入状态。
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; } }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
如上面代码所示
首先我们通过 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; }
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
上面是 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);
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
三、模拟键盘输入
模拟键盘输入比较简单,.Net 提供了一个静态函数来模拟键盘输入System.Windows.Forms.SendKeys.Send
这个函数很简单,而且微软的帮助也很全面了,我这里就不多说了。
另外我们还可以用更加底层的 API 函数来模拟键盘的输入
[DllImport("user32.dll")] static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);
.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
这个函数是 keybd_event,关于这个函数的使用,微软的帮助也写的很清楚,这里也不重述了。
相关文章推荐
- 实现软键盘的几个关键技术(转载)
- C#实现软键盘的几个关键技术介绍
- Windows平台下C++插件系统实现的几个关键技术问题及其解决思路
- Windows平台下C++插件系统实现的几个关键技术问题及其解决思路
- Windows平台下C++插件系统实现的几个关键技术问题及其解决思路
- 自己制作软键盘的几个关键技术解析
- Windows平台下C++插件系统实现的几个关键技术问题及其解决思路
- 自己制作软键盘的几个关键技术解析
- (转)关键技术之单机爬虫的实现(1)---我的名字叫小蛛蛛,虽然我还小,但是我也是只可爱的蜘蛛。
- 负载均衡--大型在线系统实现的关键(上篇)(再谈QQ游戏百万人在线的技术实现)
- 12306是如何实现高流量高并发的关键技术
- 12306是如何实现高流量高并发的关键技术
- 用DotNet做简单的分布式计算的几个关键技术点
- TD-SCDMA网络实现PoC业务的关键技术分析
- 运用@media实现网页自适应中的几个关键分辨率
- 聊聊推送的架构及关键技术实现
- 运用@media实现网页自适应中的几个关键分辨率
- 负载均衡--大型在线系统实现的关键(上篇)(再谈QQ游戏百万人在线的技术实现)
- 从一个实战项目来看一下React Native开发的几个关键技术点
- android实现桌面歌词效果的关键技术点