问题描述
当我的 WinForm 应用程序从主监视器移动到辅助监视器时,这些属性和 winapi 函数返回的边界(窗口的高度和宽度)值不会改变:
When my WinForm application is moved from a primary monitor to a secondary monitor, the bounds (Height and Width of the Window) value returned by these properties and winapi function does not change :
- Form.Bounds
- 形式.大小
- GetWindowRect()
但是 DwmGetWindowAttribute
和 DWMWA_EXTENDED_FRAME_BOUNDS
返回的值发生了巨大的变化.
But the value returned by DwmGetWindowAttribute
with DWMWA_EXTENDED_FRAME_BOUNDS
changes drastically.
根据评论的建议进行例如,在主监视器中 DwmgetWindowAttribute 返回宽度和高度 292, 100
和其他值返回 306, 107
.考虑到投影占用 7 个像素,这是连贯的.但是当窗口移动到辅助监视器时,DwmgetWindowAttribute返回437, 150
,其他方法返回相同的306, 107
Edits after suggestion from comments: For instance, in the primary monitor DwmgetWindowAttribute returns a rect of width and height 292, 100
and the other values return 306, 107
. This is coherent considering the drop shadow takes up 7 pixels. But when the window is moved to the secondary monitor, DwmgetWindowAttribute returns 437, 150
and the other methods return the same 306, 107
事实上,我的两台显示器的分辨率都是 1920 * 1080(但如果重要的话,比例会有所不同)
In fact both my monitors are of resolution 1920 * 1080 (but the scale differs though if it matters)
问题:为什么会这样?是只有我还是其他人遇到过类似的问题?最终我想计算阴影大小.还有其他办法吗?
Question: Why does this happen this way? Is it only me or have anyone else faced similar issues? Ultimately I want to calculate the drop shadow size. Is there any other way?
复制:
如果您希望重现此内容,请创建一个 winform 项目.在构造函数中使用 AllocConsole() 分配控制台.为 LocationChanged
添加一个事件处理程序,并将以下代码添加到事件处理程序中:
If you wish to reproduce this, create a winform project. Allocate console using AllocConsole() in the constructor. Add an event handler for LocationChanged
and add the following code to the event handler:
private void AgentMainForm_LocationChanged(object sender, EventArgs e)
{
Console.WriteLine("bounds: {0}, {1}", Bounds.Width, Bounds.Height);
Console.WriteLine("Size: {0}, {1}", Size.Width, Size.Height);
Console.WriteLine("Window Rect: {0}, {1}", GetSizeWithShadow().Width, GetSizeWithShadow().Height);
Console.WriteLine("Window Rect: {0}, {1}", GetSizeWithoutShadow().Width, GetSizeWithoutShadow().Height);
}
[DllImport("user32.dll", SetLastError = true)]
public static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);
[DllImport("dwmapi.dll")]
public static extern int DwmGetWindowAttribute(IntPtr hwnd, int dwAttribute, out RECT pvAttribute, int cbAttribute);
public Size GetSizeWithoutShadow()
{
RECT regionWithoutShadow;
IntPtr hWnd = this.Handle;
if (Environment.OSVersion.Version.Major < 6) //DwmGetWindowAttribute does not work in XP, compatible only from Vista
{
GetWindowRect(hWnd, out regionWithoutShadow);
}
else
{
if (DwmGetWindowAttribute(hWnd, DWMWA_EXTENDED_FRAME_BOUNDS, out regionWithoutShadow, Marshal.SizeOf(typeof(RECT))) != 0)
{
//Handle for failure
}
}
return new Size(regionWithoutShadow.right - regionWithoutShadow.left, regionWithoutShadow.bottom - regionWithoutShadow.top);
}
public Size GetSizeWithShadow()
{
RECT regionWithoutShadow;
IntPtr hWnd = this.Handle;
GetWindowRect(hWnd, out regionWithoutShadow);
return new Size(regionWithoutShadow.right - regionWithoutShadow.left, regionWithoutShadow.bottom - regionWithoutShadow.top);
}
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
推荐答案
您得到这个答案是因为您的 DPI 比例在一台显示器上为 1.5,在另一台显示器上为 1.0.可以使用 GetDpiForWindow进行协调一>.
You get this answer because your DPI scale is 1.5 on one monitor and 1.0 on the other. It might be possible to reconcile using GetDpiForWindow.
这篇关于为什么在切换监视器时 DwmGetWindowAttribute 和 DWMWA_EXTENDED_FRAME_BOUNDS 的行为异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!