C# 快捷键 设计

来源:互联网 发布:长宁区新虹桥小学 知乎 编辑:程序博客网 时间:2024/04/27 18:59

  大家在C#编程过程中,可能需要特殊的快捷键,比如我按A键就需要处理A键的相应处理方法,大家会想到使用Form中的有关键建按下的消息进行过滤,比如下面的程序:  

private   void  Form1_KeyDown( object  sender, KeyEventArgs e)  
{  
if  (Keys.A == e.KeyCode)  
   {  
       MessageBox.Show( "A" );  
   }  
}  
 private void Form1_KeyDown(object sender, KeyEventArgs e) { if (Keys.A == e.KeyCode) { MessageBox.Show("A"); } }

仅仅这样做是不行的,比如我我们的窗体有有控件并且有控件的焦点,我们还必须设置窗体属性 KeyPreview ==true才行。这样就可以解决了我们快捷键A的问题。

这样做很好的解决方案,不过我们的快捷键,做这个东西并不是这么的简单,例如我们给Button做个快捷键,那么我们就必须把程序控制代码放在主窗体中,这样做出的程序的结构都是不是很舒服。因此我们必须 想方法处理这个问题。

如果把处理快捷键消息放在各个控件之中的话,这样我们的程序就是很有简洁性,比如我们可以创建一个快捷键管理的类。我们可以使用一个委托定义,并写一个累来触发他。  

public   delegate   void  KeyDown(Keys key);  
public   static   class  KeyManager  
{  
public   static  KeyDown KeyDownEventHandler;  
}  
 public delegate void KeyDown(Keys key); public static class KeyManager { public static KeyDown KeyDownEventHandler; }

然后在主窗体中KeyDown事件中调用委托就行了  

private   void  Form1_KeyDown( object  sender, KeyEventArgs e)  
{  
if  (KeyManager.KeyDownEventHandler !=  null )  
   {  
       KeyManager.KeyDownEventHandler(e.KeyCode);  
   }  
}  
private void Form1_KeyDown(object sender, KeyEventArgs e){ if (KeyManager.KeyDownEventHandler != null) { KeyManager.KeyDownEventHandler(e.KeyCode); }}

  然后我们在各自的自定义控件中调用使用这个委托,由于委托是多播的形式,就不用害怕。  

public  partial  class  UserControl1 : UserControl  
{  
public  UserControl1()  
  {  
     InitializeComponent();  
     KeyManager.KeyDownEventHandler +=  new  KeyDown(KeyDowTest);  
  }  
  
void  KeyDowTest(Keys key)  
  {  
     MessageBox.Show(key.ToString());  
  }  
}  
public partial class UserControl1 : UserControl{ public UserControl1() { InitializeComponent(); KeyManager.KeyDownEventHandler += new KeyDown(KeyDowTest); } void KeyDowTest(Keys key) { MessageBox.Show(key.ToString()); }}

这样就完成了快捷键基本功能的设计,比如我们可能还需要对委托调用需要更好的控制,我们可以使集合来处理他。当然我们也可以使用事件的处理方式。 

public   delegate   void  KeyDown(KeyEventArgs e);  
public   static   class  KeyManager  
{  
static  List<KeyDown> list =  new  List<KeyDown>();  
private   static   event  KeyDown keyDownEventHandler;  
  
public   static   event  KeyDown KeyDownEventHandler  
   {  
       add { list.Add(value);}  
       remove { list.Remove(value); }  
   }  
  
public   static   void  KeyDown(KeyEventArgs e)  
   {  
if (list.Count > 0)  
      {  
foreach  (KeyDown keydown  in  list)  
         {  
if (e.Handled)   
            {  
return ;  
            }  
            keydown(e);  
         }  
       }  
    }  
}  
public delegate void KeyDown(KeyEventArgs e);public static class KeyManager{ static List<KeyDown> list = new List<KeyDown>(); private static event KeyDown keyDownEventHandler; public static event KeyDown KeyDownEventHandler { add { list.Add(value);} remove { list.Remove(value); } } public static void KeyDown(KeyEventArgs e) { if(list.Count > 0) { foreach (KeyDown keydown in list) { if(e.Handled)  { return; } keydown(e); } } }}

这样我们就可以通过list循环来控制是否需要执行下去。

      

   


在上一次我们了解到使用委托实现的威力,在我们这样做时,还不是多么好,还是存在耦合性,我们只不过把耦合性推到快捷键管理类中。所以我们我能不能使用更为简单的方法来实现快捷键,当然可以在.net中我们可以使用Application.AddMessageFilter(IMessageFilter filter)方法来增加一个线程消息过滤。这个接口只有一个方法,这个函数返回值为true标示不再交给其他处理程序处理,不要随便返回true,需要小心使用!!!!!!。  

public   class  MG : IMessageFilter  
{
    #region IMessageFilter 成员   
  
public   bool  PreFilterMessage( ref  Message m)  
    {  
int  keyDown = 0x100;  
if  (m.Msg == keyDown)  
        {  
            MessageBox.Show(((Keys)m.WParam).ToString());  
return   true ;  
        }  
return   false ;  
    }

    #endregion   
}  
 public class MG : IMessageFilter { #region IMessageFilter 成员 public bool PreFilterMessage(ref Message m) { int keyDown = 0x100; if (m.Msg == keyDown) { MessageBox.Show(((Keys)m.WParam).ToString()); return true; } return false; } #endregion }

然后我们在我们控件使用,这样我们就可以在控件中就实现了快捷键。  

public  partial  class  UserControl1 : UserControl  
   {  
public  UserControl1()  
       {  
           InitializeComponent();  
           Application.AddMessageFilter( new  MG());  
       }  
    }  
 public partial class UserControl1 : UserControl { public UserControl1() { InitializeComponent(); Application.AddMessageFilter(new MG()); } }

这里有个Message类型的参数,这个是windows消息参数,具体的内容可以查看window消息循环机制,这些消息都定义在WinUser.h头文件中 ,以WM_开头,下面是部分C++定义  

#define WM_KEYFIRST                     0x0100   
#define WM_KEYDOWN                      0x0100   
#define WM_KEYUP                        0x0101   
#define WM_CHAR                         0x0102   
#define WM_DEADCHAR                     0x0103   
#define WM_SYSKEYDOWN                   0x0104   
#define WM_SYSKEYUP                     0x0105   
#define WM_SYSCHAR                      0x0106   
#define WM_SYSDEADCHAR                  0x0107   
#if(_WIN32_WINNT >= 0x0501)   
#define WM_UNICHAR                      0x0109   
#define WM_KEYLAST                      0x0109   
#define UNICODE_NOCHAR                  0xFFFF   
#define WM_KEYFIRST 0x0100#define WM_KEYDOWN 0x0100#define WM_KEYUP 0x0101#define WM_CHAR 0x0102#define WM_DEADCHAR 0x0103#define WM_SYSKEYDOWN 0x0104#define WM_SYSKEYUP 0x0105#define WM_SYSCHAR 0x0106#define WM_SYSDEADCHAR 0x0107#if(_WIN32_WINNT >= 0x0501)#define WM_UNICHAR 0x0109#define WM_KEYLAST 0x0109#define UNICODE_NOCHAR 0xFFFF

另外,我们还应知道虚拟键码,大家可以参考windows程序设计这本电子书,进行消息拦截 


本文来自CSDN博客,转载请标明出处:http://blog.chinaunix.net/u2/69195/showart_2149928.html