再谈Windows Mobile上的模拟按键操作
再谈Windows Mobile上的模拟按键操作
摘要:本文总结了如何在Windows Mobile上实现模拟按键的操作,并阐述了通过模拟按键我们可以实现的种种有意义的应用。
Keywords
Windows Mobile, keybd_event, .Net Compact Framework, keystroke
Windows CE /Windows Mobile的键盘消息处理方式和桌面版本的Windows大体相同。当一个键被按下的时候,OS会发送一系列的消息给焦点窗体。通常首先是一个WM_KEYDOWN消息,如果按下的键代表的是一个字符或者数字,Windows会接着发送一个WM_CHAR的消息。当键被释放(松开)的时候,Windows会发送一个WM_KEYUP的消息。如果一个键被一直按着到足够长的时间(足以被OS认定为自动重复模式),则会在释放前重复发送WM_KEYDOWN和WM_CHAR的消息。
Tips一些功能键和鼠标键是不代表任何字符和数字的,这时需要在按键时由程序截获WM_KEYDOWN消息来获知按键信息。当然,目前对于Windows Mobile的大部分设备,并没有鼠标键和诸多功能键的实现。此外,当Alt键被按住的时候,如果有其他键被按下,则前面提到的消息分别会是:WM_SYSKEYDOWN, WM_SYSCHAR和WM_SYSKEYUP。
之前的一些随笔中曾用到过在Windows Mobile如何实现模拟按键的方法,比如:
http://www.cnblogs.com/fox23/archive/2008/02/19/1069059.html
http://www.cnblogs.com/fox23/archive/2008/04/27/windowsmobile-compactframework-speaker-csharp.html
现在可以来总结一下在Windows Mobile上面模拟按键是一件多么有趣的事情了。
在前面的两篇文章里面都提到了keybd_event这个函数,在Windows CE SDK中我们可以找到它,从文档中可以看到这个函数能产生WM_KEYUP 或 WM_KEYDOWN的消息。也就是说你可以将按键的信息广播至整个系统。
该函数定义如下:
BYTE bScan, //WinCE下通常设为0
DWORD dwFlags, //按键状态标示
DWORD dwExtraInfo//WinCE下通常设为0
);
参数的含义文档上已经做了说明,这里不再赘述。在前面文章用过的例子中可以看到,要模拟一次按键行为,需要调用keybd_event两次(如果是组合按键的话将会是2n次)。第一次是按下键,只需传递一个键值和一个非KEYEVENTF_KEYUP的状态(一般是KEYEVENTF_KEYDOWN)。第二次是传递该键值和KEYEVENTF_KEYUP标志,表示松开按键。这里还有一个常用的状态标志是使用KEYEVENTF_SILENT(0x4)标志,表示模拟击键而不产生常规按键时敲击的“嘟”声音。
Tips 关于Windows Mobile/Windows CE常见的VK键值表可以参考:
http://www.cnblogs.com/fox23/archive/2008/02/01/1061906.html
http://msdn.microsoft.com/en-us/library/ms927178.aspx
http://msdn.microsoft.com/en-us/library/bb431750.aspx
以下是使用模拟按键的一些有趣示例:
1. 将应用程序放置到后台
在 SmartPhone上面有时候我们也想实现在PPC上面一样的最小化功能,可惜SmartPhone的Form上没有那个“X”可以点击。所以,你想把程序挪到后台的话就得按下回退键(通常是红色的)。我们可以通过在程序中模拟按键的方式来实现。你需要做的只是把VK_ESC 键(0x1B)送给 keybd_event。
2. 在程序中调用今日屏幕(Today Screen)
实际上就是模拟按下”Home”键。对应的键是VK_F4,对应的键值是0x73。
3. 锁定键盘
如果你想锁定你的设备,就像它待机一定时间之后做的一样,你同样可以通过模拟按键的方式来实现。在Smartphone上面你需要使用VK_APP6 键(0xC6)。在Pocket PC上面需要用VK_F22或者VK_KEYLOCK键(键值均为0x85)。
在Windows Mobile 6.0及其以后的设备上要方便一些,直接可以使用API 函数SHDeviceLockAndPrompt来实现锁和解锁的状态切换。
Tips VK_APP系列键并没有在Windows Embedded CE中定义,是Windows Mobile特有的。VK_APP键只有在被VK_LWIN键“包装”后才能正常使用,其用法如下:
GenKeyEvent(VK_APP6);
keybd_event(VK_LWIN, 0, KEYEVENTF_SILENT | KEYEVENTF_KEYUP, 0);
4. 防止设备进入休眠或者锁住的状态
当你在浏览网页或者看电子书的时候,尤其是如果你的显示屏比较大,当你正看得欢的时候突然屏幕被锁住了,这的确是一件令人郁闷的事。好在你可以通过模拟按键来避免这种情况发生,有按键的行为发生相当于告知了你的设备你你还在忙,你还需要它工作。不过我们应该模拟按下哪个键呢?按下哪个键可以不影响用户的使用,不影响用户的输入呢?显然,模拟数字,字符或者常见键盘操作键都似不可取的。如果你认为可以是shift或者caps-lock之类的,那就更不对了。因为一旦你模拟的按键是它们的话很可能你在程序中的输入会变成“lIkE tHiS”大小写不一。好在我们可以在VK表中找到这样一个键: VK_NONAME (0xFC)。他是一个不做任何实质性操作的保留键,也就是我们想要的。
5. 关闭设备
恩,没想到阿没想到,还可以模拟按键来关闭设备。只需要模拟按下VK_OFF (0xDF)就可以在SmartPhone上面实现软启动,在Pocket PC上面实现关闭屏幕。
(关于编程重启Windows Mobile设备可以参考老马的文章:http://blog.csdn.net/aawolf/archive/2008/02/07/2086199.aspx)
6.打开扬声器
这是我之前的文章中用到的,你只需要发送VK_F16 键(0x7F)的按键消息即可。
7. 组合按键
组合按键无非是先按下一些键,再松开一些键,下面的例子演示了如何按下shift+2组合键:
keybd_event(VK_SHIFT, 0xAA, 0, 0);
keybd_event(2, 0x83, 0 ,0);
//松开键
keybd_event(VK_SHIFT,0xAA , KeyUp, 0);
keybd_event(2, 0x83, KeyUp , 0);
好了,纸上谈兵了一会儿,最后我们来看看代码吧。
下面这个很简单的类封装了keybd_event,并提供了一个Sendkey的函数供调用,可以完成上述的所有功能,该类仅仅用到了p/invoke兼容.Net Compact Frame work 1.0到现在的所有版本:
public class SystemCalls
{
//更多按键请参考 http://msdn2.microsoft.com/en-us/library/ms927178.aspx
public const byte VK_NONAME = 0xFC; // 什么也不做
public const byte VK_ESC = 0x1B; // Smartphone的回退键
public const byte VK_F4 = 0x73; // Home Screen
public const byte VK_APP6 = 0xC6; // Smartphone上锁定键盘
public const byte VK_F22 = 0x85; // PocketPC上锁定键盘 (VK_KEYLOCK)
public const byte VK_F16 = 0x7F; // 出发扬声器
public const byte VK_OFF = 0x7F; //电源键
/// <summary>
/// 将按键送至全局键盘缓冲区
/// </summary>
/// <param name="key"></param>
public static void SendKey(byte key)
{
//const byte KEYEVENTF_SILENT = 0x0004;
const int KEYEVENTF_KEYUP = 0x02;
const int KEYEVENTF_KEYDOWN = 0x00;
keybd_event(key, 0, KEYEVENTF_KEYDOWN, 0);
keybd_event(key, 0, KEYEVENTF_KEYUP, 0);
}
[DllImport("coredll", SetLastError = true)]
private static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
}
使用方法:
SystemCalls.SendKey(SystemCalls.VK_F22);
Enjoy it!
黄季冬<fox23>
纠正:VK_OFF应为0xDF
posted on 2008-06-04 16:12 J.D Huang 阅读(8392) 评论(9) 编辑 收藏 举报