在WPF程式開發中,我們常常會發現預設的視窗標題列過於不合適,而想修改其樣式。有不少辦法可以達到這一目的,但往往都不那麼容易。而最簡單的方法就是,直接不要預設的標題列,轉而在表單內部重新製作一個,這樣就可以充分使用我們所熟知的WPF的開發方式。不過,這樣一來又有一個問題,即類比的標題列畢竟不是真正的標題列,按住它無法拖動視窗,也無法雙擊最大化。Aland Li提供了一個好辦法解決這一問題。
Windows使用WM_NCHITTEST視窗訊息來判斷滑鼠的位置的類型,比如是否是標題列,我們可以捕獲這個訊息,然後檢查滑鼠的座標,如果在我們所設計的標題列內,我們就告訴系統這個位置在標題列上(返回HTCAPTION(2))。下面是詳細代碼:
private void Window_Loaded(object sender, RoutedEventArgs e){ // 添加一個訊息過濾器 IntPtr hwnd = new WindowInteropHelper(this).Handle; HwndSource.FromHwnd(hwnd).AddHook(new HwndSourceHook(WndProc));}private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam,
ref bool handled){ if(msg == WM_NCHITTEST) { // 擷取螢幕座標 Point p = new Point(); int pInt = lParam.ToInt32(); p.X = (pInt << 16) >> 16; p.Y = pInt >> 16; if(isOnTitleBar(PointFromScreen(p))) { // 欺騙系統滑鼠在標題列上 handled = true; return new IntPtr(2); } } return IntPtr.Zero;}private bool isOnTitleBar(Point p){ // 假設標題列在0和100之間 if(p.Y >= 0 && p.Y < 100) return true; else return false;}private const int WM_NCHITTEST = 0x0084;
如此,只要點擊視窗上方0-100的地區,便可以拖動視窗,也可以雙擊視窗進行最大化了。
而要去掉預設的標題列,只需要將WindowStyle設為None即可。
BTW,其實並不一定要WPF才行吧,這個方法同時也適用於Winform,不過一般WPF程式更有美化標題列的需求而已。