2013-02-21 82 views
2

我正在完全自定義窗口控件,並處理它的最大化,我已經覆蓋WindowProc函數並處理自己的WM_GETMINMAXINFO消息。WPF自定義窗口和最大化尺寸

我將MINMAXINFO結構填充併發送到窗口句柄並完成。

它很好地工作,我的主監視器,但我的第二個監視器窗口太大的..

我不明白的是,MINMAXINFO結構,我的第二個監視器上最大化時發送具有正確的尺寸信息(1920x1080),但一旦最大化Windows結束與2160x1100的大小..

任何人都知道發生了什麼?

非常感謝。

+0

是否有你沒有使用WindowState屬性的原因? ('this.WindowState = System.Windows.WindowState.Maximized;') – JYL 2013-02-26 13:54:41

+0

我正在創建一個沒有任何邊框的自定義WPF窗口,所以我需要自己處理最大化的大小。沒有它Windows最大化我的窗口太大。我的問題不是如何最大化它,而是最大化它的大小。 – Karnalta 2013-02-28 10:55:51

+0

這不是因爲你的窗口沒有邊界,你必須自己處理「最大化」。看到我的回答建議。 – JYL 2013-02-28 12:38:16

回答

1

@卡爾納塔 - 我之前做了類似的事情。看看我的an old blog post。我在上面的鏈接中考慮了可下載示例中的任務欄和自動隱藏任務欄。我的兩臺顯示器的尺寸都相同,所以它看起來對我來說非常合適,但請嘗試一下。以下是您可能最感興趣的兩種方法。

private static void WmGetMinMaxInfo(IntPtr hwnd, IntPtr lParam) 
{ 
    MINMAXINFO mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO)); 
    IntPtr monitorContainingApplication = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); 

    if (monitorContainingApplication != System.IntPtr.Zero) 
    { 
     MONITORINFO monitorInfo = new MONITORINFO(); 
     GetMonitorInfo(monitorContainingApplication, monitorInfo); 
     RECT rcWorkArea = monitorInfo.rcWork; 
     RECT rcMonitorArea = monitorInfo.rcMonitor; 
     mmi.ptMaxPosition.x = Math.Abs(rcWorkArea.left - rcMonitorArea.left); 
     mmi.ptMaxPosition.y = Math.Abs(rcWorkArea.top - rcMonitorArea.top); 
     mmi.ptMaxSize.x = Math.Abs(rcWorkArea.right - rcWorkArea.left); 
     mmi.ptMaxSize.y = Math.Abs(rcWorkArea.bottom - rcWorkArea.top); 
     mmi.ptMaxTrackSize.x = mmi.ptMaxSize.x;             //maximum drag X size for the window 
     mmi.ptMaxTrackSize.y = mmi.ptMaxSize.y;             //maximum drag Y size for the window 
     mmi.ptMinTrackSize.x = 800;                //minimum drag X size for the window 
     mmi.ptMinTrackSize.y = 600;                //minimum drag Y size for the window 
     mmi = AdjustWorkingAreaForAutoHide(monitorContainingApplication, mmi);     //need to adjust sizing if taskbar is set to autohide 
    } 
    Marshal.StructureToPtr(mmi, lParam, true); 
} 

private static MINMAXINFO AdjustWorkingAreaForAutoHide(IntPtr monitorContainingApplication, MINMAXINFO mmi) 
{ 
    IntPtr hwnd = FindWindow("Shell_TrayWnd", null); 
    if (hwnd == null) return mmi; 
    IntPtr monitorWithTaskbarOnIt = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); 
    if (!monitorContainingApplication.Equals(monitorWithTaskbarOnIt)) return mmi; 
    APPBARDATA abd = new APPBARDATA(); 
    abd.cbSize = Marshal.SizeOf(abd); 
    abd.hWnd = hwnd; 
    SHAppBarMessage((int)ABMsg.ABM_GETTASKBARPOS, ref abd); 
    int uEdge = GetEdge(abd.rc); 
    bool autoHide = System.Convert.ToBoolean(SHAppBarMessage((int)ABMsg.ABM_GETSTATE, ref abd)); 

    if (!autoHide) return mmi; 

    switch (uEdge) 
    { 
     case (int)ABEdge.ABE_LEFT: 
      mmi.ptMaxPosition.x += 2; 
      mmi.ptMaxTrackSize.x -= 2; 
      mmi.ptMaxSize.x -= 2; 
      break; 
     case (int)ABEdge.ABE_RIGHT: 
      mmi.ptMaxSize.x -= 2; 
      mmi.ptMaxTrackSize.x -= 2; 
      break; 
     case (int)ABEdge.ABE_TOP: 
      mmi.ptMaxPosition.y += 2; 
      mmi.ptMaxTrackSize.y -= 2; 
      mmi.ptMaxSize.y -= 2; 
      break; 
     case (int)ABEdge.ABE_BOTTOM: 
      mmi.ptMaxSize.y -= 2; 
      mmi.ptMaxTrackSize.y -= 2; 
      break; 
     default: 
      return mmi; 
    } 
    return mmi; 
} 
+0

謝謝,它現在的工作:) – Karnalta 2013-03-04 14:50:13

+0

@卡爾納塔不客氣......我的拳頭賞金!好極了! – BBauer42 2013-03-05 13:42:54

0

而不是使用win32事件,它可能會更容易讓WPF自己最大化窗口(使用WindowState = System.Windows.WindowState.Maximized;)並修改您的窗口內容模板以適合您需要的大小。

例如,也許您可​​以將窗口內容封裝在網格中,並將邊距設置爲此網格。 最終,然後將窗口的背景屬性(如果有)移動到網格併爲窗口背景設置透明顏色。

+0

當我第一次接觸這個新手時,我已經做了很多調整,而且我有很多問題,比如屏幕上有一個任務欄,而不是第二個,所以調整必須有所不同。所以通過處理Win32事件,它在我的主屏幕上工作得非常好,並且在第二個屏幕上也能很好地工作。除了第二個屏幕上的事件不符合MINMAXINFO結構,我不明白爲什麼。 – Karnalta 2013-02-28 14:04:56

+0

好的,也許你應該用「winapi」重新提出你的問題! – JYL 2013-02-28 14:32:41

0

聽起來好像您正在根據第二臺顯示器的大小提供大小。 documentation for WM_GETMINMAXINFO指出,即使窗口將顯示在具有不同分辨率的不同顯示器中,寬度/高度也是基於主顯示器的大小表示的。