C# 快捷鍵 設計

  大家在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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章