我正在尝试绘制一个自定义标题栏,并且我已经阅读过,为了在窗口的客户区之外进行绘制,我需要覆盖 WndProc 并处理 WM_NCPAINT 消息。目前,我正在这样做:
//WndProc override
virtual void WndProc(Message% m) override
{
switch(m.Msg)
{
case 0x85: //WM_NCPAINT
case 0x0A: //WM_PAINT
//Call original
System::Windows::Forms::Form::WndProc(m);
//Now we'll do our painting
DrawTitleBar(m.HWnd);
break;
default:
System::Windows::Forms::Form::WndProc(m);
break;
}
}
哪个有效,因为我可以在其中设置一个断点并且它会被击中。如果我删除对原始的调用,则不会绘制窗口的框架。DrawTitleBar
看起来像这样:
void DrawTitleBar(IntPtr hWnd)
{
IntPtr hDC;
Graphics^ g;
//Get the device context (DC)
hDC = GetWindowDC(hWnd);
//Get the graphics
g = Graphics::FromHdc(hDC);
//Draw
g->FillRectangle(Brushes::Blue, 0, 0, 100, 10);
//Cleanup
g->Flush();
ReleaseDC(hWnd, hDC);
}
我首先从窗口句柄中获取 DC。然后我Graphics
通过使用Graphics::FromHdc
. 我用ReleaseDC
. 如果这里有问题,这就是我导入本机 Win32 函数的方式:
[DllImport("user32.dll")]
extern IntPtr GetWindowDC(IntPtr hWnd);
[DllImport("user32.dll")]
extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);
另外:我尝试了很多不同的方法,结果都一样。我可以在网上找到一堆 C# 和 VB 示例,但没有 C++ 示例。我还阅读了有关 Windows Vista 兼容性是这类事情的一个问题。目前,我不在乎这一点,因为我稍后会添加它。