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("命令執行!"); }