如果想PPC截获硬件按钮事件,需要以下几步:
1. 组合键常量和硬件按键常量。它们配合上面的api使用。
2. 几个api函数,这些api函数可以注册热键到你的应用中,它们是:RegisterHotKey,UnregisterHotKey,UnregisterFunc1(据说这个是未公开的接口函数)它们都在”coredll.dll”中,它们的参数和用法在以下的例子中说明。
3. 有了以上的准备,最后一步就要重写应用主窗体的消息循环函数wndproc,截获WM_HOTKEY消息。
为了重用,我们都以类的方式提供,代码及说明如下:
//第一步常量类,声明virsual key 的组合键常量
public class KeyModifers
{
public const uint MOD_ALT = 0x1;
public const uint MOD_CONTROL = 0x2;
public const uint MOD_SHIFT = 0x4;
public const uint MOD_WIN = 0x8;
}
//声明硬件按键常量 只能是这几个值
public class KeysHardware
{
public const uint Hardware1 = 193;
public const uint Hardware2 = 194;
public const uint Hardware3 = 195;
public const uint Hardware4 = 196;
public const uint Hardware5 = 197;
}
<?XML:NAMESPACE PREFIX = O />
//第二步,封装两个api函数,调用非托管dll函数类
public class RegisterHotKeys
{
//声明aapi
[DllImport("coredll.dll")]
private static extern bool UnregisterFunc1(
uint fsModifiers, //组合键的键值
uint vk //热键键值
);
[DllImport("coredll.dll")]
private static extern bool RegisterHotKey(
IntPtr hWnd, //要注册的窗体的句柄
int id, // 热键的键值
uint fsModifiers, //组合键的键值
uint vk // virtual-key code (虚拟键的编码,这里和第二个参数一样)
);
[DllImport("coredll.dll")]
private static extern bool UnregisterHotKey(
IntPtr hWnd, //要注册的窗体的句柄
int id //热键的键值
);
//end
//注册热键,封装了UnregisterFunc1和RegisterHotKey
private static bool _mRegisterHotKey(IntPtr hwnd, int id, uint vk)
{
bool re = UnregisterFunc1(KeyModifers.MOD_WIN, vk);
bool re1 = RegisterHotKey(hwnd, id, KeyModifers.MOD_WIN, vk);
return re && re1;
}
public static bool RegisterHotKey(IntPtr hwnd)
{
bool re = true;
for (int i = (int)KeysHardware.Hardware1; i <= (int)KeysHardware.Hardware5; i++)
{
re = _mRegisterHotKey(hwnd, i, (uint)i);
if (!re) break;
}
return re;
}
public static bool UnRegisterHotKey(IntPtr hwnd)
{
bool re = true;
for (int i = (int)KeysHardware.Hardware1; i <= (int)KeysHardware.Hardware5; i++)
{
UnregisterHotKey(hwnd, i);
if (!re) break;
}
return re;
}
}//大家可以看到这个类只有两个public函数,其他的函数对外不提供,为内部服务
//第三步重写消息循环,定义消息窗体,并重写wndproc方法
public class MyMsgWindow : MessageWindow
{
public const int WM_HOTKEY = 0x0312;
private TestForm form = null; //TestForm为你的热键要注册的应用主窗体
public MyMsgWindow(TestForm form)
{
this.form = form;
}
protected override void WndProc(ref Message msg)
{
switch (msg.Msg)
{
case WM_HOTKEY:
form.clickHardWareButton(msg.WParam.ToInt32());//clickHardWareButton是你在主窗体中定义的按钮事件函数,在这里被调用
return;
}
base.WndProc(ref msg);
}
}
我的事例中主窗体为TestForm,它是怎么和MessageWindow关联的呢?很简单,在TestForm的构造函数中这样写:
public class TestForm : System.Windows.Forms.Form
{
public TestForm()
{
InitializeComponent();
//以下是我添加的代码
mmw = new MyMsgWindow(this);//主窗体被传入MessageWindow中,主窗体中的
//消息循环按照新的消息循环执行
if (!RegisterHotKeys.RegisterHotKey(mmw.Hwnd))
MessageBox.Show("register hot key error");
}
public void clickHardWareButton(int value)//消息循环执行的函数
{
if ((value >= 0xc1) && (value <= 0xcf))
{
MessageBox.Show(value.ToString());
}
}
//窗体关闭时,卸载注册的热键
Private void TestForm_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
RegisterHotKeys.UnRegisterHotKey1(mmw.Hwnd);
}
……
}
这样在PPC中就能够将硬件按键事件注册到应用的主窗体中,执行自己需要的逻辑。终于写完了,不知道是否有用,是否说清楚了,如果有不明欢迎骚扰!
-
#
wuyazhe 发表于2008-06-20 23:31:40 IP: 58.248.7.*
-
你好。这样做确实是可以实现效果。但显然不是最好办法。当然我也没更好办法。
对于快捷键。我的想法是自己做快捷键类。我就是都添加keyup,事件。递归父类子类,但是效果。貌似有些地方不可以用。打算用RegistHotkey。是这个大家都想的到。但是不知道如何捕获消息。wince下不支持IMessageFilter这个接口。你用的这个MessageWindow虽然也可以。但多少感觉这样会多一个window。这都不是主要的。最重要的是需要添加Microsoft.WindowsCE.Forms这个引用。添加了这个引用的就不可以在pc上用了。我自己的程序,都写成:
public static void Postmessage(...)
{
if(Envirment.OsVersion.PlatformID == PlatForm.Wince)
{
PostMessageCE(...);
}
else
{
PostMessagePC(...);
}
[...coredll.dll]
public extern void PostMessageCE(...)
[kernal32.dll]
public extern void PostMessagePC(...)
}
这样的。
我就希望可以写一次程序,在wince,pc上都可以运行的。所以,我不想用那个dll。
那么,我的选择就是2个,
1.用键盘钩子
2.自己重写Application.Run方法,也就是重写Application类。
方法1因为麻烦点。还没尝试。方法2是没弄成功。可以启动。但不能结束。诶。。。。
呵呵。有兴趣的话。交流一下啊。我的email:wuyazhe@yeah.net
QQ:32610303
对了。请注明:ppc 同行