1. 程式人生 > >WPFの三種方式實現快捷鍵

WPFの三種方式實現快捷鍵

原文: WPFの三種方式實現快捷鍵

最近,對wpf新增快捷鍵的方式進行了整理。主要用到的三種方式如下:

一、wpf命令:

資源中新增命令
<Window.Resources>
        <RoutedUICommand x:Key="ToolCapClick" Text="截圖快捷鍵" />
</Window.Resources>

輸入命令繫結
<Window.InputBindings>
        <KeyBinding Gesture="Ctrl+Alt+Q" Command="{StaticResource ToolCapClick}"/>
</Window.InputBindings>

命令執行方法繫結
<Window.CommandBindings>
        <CommandBinding Command="{StaticResource ToolCapClick}"
                    CanExecute="CommandBinding_ToolCapClick_CanExecute"
                    Executed="CommandBinding_ToolCapClick_Executed"/>
</Window.CommandBindings>

 需要注意的是,繫結命令的時候,也可以<KeyBinding Modifiers="Ctrl+Alt" Key="Q" Command="{StaticResource ToolCapClick}"/>,建議用前者,以免造成混亂。

執行方法實現

  #region 截圖快捷鍵
        private void CommandBinding_ToolCapClick_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

        private void CommandBinding_ToolCapClick_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            try
            {
                CaptureImageTool capture = new CaptureImageTool();
                capture.CapOverToHandWriting += Capture_CapOverToHandWriting;
                capture.CapOverToBlackboard += Capture_CapOverToBlackboard;
                string saveName = String.Empty;
                if (capture.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {

                    //儲存擷取的內容
                    System.Drawing.Image capImage = capture.Image;
                    //上課存班級內部,不上課存外部
                    string strSavePath = DataBusiness.GetCurrentTeachFilePath(SystemConstant.PATH_CAPS);
                    if (!String.IsNullOrEmpty(strSavePath))
                    {
                        if (!Directory.Exists(strSavePath))
                        {
                            Directory.CreateDirectory(strSavePath);
                        }
                        saveName = strSavePath + DateTime.Now.ToString(SystemConstant.FORMAT_CAPS);
                    }
                    else
                    {

                        saveName = PathExecute.GetPathFile(SystemConstant.PATH_SAVE + Path.DirectorySeparatorChar + SystemConstant.PATH_CAPS, DateTime.Now.ToString(SystemConstant.FORMAT_CAPS));
                    }

                    capImage.Save(saveName + SystemConstant.EXTENSION_PNG, System.Drawing.Imaging.ImageFormat.Png);
                }
            }
            catch (Exception ex)
            {
                new Exception("capscreen module error:" + ex.Message);
            }
        }

 二、利用windows鉤子(hook)函式

第一步 引入到Winows API

   1: [DllImport("user32.dll")]
    
   2: public static extern bool RegisterHotKey(IntPtr hWnd, int id, uint fsModifiers, uint vk);
    
   3: [DllImport("user32.dll")]
    
   4: public static extern bool UnregisterHotKey(IntPtr hWnd, int id);

這邊可以參考兩個MSDN的連結

第一個是關於RegisterHotKey函式的,裡面有關於id,fsModifiers和vk 的具體說明

http://msdn.microsoft.com/en-us/library/windows/desktop/ms646309%28v=vs.85%29.aspx

第二個是Virtual-Key 的表,即RegisterHotKey的最後一個引數

http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx

第二步 註冊全域性按鍵

 

這裡先介紹一個窗體的事件SourceInitialized,這個時間發生在WPF窗體的資源初始化完畢,並且可以通過WindowInteropHelper獲得該窗體的控制代碼用來與Win32互動。

具體可以參考MSDN http://msdn.microsoft.com/en-us/library/system.windows.window.sourceinitialized.aspx

我們通過過載OnSourceInitialized來在SourceInitialized事件發生後獲取窗體的控制代碼,並且註冊全域性快捷鍵

 private const Int32 MY_HOTKEYID = 0x9999;
 protected override void OnSourceInitialized(EventArgs e)
 {
     base.OnSourceInitialized(e);
     IntPtr handle = new WindowInteropHelper(this).Handle;
    RegisterHotKey(handle, MY_HOTKEYID, 0x0001, 0x72);
 }

 

關於幾個常熟的解釋

MY_HOTKEYID 是一個自定義的ID,取值範圍在0x0000 到 0xBFFF。之後我們會根據這個值來判斷事件的處理。

RegisterHotKey的第三或第四個引數可以參考第一步

第三步 新增接收所有視窗訊息的事件處理程式

上面只是在系統中註冊了快捷鍵,但是還要獲取訊息的事件,並篩選訊息。

繼續在OnSourceInitialized函式中操作

 protected override void OnSourceInitialized(EventArgs e)
 {
     base.OnSourceInitialized(e);
 
     IntPtr handle = new WindowInteropHelper(this).Handle;
    RegisterHotKey(handle, MY_HOTKEYID, 0x0001, 0x72);
 
     HwndSource source = PresentationSource.FromVisual(this) as HwndSource;
    source.AddHook(WndProc);
 }

 

下面來完成WndProc函式

 IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handle)
 {
    //Debug.WriteLine("hwnd:{0},msg:{1},wParam:{2},lParam{3}:,handle:{4}"
     //                ,hwnd,msg,wParam,lParam,handle);
    if(wParam.ToInt32() == MY_HOTKEYID)
    {
        //全域性快捷鍵要執行的命令
     }
    return IntPtr.Zero;
 }

 三、給button控制元件新增快捷鍵

<UserControl.Resources>
 <RoutedUICommand x:Key="ClickCommand" Text="點選快捷鍵" />
</UserControl.Resources>

<UserControl.CommandBindings>
    <CommandBinding Command="{StaticResource ClickCommand}" 
                    Executed="ClickHandler" />
</UserControl.CommandBindings>

<UserControl.InputBindings>
    <KeyBinding Key="C" Modifiers="Ctrl" Command="{StaticResource ClickCommand}" />
</UserControl.InputBindings>

<Grid>
    <Button Content="button" Command="{StaticResource ClickCommand}"/>
</Grid>

 執行方法:

private void ClickHandler(object sender, RoutedEventArgs e) 
{
 Message.Show("命令執行!");
 }