カスタム フォーム (C#/Windows Forms/Vista/Windows7) を作成し、WndProc をオーバーライドして WM_NCPAINT、WM_NCCALCSIZE、および WM_NCHITTEST をキャプチャしてカスタム フレームを描画しています。私はそれでほぼ完了しましたが、自分で回避できなかったという問題があります。
問題は、最大化後にフォームを復元すると、NC_CALCSIZE によってフォームが縮小されることです。私はそれをグーグルで検索し、Bob Powell からの回答を見つけました。彼は、WPARAM が TRUE の場合、NC_CALCSIZE を処理する必要はないと述べました。私がそれを行った後、WM_NCPAINT はもう効果がありませんでした (WM_NCPAINT を処理しますが、非クライアント領域を描画しません。無効にした後でのみです)。
したがって、再開すると、WM_NCCALCSIZE(WPARAM == TRUE) を処理すると、フォームが縮小されます。そうしないと、もうペイントされません。
誰かが以前にこの問題を抱えていましたか? さらにコードが必要な場合は、提供できます。わかりました。
ここに私の WN_CALCSIZE コードがあります:
private void WndProcNonClientCalcSize(ref Message m)
{
if (m.WParam == WinAPI.FALSE)
{
this.Log(MethodInfo.GetCurrentMethod(), "FALSE");
WinAPI.NCCALCSIZE_PARAMS csp;
csp = (WinAPI.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(WinAPI.NCCALCSIZE_PARAMS));
csp.rectProposed.Top += this._nonClientHeight;
csp.rectProposed.Bottom -= this._nonClientBorderThickness;
csp.rectProposed.Left += this._nonClientBorderThickness;
csp.rectProposed.Right -= this._nonClientBorderThickness;
Marshal.StructureToPtr(csp, m.LParam, false);
}
else if (m.WParam == WinAPI.TRUE)
{
this.Log(MethodInfo.GetCurrentMethod(), "TRUE");
WinAPI.NCCALCSIZE_PARAMS csp;
csp = (WinAPI.NCCALCSIZE_PARAMS)Marshal.PtrToStructure(m.LParam, typeof(WinAPI.NCCALCSIZE_PARAMS));
csp.rectProposed.Top += this._nonClientHeight;
csp.rectProposed.Bottom -= this._nonClientBorderThickness;
csp.rectProposed.Left += this._nonClientBorderThickness;
csp.rectProposed.Right -= this._nonClientBorderThickness;
Marshal.StructureToPtr(csp, m.LParam, false);
}
m.Result = WinAPI.TRUE;
}
ここに私の WM_NCPAINT コードがあります:
private bool WndProcNonClientPaint(ref Message m)
{
this.Log(MethodInfo.GetCurrentMethod(), string.Empty);
this.PaintNonClient(m.HWnd, (IntPtr)m.WParam);
m.Result = WinAPI.TRUE;
return true;
}
private void PaintNonClient(IntPtr hWnd, IntPtr hRgn)
{
WinAPI.RECT windowRect = new WinAPI.RECT();
WinAPI.GetWindowRect(hWnd, ref windowRect);
Rectangle bounds = new Rectangle(0, 0,
windowRect.Right - windowRect.Left,
windowRect.Bottom - windowRect.Top);
if (bounds.Width == 0 || bounds.Height == 0)
return;
Region clipRegion = new Region(bounds);
if (hRgn != (IntPtr)1)
clipRegion = Region.FromHrgn(hRgn);
WinAPI.DCV dcv =
WinAPI.DCV.WINDOW |
WinAPI.DCV.INTERSECTRGN |
WinAPI.DCV.CACHE |
WinAPI.DCV.CLIPSIBLINGS;
IntPtr hDC =
WinAPI.GetDCEx(
hWnd,
hRgn,
dcv);
if (hDC == IntPtr.Zero)
hDC = WinAPI.GetWindowDC(hWnd);
IntPtr compatiblehDC = WinAPI.CreateCompatibleDC(hDC);
IntPtr compatibleBitmap = WinAPI.CreateCompatibleBitmap(hDC, bounds.Width, bounds.Height);
try
{
WinAPI.SelectObject(compatiblehDC, compatibleBitmap);
WinAPI.BitBlt(compatiblehDC, 0, 0, bounds.Width, bounds.Height, hDC, 0, 0, WinAPI.SRCCOPY);
using (Graphics g = Graphics.FromHdc(compatiblehDC))
{
Rectangle outterEdge = new Rectangle(0, 0, this.Width, this.Height);
int x = this._nonClientBorderThickness;
int y = this._nonClientHeight;
int width = this.Width - (this._nonClientBorderThickness * 2);
int height = this.Height - this._nonClientBorderThickness - this._nonClientHeight;
Rectangle innerEdge = new Rectangle(x, y, width, height);
GraphicsPath path = new GraphicsPath();
path.AddRectangle(outterEdge);
path.AddRectangle(innerEdge);
using (SolidBrush brush = new SolidBrush(Color.FromArgb(45, 45, 48)))
g.FillPath(brush, path);
path.Dispose();
}
WinAPI.BitBlt(hDC, 0, 0, bounds.Width, bounds.Height, compatiblehDC, 0, 0, WinAPI.SRCCOPY);
}
finally
{
WinAPI.DeleteObject(compatibleBitmap);
WinAPI.DeleteDC(compatiblehDC);
}
}