我正在尝试使用DWM为我的表单创建自定义窗口框架。 该平台是C#WinForms,Pinvoking DWM。
在MSDN article on making custom window frame with DWM之后,接下来是主要步骤:
我以下一种方式处理WM_NCCALCSIZE消息:
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_NCCALCSIZE:
if (isDwmWindowFramePaintEnabled() && m.WParam != IntPtr.Zero)
{
m.Result = IntPtr.Zero;
}
else
{
base.WndProc(ref m);
}
return;
}
}
根据MSDN documentation on WM_NCCALCSIZE,
当wParam为TRUE时,只返回0而不处理 NCCALCSIZE_PARAMS矩形将导致客户区调整大小 窗口的大小,包括窗口框架。这将删除 窗口框架和标题项目从您的窗口,只留下 客户区显示。
除了一个问题,一切都很好,对我有用。 当我最大化/恢复窗口时,它在恢复时总是会增长一点。 我想,问题是这样的:
因此,每当我最大化/恢复它时,这个窗口就会增长一点点。 我需要删除非客户区域以使用DWM绘制自定义表单框架。 我不能简单地将窗口边框样式设置为无,因为DWM不会绘制窗口标题和边框。
请帮助解决问题并愉快地拥有自定义窗口框架。
答案 0 :(得分:4)
这实际上是Windows窗体中的一个错误,并且有一个解决方法。在函数Form.SizeFromClientSize(int, int)
中,AdjustWindowRectEx
函数用于转换大小,它始终使用默认度量,不能被覆盖。从两个地方调用此函数:
RestoreWindowBoundsIfNecessary
SetClientSizeCore
解决方法如下:
在表单中覆盖CreateParams:
private bool createParamsHack;
protected override CreateParams CreateParams
{
get
{
CreateParams cp = base.CreateParams;
// Remove styles that affect the border size
if (createParamsHack)
cp.Style &= ~(int)(WS_BORDER | WS_CAPTION | WS_DLGFRAME | WS_THICKFRAME);
return cp;
}
}
覆盖WndProc并插入以下代码来处理WM_WINDOWPOSCHANGED:
if (m.Msg == WM_WINDOWPOSCHANGED)
{
createParamsHack = true;
base.WndProc(ref m);
createParamsHack = false;
}
覆盖SetClientSizeCore:
protected override void SetClientSizeCore(int x, int y)
{
createParamsHack = true;
base.SetClientSizeCore(x, y);
createParamsHack = false;
}
覆盖SizeFromClientSize(Size)
以返回正确的测量值也可能是个好主意,但这并不是绝对必要的。