再谈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的消息。也就是说你可以将按键的信息广播至整个系统。

该函数定义如下:

VOID keybd_event (BYTE bVk, //VK键值

BYTE bScan, 
//WinCE下通常设为0

DWORD dwFlags, 
//按键状态标示

DWORD dwExtraInfo
//WinCE下通常设为0

);

参数的含义文档上已经做了说明,这里不再赘述。在前面文章用过的例子中可以看到,要模拟一次按键行为,需要调用keybd_event两次(如果是组合按键的话将会是2n次)。第一次是按下键,只需传递一个键值和一个非KEYEVENTF_KEYUP的状态(一般是KEYEVENTF_KEYDOWN)。第二次是传递该键值和KEYEVENTF_KEYUP标志,表示松开按键。这里还有一个常用的状态标志是使用KEYEVENTF_SILENT0x4)标志,表示模拟击键而不产生常规按键时敲击的“嘟”声音。

 

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键“包装”后才能正常使用,其用法如下:

keybd_event(VK_LWIN, 0, KEYEVENTF_SILENT, 0);
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,  00);

keybd_event(
20x830 ,0);

//松开键

keybd_event(VK_SHIFT,
0xAA , KeyUp,  0);

keybd_event(
20x83, KeyUp , 0);

好了,纸上谈兵了一会儿,最后我们来看看代码吧。

 

下面这个很简单的类封装了keybd_event,并提供了一个Sendkey的函数供调用,可以完成上述的所有功能,该类仅仅用到了p/invoke兼容.Net Compact Frame work 1.0到现在的所有版本:

using System.Runtime.InteropServices;



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 Freesc Huang 阅读(5552) 评论(9) 编辑 收藏

评论

#1楼 2008-06-04 17:02 Windie Chai(笑煞天)      

学习一下,对Mobile有些兴趣,呵呵。  回复 引用 查看   

#2楼[楼主] 2008-06-04 17:11 fox23      

@Windie Chai(笑煞天)
欢迎常来交流~
 回复 引用 查看   

#3楼 2008-06-04 18:02 SpadeQ      

不错不错,最近有开始研究wm的冲动,先收藏啦~~~  回复 引用 查看   

#4楼[楼主] 2008-06-04 18:21 fox23      

@SpadeQ
欢迎加入~

 回复 引用 查看   

#5楼 2008-06-04 22:52 BAsil      

支持一下  回复 引用 查看   

#6楼 2008-12-30 19:50 liaoxh[未注册用户]

恩,不知道C++有没对应的代码?

想请问下平时左右软键上的点击按扭,到底是用WM_KEYDOWN,还是用WM_LBUTTONDOWN啊?

另外如何获取软键上显示按钮的句柄?
 回复 引用   

#7楼 2009-02-16 15:42 xpengfee      

请教一下LZ关于锁屏的问题。
使用了您的代码,在Mobile系统里,能正常锁屏
但在WinCE5.0下没有反应?请问这是为什么呢?

另外,弱弱的问一句,GenKeyEvent这个方法是哪来的呀??
 回复 引用 查看   

#8楼[楼主] 2009-02-16 19:00 fox23      

@xpengfee
1.有些键是只在Windows Mobile中被定义的, 请先查看文中给出的MSDN链接
2.GenKeyEvent要自己写的, 如下:
void GenKeyEvent( BYTE bVkCode )
{
keybd_event( bVkCode, 0, KEYEVENTF_SILENT, 0 );
Sleep(100);
keybd_event(bVkCode, 0, KEYEVENTF_SILENT | KEYEVENTF_KEYUP, 0);
}
 回复 引用 查看   

#9楼 2009-02-17 15:05 xpengfee      

感谢LZ的回复!
我又测试了一下,在WinCE5.0下还是没能锁屏(查看MSDN链接,VK_F22在WinCE中有定义)。烦请LZ帮忙解决一下,谢谢!!
 回复 引用 查看   

<2012年2月>
2930311234
567891011
12131415161718
19202122232425
26272829123
45678910

公告

These postings are provided "AS IS" with no warranties
and confer no rights.


Locations of visitors to this page

Blog Keywords
Embedded System,Visual Studio,.Net Framework,.Net Compact Framework,.Net Micro Framework,Windows Mobile,Windows Embedded CE,Emulator,WCF,CLR,Design & Pattern,C/C++,C#,Matlab,Algorithms
昵称:Freesc Huang
园龄:4年11个月
粉丝:32
关注:4

统计

  • 随笔 - 197
  • 文章 - 0
  • 评论 - 840

搜索

 

随笔分类(227)

随笔档案(197)

Blogs

Link

积分与排名

最新评论

阅读排行榜

评论排行榜

推荐排行榜