博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

今天遇到一个问题:我们有一个分页控件,该控件包含一个 ComboBox:cmbPageSize,用以输入 pagesize,再回车后分页跳转,但是没有反应或者就是到了 cmbPageSize_KeyDown 事件的代码中以后,该 keycode 就变成了 Keys.Back, Keys.Numlock 之类的 keycode,而我的程序里有 if (key.code == Keys.Enter) 的判断,这样导致后面程序无法执行。这个问题只发生在控件所在窗体作为 MDI Form 的子窗体显示的情况下,如果直接用 ShowDialog 就不存在这个问题。

后来请教了 Montaque 才解决了问题。解决方案如下:
重写了 ComboBox, 重载 ComboBox 的 ProcessDialogKey,让它总是返回 false.

public class ComboBoxExtend: System.Windows.Forms.ComboBox
 
{
  
public ComboBoxExtend():base()
  
{
  }


  
protected override bool ProcessDialogKey(System.Windows.Forms.Keys keyData )
  
{
   
return false;
  }

 }


 后来一查 ProcessDialogKey 找了这个帖子:http://www.sxsedu.net/sxjky/yy/files/%B0%B4%C9%CF%CF%C2%BC%FC%BB%E1%D4%DA%B8%F7%B8%F6MDI%D7%D3%B4%B0%CC%E5%C0%B4%BB%D8%C7%D0%BB%BB.txt 原来在MDI子窗体中,父窗体会覆盖子窗体的 ProcessDialogKey,

再一查MSDN,发现ComboBox的keyDown事件有这样的说明:
To handle keyboard events only at the form level and not allow 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. In order 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.
也就是说如果想让控件自己处理TAB, RETURN, ESCAPE, and arrow keys的KeyDown 事件,那就得重写IsInputKey, IsInputKey返回是否是TAB, RETURN, ESCAPE, and arrow keys被key down. 所以一般的combobox, textbox都有自己的IsInputKey方法。

追溯到 IsInputKey 方法
This method is called during window message preprocessing to determine whether the given input character should be preprocessed or sent directly to the control. If the IsInputChar method returns true, the specified character is sent directly to the control. However, if the method returns false, the character is preprocessed and only sent to the control if it is not consumed by the preprocessing phase. The preprocessing of a character includes checking whether the character is a mnemonic of another control.

追溯到 ProcessDialogKey  方法
This method is called during message preprocessing to handle dialog characters, such as TAB, RETURN, ESCAPE, and arrow keys. This method is called only if the IsInputKey method indicates that the control is not processing the key. The ProcessDialogKey simply sends the character to the parent's ProcessDialogKey method, or returns false if the control has no parent. The Form class overrides this method to perform actual processing of dialog keys. This method is only called when the control is hosted in a Windows Forms application or as an ActiveX control.

Notes to Inheritors:  When overriding the ProcessDialogKey method in a derived class, a control should return true to indicate that it has processed the key. For keys that are not processed by the control, the result of calling the base class's ProcessDialogChar method should be returned. Controls will seldom, if ever, need to override this method.