如何捕捉Arrow在Panel中的CheckBox的KeyDown事件?

本文介绍了解决Windows Mobile应用程序中CheckBox控件无法响应箭头键的问题。通过使用P/Invoke调用GetAsyncKeyState方法,在CheckBox失去焦点时判断用户是否按下箭头键,并手动改变焦点。这种方法适用于.Net CF2环境。
近日,开始做公司Windows Mobile的技术支持给一个项目。在fix bug时遇到一个问题。要求是这样的。
一个Form,嵌入一个Panel,然后再Panel里add 进去几个checkBox控件。然后,当Focus在CheckBox上时,用户会按上下箭头来改变Focus,CheckBox是有一个keydown事件,但是系统不对Arrow这样的事件处理,也就是说,但CLR捕捉到硬件的一个按键后,他把这个按键传给Form,然后,Form再发给Panel,而Panel接受到后直接内化了,就改变了Focus而已,而不发给CheckBox,这样对有如此需求的人来说就很不方便了。
MSDN也对此做了说明:

To handle keyboard events only at the form level and not enable other controls to receive keyboard events, set the KeyPressEventArgs.Handled property in your form's KeyPress event-handling method to true. Certain keys, such as the TAB, RETURN, ESCAPE, and arrow keys are handled by controls automatically. To have these keys raise the KeyDown event, you must override the IsInputKey method in each control on your form. The code for the override of the IsInputKey would need to determine if one of the special keys is pressed and return a value of true.

(MSDN link:ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.NETDEVFX.v20.en/CPref17/html/E_System_Windows_Forms_Control_KeyDown.htm)



没错,你需要override IsInputKey事件,可是这个时间却在.Net CF2中不支持。此路不通!

那么该如何做呢?
通过P/Invoke调用!

我是向来不喜欢C#的,搞来搞去,很多功能还是需要调用WIN32 API。所以,我们就利用LostFocus或者GetFocus事件发生时,
询问键盘键状态。就可以得到是否用户按了Arrow key了。

 [DllImport("Coredll.dll")]
        private static extern short GetAsyncKeyState(int nVirtKey);
       。。。。
        void CheckBoxLostFocus(object sender, EventArgs e)
        {

            senderText = ((CheckBox)sender).Text;
            if (senderText.Equals(firstChoiceText))
            {
                if (GetAsyncKeyState(0x26) < 0)//press up key
                {
                    ((CheckBox)choiceButtons[choiceTextLength - 1]).Focus();
                }
            }
            if(senderText.Equals(finalChoiceText))
            {
                if(GetAsyncKeyState(0x28)<0)//press down key
                {
                    ((CheckBox)choiceButtons[0]).Focus();
                }
            }
        }
这样就实现了Panel中的CheckBox的KeyDown事件中捕捉Arrow。类似的,你也可以捕捉Tab,Enter键。

在`MyListCtrl`中,为了绑定复选框(CheckBox)的点击事件,你需要在`OnPaint`方法内设置鼠标点击事件处理器,并在相应的函数中检查被点击的位置是否对应于一个复选框项。这里假设你已经在列中绘制了复选框: ```python def OnPaint(self, event): dc = wx.PaintDC(self) # 先正常绘制ListCtrl的内容 super(MyListCtrl, self).OnPaint(event) # 获取当前画布的大小 rect = self.GetClientRect() # 循环遍历所有项,检查点击位置 for index, (item_text, _) in enumerate(self.items): checkbox_rect = self.GetItemRect(index)[1] # 获取复选框区域 if checkbox_rect.Contains(event.Position): # 如果点击在复选框内 self.ProcessEvent(wx.CommandEvent(wx.wxEVT_COMMAND_LIST_ITEM_ACTIVATED, self.GetId(), index)) # 触发激活事件 break # 只处理第一个匹配的项 # 在窗体初始化时注册这个事件处理器 self.Bind(wx.EVT_PAINT, self.OnPaint) self.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown) # 捕获鼠标左键点击事件 def OnLeftDown(self, event): x, y = event.GetPositionTuple() for index, (_, checkbox_state) in enumerate(self.items): checkbox_rect = self.GetItemRect(index)[1] # 再次获取复选框区域 if checkbox_rect.Contains((x, y)): self.SetCheckboxState(index, not checkbox_state) # 更新复选框状态 break ``` 在这个例子中,`ProcessEvent`模拟了当用户点击复选框时通常会发生的行为,而`OnLeftDown`函数则会更新复选框的状态。记得替换`path_to_checkbox_on.png`和`path_to_checkbox_off.png`为实际的图片路径。同时,你可能还需要根据应用需求修改具体的事件处理逻辑。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值