10

我在 WPF 中创建了一个无边界应用程序,效果很好。但是,当我将 WindowState 设置为全屏时,应用程序占用的空间比我的屏幕分辨率还多,所以屏幕外各个方向都有一些像素!(看起来像添加了一些硬编码的负边距以隐藏默认边框)

任何想法如何防止这种情况发生?

我的xml:

<Window x:Class="MyApp.Shell"
    WindowStyle="None"
    BorderThickness="0"
    AllowsTransparency="True"
    Background="Transparent"
    ResizeMode="CanResizeWithGrip"
    WindowState="{Binding MainApplicationWindowState}"
    ...

此外,我看到的另一个问题是 Windows 工具栏/任务栏被全尺寸状态覆盖,因此看起来使用的是“实际”屏幕高度而不是“可用”屏幕高度,这意味着屏幕高度减去 Windows 工具栏/任务栏!

有人找到解决这些问题的方法吗?

谢谢

4

9 回答 9

4

我找到了这个很棒的解决方案

<Window WindowStyle="None" WindowStartupLocation="CenterScreen" WindowState="Maximized"
        MaxWidth="{Binding Source={x:Static SystemParameters.WorkArea}, Path=Width}"
        MaxHeight="{Binding Source={x:Static SystemParameters.WorkArea}, Path=Height}"
    >
...
</Window>

但是对我来说,错误仍然存​​在,窗口在顶部和左侧偏移了几个像素......我在更改窗口状态后尝试将左侧和顶部设置为 0,但没有任何反应。

于 2013-02-25T14:38:12.027 回答
2

我这样解决了这个问题:

XAML:

WindowStyle="None"
Left="0"
Top="0"
Width="{Binding WPFSettings.Width}"
Height="{Binding WPFSettings.Height}">

视觉基础:

Public Class WPFSettings
   Public ReadOnly Property Width() As Double
      Get
         Return System.Windows.SystemParameters.PrimaryScreenWidth
      End Get
   End Property

   Public ReadOnly Property Height() As Double
      Get
         Return System.Windows.SystemParameters.PrimaryScreenHeight
      End Get
   End Property
End Class

它工作得很好。

于 2010-01-19T16:15:23.270 回答
1

试试这个

Width="{Binding Source={x:Static SystemParameters.WorkArea}, Path=Width}"
Height="{Binding Source={x:Static SystemParameters.WorkArea}, Path=Height}"
于 2015-03-26T05:32:26.350 回答
1

.NET 的一个新特性解决了这个问题。离开您的WindowStyle="SingleBorderWindow""ThreeDBorderWindow" 离开ResizeMode="CanResize",然后将其添加到 xaml 中

<Window>
    <WindowChrome.WindowChrome>
        <WindowChrome GlassFrameThickness="0" CornerRadius="0" CaptionHeight="0" 
            UseAeroCaptionButtons="False" ResizeBorderThickness="7" />
    </WindowChrome.WindowChrome>
</Window>

该窗口将没有任何默认窗口窗格,但仍允许调整大小并且在最大化时不会覆盖任务栏。

于 2018-05-02T15:22:59.783 回答
0

Xaml中设置以下绑定Window.MaxHeight

MaxHeight="{DynamicResource {x:Static SystemParameters.MaximizedPrimaryScreenHeightKey}}"

不需要额外的实用程序类。

于 2010-09-02T18:39:42.827 回答
0

在我的情况下,Window 的 XAML 标记具有 Property SizeToContent="True",我所要做的就是删除它。

于 2011-05-13T10:23:39.863 回答
0

我需要它在不同尺寸的显示器上工作(就像大多数人听起来一样)。所以我只是这样做了......

<Window x:Class="MyApp.MainWindow"
    ResizeMode="CanResize" 
    WindowStyle="SingleBorderWindow"
    SizeChanged="Window_SizeChanged">
....
Code
....
</Window>


public void Window_SizeChanged(object sender, SizeChangedEventArgs e)
    {
        if (this.WindowState == WindowState.Maximized)
        {
            this.BorderThickness = new System.Windows.Thickness(8);
        }
        else
        {
            this.BorderThickness = new System.Windows.Thickness(0);
        }
    }
于 2019-07-10T08:19:44.947 回答
0

我加入俱乐部已经很晚了,但我相信追随我的人可能会从中受益。我尝试了几种解决方案,但大多数都无法在多个显示器上工作。因此,我正在分享一个在商业应用程序中非常适合我的解决方案。

我注册了 SourceInitialized 事件。在事件的回调中,我添加了以下代码,

        private void Window_SourceInitialized (object sender, EventArgs e)
        {
        WindowSizing.WindowInitialized(this);
        }

以下是 WindowSizing 类的代码,

public static class WindowSizing
    {
    const int MONITOR_DEFAULTTONEAREST = 0x00000002;

    #region DLLImports

    [DllImport("shell32", CallingConvention = CallingConvention.StdCall)]
    public static extern int SHAppBarMessage (int dwMessage, ref APPBARDATA pData);

    [DllImport("user32", SetLastError = true)]
    static extern IntPtr FindWindow (string lpClassName, string lpWindowName);

    [DllImport("user32")]
    internal static extern bool GetMonitorInfo (IntPtr hMonitor, MONITORINFO lpmi);

    [DllImport("user32")]
    internal static extern IntPtr MonitorFromWindow (IntPtr handle, int flags);

    #endregion

    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;
        }

    private static int GetEdge (RECT rc)
        {
        int uEdge = -1;
        if ( rc.top == rc.left && rc.bottom > rc.right )
            uEdge = (int) ABEdge.ABE_LEFT;
        else if ( rc.top == rc.left && rc.bottom < rc.right )
            uEdge = (int) ABEdge.ABE_TOP;
        else if ( rc.top > rc.left )
            uEdge = (int) ABEdge.ABE_BOTTOM;
        else
            uEdge = (int) ABEdge.ABE_RIGHT;
        return uEdge;
        }

    public static void WindowInitialized (Window window)
        {
        IntPtr handle = (new System.Windows.Interop.WindowInteropHelper(window)).Handle;
        System.Windows.Interop.HwndSource.FromHwnd(handle).AddHook(new System.Windows.Interop.HwndSourceHook(WindowProc));
        }

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

        return (IntPtr) 0;
        }

    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);
        }

    public enum ABEdge
        {
        ABE_LEFT = 0,
        ABE_TOP = 1,
        ABE_RIGHT = 2,
        ABE_BOTTOM = 3
        }

    public enum ABMsg
        {
        ABM_NEW = 0,
        ABM_REMOVE = 1,
        ABM_QUERYPOS = 2,
        ABM_SETPOS = 3,
        ABM_GETSTATE = 4,
        ABM_GETTASKBARPOS = 5,
        ABM_ACTIVATE = 6,
        ABM_GETAUTOHIDEBAR = 7,
        ABM_SETAUTOHIDEBAR = 8,
        ABM_WINDOWPOSCHANGED = 9,
        ABM_SETSTATE = 10
        }

    [StructLayout(LayoutKind.Sequential)]
    public struct APPBARDATA
        {
        public int cbSize;
        public IntPtr hWnd;
        public int uCallbackMessage;
        public int uEdge;
        public RECT rc;
        public bool lParam;
        }

    [StructLayout(LayoutKind.Sequential)]
    public struct MINMAXINFO
        {
        public POINT ptReserved;
        public POINT ptMaxSize;
        public POINT ptMaxPosition;
        public POINT ptMinTrackSize;
        public POINT ptMaxTrackSize;
        };

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
    public class MONITORINFO
        {
        public int cbSize = Marshal.SizeOf(typeof(MONITORINFO));
        public RECT rcMonitor = new RECT();
        public RECT rcWork = new RECT();
        public int dwFlags = 0;
        }

    [StructLayout(LayoutKind.Sequential)]
    public struct POINT
        {
        public int x;
        public int y;

        public POINT (int x, int y)
            {
            this.x = x;
            this.y = y;
            }
        }

    [StructLayout(LayoutKind.Sequential, Pack = 0)]
    public struct RECT
        {
        public int left;
        public int top;
        public int right;
        public int bottom;
        }
    }

这对于许多场景来说就像魔术一样,比如最大化没有边框的窗口也覆盖了任务栏。此解决方案也使任务栏不被覆盖。

问候, 奥马尔

于 2021-10-26T09:30:18.970 回答
-1

我在窗口上使用触发器:

<Style.Triggers>
    <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self},Path=WindowState}" Value="{x:Static WindowState.Maximized}">
        <Setter Property="BorderThickness" Value="8"/>
    </DataTrigger>
</Style.Triggers>

当窗口状态最大化时,此触发器会创建一个边框。我认为它很有用。

于 2019-09-04T02:42:49.440 回答