目录
介绍
背景
是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 width和height调整窗口大小。另外,还要确保你为窗口设置了Left和Top。
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 将确保该窗口的默认行为被覆盖,并使任务栏重新出现。