最近做了一個登入視窗,其中WindowStyle="None",隱藏了視窗的標題列。但是當用alt+space快速鍵的時候,系統功能表還是會彈出來。最後在網上找到了屏蔽的方法。
主要是調用API函數實現,GetSystemMenu用來取得系統功能表,GetMenuItemCount得到菜單的個數,而後用RemoveMenu把功能表項目一一刪掉。
using System.Windows.Interop;<br />using System.Runtime.InteropServices;</p><p>namespace WpfApplication1<br />{</p><p> public partial class LogonWindow : Window<br /> {<br /> [DllImport("user32.dll", EntryPoint = "GetSystemMenu")]<br /> private static extern IntPtr GetSystemMenu(IntPtr hwnd, int revert);<br /> [DllImport("user32.dll", EntryPoint = "RemoveMenu")]<br /> private static extern int RemoveMenu(IntPtr hmenu, int npos, int wflags);<br /> [DllImport("user32.dll", EntryPoint = "GetMenuItemCount")]<br /> private static extern int GetMenuItemCount(IntPtr hmenu);</p><p> private const int MF_BYPOSITION = 0x0400;<br /> private const int MF_DISABLED = 0x0002;</p><p> public LogonWindow()<br /> {<br /> InitializeComponent();<br /> SourceInitialized += new EventHandler(LogonWindow_SourceInitialized);<br /> }</p><p> void LogonWindow_SourceInitialized(object sender, EventArgs e)<br /> {<br /> IntPtr handle = new WindowInteropHelper(this).Handle;<br /> IntPtr hmenu = GetSystemMenu(handle, 0);<br /> int cnt = GetMenuItemCount(hmenu);<br /> for (int i = cnt - 1; i >= 0; i--)<br /> {<br /> RemoveMenu(hmenu, i, MF_DISABLED | MF_BYPOSITION);<br /> }<br /> }</p><p> }<br />}
後來發現實際上我的這個視窗還在工作列上顯示,在工作列上點右鍵畢竟不影響視窗的美觀,所以是否顯示系統菜單無所謂,用上面的代碼程式啟動速度變慢了。於是我想到直接屏蔽Alt+space鍵更好。
在winform裡面,有一個keypreview屬性可以讓視窗首先接受訊息,或者IMessageFilter提前處理訊息。在wpf的window裡面沒這些東西了,但是可以用PreviewKeyDown事件來完成。
其次,在屏蔽alt+F4的時候開始是這樣寫的:
if ((Keyboard.Modifiers == ModifierKeys.Alt) &&e.Key== Key.Space)
如果是Ctrl+Space還好說,或者Ctrl+A之類的,但是點擊Alt鍵之後,鍵盤的訊息交給了系統,所以上面的e.Key是System,而不是Space。
百度,google了一陣子沒發現解決方案,由於e是KeyEventArgs參數,於是想看看下面還有什麼東西,輸入e.後,代碼提示有一個SystemKey屬性,經過實驗,發現居然可以。於是到MSDN上看了一下解釋:
Gets the keyboard key referenced by the event, if the key will be processed by the system.
如果這個key將要被系統處理,得到這個key。
靠,終於把問題解決了!