c# - 单击任务栏图标 wpf 时在辅助监视器上正确调整大小
问题描述
我有一个 wpf 应用程序,我使用 WmGetMinMaxInfo 管理最大尺寸:
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;
mmi.ptMaxTrackSize.y = mmi.ptMaxSize.y;
}
Marshal.StructureToPtr(mmi, lParam, true);
}
我的窗口设置为:
WindowStyle="None"
ResizeMode="CanResizeWithGrip"
AllowsTransparency="True"
当我在最大化状态下最小化应用程序以及在任务栏图标上单击返回以返回最大化窗口应用程序时,我遇到了一个奇怪的问题。
它不占用全屏,它似乎占用了主屏幕分辨率。当我在主屏幕和辅助屏幕之间没有相同的分辨率时(显然我的辅助屏幕比第一个更大),我遇到了这种情况。
你有什么想法问题出在哪里?Windows功能 ?有什么解决办法吗?
解决方案:我已经用 Keithernet 的想法解决了我的问题,即当 windowState 最小化时不重新计算。谢谢 !
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;
if (Application.Current.MainWindow.WindowState != WindowState.Minimized)
{
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;
mmi.ptMaxTrackSize.y = mmi.ptMaxSize.y;
lastGoodMaxTrackSize = mmi.ptMaxTrackSize;
lastGoodMaxPosition = mmi.ptMaxPosition;
lastGoodMaxSize = mmi.ptMaxSize;
}
else
{
mmi.ptMaxPosition = lastGoodMaxPosition;
mmi.ptMaxSize = lastGoodMaxSize;
mmi.ptMaxTrackSize = lastGoodMaxTrackSize;
}
mmi = AdjustWorkingAreaForAutoHide(monitorContainingApplication, mmi);
}
Marshal.StructureToPtr(mmi, lParam, true);
}
解决方案
我有一个多年前编写的自定义窗口控件。它仍在积极使用中。无论 Windows 在哪个显示器上以及单个 DPI 是什么,都可以正确处理 Windows。
这是我的WmGetMinMaxInfo
.
我希望这是有帮助的。
private void WmGetMinMaxInfo(IntPtr hwnd, IntPtr lParam)
{
var mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO));
var hMonitor = Win32.MonitorFromWindow(hwnd, 1);
if (hMonitor != IntPtr.Zero)
{
var monitorInfo = new Win32.MONITORINFO();
Win32.GetMonitorInfo(hMonitor, monitorInfo);
var rcWorkArea = monitorInfo.rcWork;
var 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.ptMinTrackSize.x = (int)(minWidth * hidpiX);
mmi.ptMinTrackSize.y = (int)(minHeight * hidpiY);
var window = (Window)HwndSource.FromHwnd(hwnd)?.RootVisual;
if (window != null)
{
if (window.WindowState != WindowState.Minimized)
{
mmi.ptMaxTrackSize.x = Win32.GetSystemMetrics(Win32.SystemMetric.SM_CXVIRTUALSCREEN);
mmi.ptMaxTrackSize.y = Win32.GetSystemMetrics(Win32.SystemMetric.SM_CYVIRTUALSCREEN);
lastGoodMaxTrackSize = mmi.ptMaxTrackSize;
}
else if (lastGoodMaxTrackSize.x > 0 && lastGoodMaxTrackSize.y > 0)
{
mmi.ptMaxTrackSize = lastGoodMaxTrackSize;
}
}
mmi = AdjustWorkingAreaForAutoHide(hMonitor, mmi);
}
Marshal.StructureToPtr(mmi, lParam, true);
}
对于 hidpiX 和 hidpiY,我将它们放在OnSourceInitialized
事件的处理程序中。
private void OnSourceInitialized(object sender, EventArgs e)
{
...
var source = PresentationSource.FromVisual((Visual)sender);
if (source == null) return;
// Get the X and Y HiDPI factors from the media matrix
if (source.CompositionTarget != null)
{
hidpiX = source.CompositionTarget.TransformToDevice.M11;
hidpiY = source.CompositionTarget.TransformToDevice.M22;
}
...
}
推荐阅读
- arrays - 带有大数组的 Symfony ChoiceType,错误“此值无效。”
- python - 如何仅打印python列表中的重复元素
- angular - 从子组件到父组件的Angular 5 EventEmitter发出未定义的
- python - 多处理不起作用(不间断进程)
- c# - 处理 EF Core 2.0 的异常
- r - 如何将自定义日期向量添加到绘图中?
- c# - C# Windows 应用程序计时器停止
- php - 通过表单提交数组索引而不在php中输入
- linux - 如何使用 linux shell 脚本从 1-500 生成大小为 1mb 的随机文件
- linux - 在 Linux 中并行启动多个命令并等待所有命令完成