【问题标题】:WPF Custom window and maximized sizeWPF 自定义窗口和最大化大小
【发布时间】:2013-02-21 13:28:16
【问题描述】:

我正在开发一个完全自定义的窗口控件并处理它的最大化,我已经覆盖了 WindowProc 函数并自己处理 WM_GETMINMAXINFO 消息。

我填充 MINMAXINFO 结构并将其发送到窗口句柄,然后就完成了。

它适用于我的主显示器,但在我的第二个显示器上,窗口太大了..

我不明白的是,我在第二台显示器上最大化时发送的 MINMAXINFO 结构具有正确的尺寸信息 (1920x1080),但一旦最大化,窗口的尺寸就会以 2160x1100..

有人知道发生了什么吗?

非常感谢。

【问题讨论】:

  • 您不使用 WindowState 属性是否有原因? (this.WindowState = System.Windows.WindowState.Maximized;)
  • 我正在创建一个没有任何边框的自定义 WPF 窗口,所以我需要自己处理最大化的大小。没有它 Windows 最大化我的窗口太大。我的问题不是如何最大化它,而是它最大化时的大小。
  • 这不是因为你的窗口没有边框,你必须自己处理“最大化”。请参阅我的答案建议。
  • 当问题被问到时,它更像是一个 win32 问题而不是 WPF 问题。

标签: wpf winapi window maximize


【解决方案1】:

@Karnalta - 不久前我也在做类似的事情。看看我的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;
}

【讨论】:

    【解决方案2】:

    与其使用 win32 事件,不如让 WPF 自己最大化窗口(使用WindowState = System.Windows.WindowState.Maximized;)并修改您的窗口内容模板以适合您想要的大小。

    例如,也许您可​​以将窗口内容封装在 Grid 中,并为此 Grid 设置边距。 最后,将窗口的背景属性(如果有)移动到网格中,并为窗口背景设置透明色。

    【讨论】:

    • 当我第一次开始使用这个方法时,我以很多调整结束,我遇到了很多问题,比如屏幕有一个任务栏而不是第二个,所以调整必须不同。因此,通过处理 Win32 事件,它在我的主屏幕上运行得非常好,并且在第二个屏幕上也应该很好地运行。除了第二个屏幕上的事件不服从 MINMAXINFO 结构,我不明白为什么。
    • 好的,也许你应该用“winapi”重新标记你的问题!
    【解决方案3】:

    听起来您提供的尺寸是基于第二台显示器的尺寸。 documentation for WM_GETMINMAXINFO 声明宽度/高度基于主监视器的大小表示,即使窗口将以不同的分辨率显示在不同的监视器中。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多