2012-08-07 44 views
0

我想绘制一个自定义标题栏,我已经读过,为了在窗口的客户区域之外绘画,我需要重写WndProc并处理WM_NCPAINT消息。目前,我正在做的是这样的:如何在C++。NET中绘制窗口的标题栏?

//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::FromHdc得到Graphics对象。我用ReleaseDC发布DC。柜面这里有一个问题,我这是怎么导入原生Win32函数:

[DllImport("user32.dll")] 
extern IntPtr GetWindowDC(IntPtr hWnd); 
[DllImport("user32.dll")] 
extern int ReleaseDC(IntPtr hWnd, IntPtr hDC); 

另外:我已经尝试了一堆不同的方法,都具有相同的结果。我可以在网上找到一堆C#和VB示例,但没有C++示例。我也读过Windows Vista的兼容性问题。目前,我不在乎这一点,因为我稍后会添加它。

+1

需要GetDCEx()或GetWindowDC()来获取整个窗口的绘制上下文,而不仅仅是FromHwnd返回的客户区。然后Graphics :: FromHdc()。视觉样式阻止它正常工作,只考虑自定义伪造标题栏的无边框窗口。 – 2012-08-07 02:58:55

+0

@HansPassant好吧,我已经改变了我的DrawTitleBar方法来使用'GetWindowDC'。但是,我仍然没有画任何东西。我如何禁用视觉样式?我必须在我的'main'方法中去除对'Application :: EnableVisualStyles'的调用吗?这样做不会产生任何明显的结果。此外,对于无边界窗口,我只是将FormBorderStyle属性设置为None? – smoth190 2012-08-07 03:08:29

+0

与您遇到的问题无关,但如果您愿意,可以通过#include 获得GetWindowDC和ReleaseDC函数。如果你最终使用了很多Win32方法,那可能比为它们编写一个DllImport容易。 – 2012-08-08 17:09:08

回答

0

两个简单的事实。 1. DWM下的GetWindowDC基本上被打破了。 2.部分存在两种解决方法A.将兼容性模式设置为xp或98或95. B.存在msdn社交中的程序示例。搜索 “GetWindowDC破碎”,然后按照冗长的网址代码 示例[通过添加尾随修复破损的网址]]。 不幸的是,窗口显示与 圆角我的盒子构建9200,赢得8.0,没有更新。