首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

WPF 視窗最大化遮蓋工作列問題的完美解決方案

     編輯:關於.NET

在 WPF 開發中,當視窗樣式設為 WindowStyle=None(自訂標題列、無邊框)並最大化時,視窗會佔滿整個螢幕並遮蓋 Windows 工作列,這違反使用者體驗慣例。本文提供一個成熟、可直接復用的靜態工具類 FullScreenManager,透過攔截 WM_GETMINMAXINFO (0x0024) 視窗訊息,精確計算工作區域並修正最大化尺寸與位置。

問題根因

WPF 預設最大化邏輯以螢幕解析度為準,忽略工作列佔用的區域。當 WindowStyle=None 時,系統不再自動處理工作列避讓,導致視窗覆蓋任務列。

核心解決邏輯

掛鉤 HwndSource 的 WindowProc,攔截 WM_GETMINMAXINFO 訊息:

private static IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) {
    switch (msg) {
        case 0x0024: // WM_GETMINMAXINFO
            WmGetMinMaxInfo(hwnd, lParam);
            handled = true;
            break;
    }
    return IntPtr.Zero;
}

精確計算工作區域

呼叫 Win32 API 取得監視器資訊,將最大化位置與尺寸限制在工作區域(排除工作列):

private static void WmGetMinMaxInfo(IntPtr hwnd, IntPtr lParam) {
    var mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO));
    int MONITOR_DEFAULTTONEAREST = 0x00000002;
    IntPtr monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
    if (monitor != IntPtr.Zero) {
        var monitorInfo = new MONITORINFO();
        GetMonitorInfo(monitor, monitorInfo);
        RECT rcWork = monitorInfo.rcWork;      // 工作區域(不含工作列)
        RECT rcMonitor = monitorInfo.rcMonitor; // 整個監視器區域
        mmi.ptMaxPosition.x = Math.Abs(rcWork.left - rcMonitor.left);
        mmi.ptMaxPosition.y = Math.Abs(rcWork.top - rcMonitor.top);
        mmi.ptMaxSize.x = Math.Abs(rcWork.right - rcWork.left);
        mmi.ptMaxSize.y = Math.Abs(rcWork.bottom - rcWork.top);
    }
    Marshal.StructureToPtr(mmi, lParam, true);
}

完整 P/Invoke 定義

包含 MINMAXINFO、MONITORINFO、POINT、RECT 結構與 MonitorFromWindow、GetMonitorInfo 函式宣告,確保跨版本相容。

使用方式

在視窗建構函式或 Loaded 事件中呼叫:

public MainWindow() {
    InitializeComponent();
    FullScreenManager.RepairWpfWindowFullScreenBehavior(this);
}

工具類會自動處理:

  • 視窗已最大化時,先還原再重設,確保邏輯生效
  • 多螢幕環境下自動偵測視窗所在監視器
  • 高 DPI 縮放環境正確運作

附錄:常用 Windows 訊息代碼對照表

文末附上完整訊息代碼表(依名稱與代碼雙向排序),方便開發者查閱 WM_* 常數值,如 WM_PAINT=0x000F、WM_SIZE=0x0005、WM_MOUSEMOVE=0x0200 等。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved