在WPF中最大化窗口并将WindowState设置为None的任务栏

目录

介绍

背景

是Bug吗?

使用代码

解决方案

设置窗口的属性


介绍

假设您希望WPF应用程序没有标题栏,并且将最大化显示为全屏,那么您首先想到的是什么?这是最容易做到的。

  • WindowStyle设置为Maximized:这样,Window将不会显示任何标题栏。窗口样式将转换为带有边框的Box
  • WindowState设置为None:这样,窗口将最大化到整个屏幕,并且仅显示该窗口,而没有其他显示。

就像我说的,它隐藏了整个屏幕,这意味着如果未将其设置为Always on Top属性,它甚至不会显示任务栏或应用于桌面的任何外部小工具。

是的,这是我最近遇到的问题,当时人们希望我显示TaskBar,即使应将应用程序最大化。

背景

Bug吗?

如果我没看错,WPF会根据屏幕分辨率构建应用程序。它产生独立于DPI的像素。如果将其指定为全屏,则它将首先获取屏幕的分辨率,然后根据其自己的算法绘制像素。因此,当您将其指定为最大化时,它将占据整个屏幕,否则屏幕的某些部分将隐藏在边界范围之外。

还原WPF屏幕时,它还将根据分辨率边界之间的距离重新计算工作区域并相应地调整其大小。现在,您是否认为Microsoft真的应该有一个替代状态,可以像正常Windows一样显示任务栏?我想是的。

使用代码

解决方案

当我需要这样做时,我自己尝试了几种解决方法。

我必须使用以下代码:

private static System.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 (System.IntPtr)0;
}

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

    // Adjust the maximized size and position to fit the work area of the correct monitor
    int MONITOR_DEFAULTTONEAREST =0x00000002;
    System.IntPtr monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);

    if (monitor != System.IntPtr.Zero)
    {                
        MONITORINFO monitorInfo = new MONITORINFO();
        GetMonitorInfo(monitor, 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);
    }

    Marshal.StructureToPtr(mmi, lParam, true);
}

调用API WmGetMinMaxInfo可获取当前桌面的最大化窗口的大小。

[DllImport("user32")]
internal static extern bool GetMonitorInfo(IntPtr hMonitor, MONITORINFO   lpmi);
[DllImport("User32")]
internal static extern IntPtr MonitorFromWindow(IntPtr handle, int flags);

调用GetMonitorInfo将获得一个MONITORINFO对象,如果您仔细查看代码,它实际上是以这样一种方式来定位窗口的:它完全根据矩形区域的高度和宽度调整自己的大小。

获取窗口句柄的更好方法是使用SourceInitialized事件。这也将避免每次动态更改窗口模板时调用ApplyTemplate

public override void OnApplyTemplate()
       {
           System.IntPtr handle = (new WinInterop.WindowInteropHelper(this)).Handle;
           WinInterop.HwndSource.FromHwnd(handle).AddHook
                                  (new WinInterop.HwndSourceHook(WindowProc));
       }

要调用此方法,我可以使用SourceInitialized事件,它最终将在修改WindowState时调用。

win.SourceInitialized += new EventHandler(win_SourceInitialized);

void win_SourceInitialized(object sender, EventArgs e)
{
    System.IntPtr handle = (new WinInterop.WindowInteropHelper(this)).Handle;
    WinInterop.HwndSource.FromHwnd(handle).AddHook(new WinInterop.HwndSourceHook(WindowProc));
}

设置窗口的属性

WindowStyle="None"
WindowState="Maximized"
ResizeMode="NoResize"

转到您的代码,然后根据PrimaryScreen widthheight调整窗口大小。另外,还要确保你为窗口设置了LeftTop

this.Width = System.Windows.SystemParameters.WorkArea.Width;
this.Height = System.Windows.SystemParameters.WorkArea.Height;
this.Left = 0;
this.Top = 0;
this.WindowState = WindowState.Normal;

Normal 将确保该窗口的默认行为被覆盖,并使任务栏重新出现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值