0

I'm trying to draw a custom title bar, and I've read that in order to paint outside a window's client area, I need to override WndProc and handle the WM_NCPAINT message. Currently, I'm doing that like this:

//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;
    }
}

Which works, because I can put a breakpoint in and it gets hit. If I remove the call to the original, the window's frame isn't drawn. DrawTitleBar looks like this:

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);
}

I first get the DC from the window handle. Then I get the Graphics object by using Graphics::FromHdc. I release the DC with ReleaseDC. Incase there's an issue here, this is how I import the native Win32 functions:

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

Also: I've tried a bunch of different methods, all with the same results. I can find a bunch of C# and VB examples on the web, but no C++ examples. I've also read about Windows Vista compatibility being an issue with this sort of thing. Currently, I don't care about that, as I will add it later.

smoth190
  • 428
  • 6
  • 26
  • 1
    GetDCEx() or GetWindowDC() is required to get a drawing context for the entire window, not just the client area like FromHwnd returns. Then Graphics::FromHdc(). Visual Styles stops this from working properly, only consider a borderless window for custom faked titlebars. – Hans Passant Aug 07 '12 at 02:58
  • @HansPassant Ok, I've changed my DrawTitleBar method to use `GetWindowDC`. However, I still get nothing drawn. How can I disable Visual Styles? Do I have to remove the call to `Application::EnableVisualStyles` in my `main` method? Doing this doesn't produce any noticeable result. Also, for a borderless window, do I just set the FormBorderStyle property to None? – smoth190 Aug 07 '12 at 03:08
  • Not related to the problem you're having, but you could get the GetWindowDC and ReleaseDC functions by `#include `, if you prefer. If you end up using a lot of Win32 methods, that would probably be easier than writing a DllImport for each of them. – David Yaw Aug 08 '12 at 17:09
  • @DavidYaw The reason I'm using DllImport is because I don't want to switch between Win32 datatypes and .NET datatypes. – smoth190 Aug 12 '12 at 20:21

1 Answers1

0

Two simple facts. 1. under DWM GetWindowDC is essentially broken. 2. Two work arounds partially exist A. set compatiblity mode to xp or 98 or 95. B. program example in msdn social exists. search for "GetWindowDC broken" then follow a lengthy url to a code sample [fix the broken url by adding a trailing ) ]. Unhappily, the window shows up with rounded corners on my box build 9200, win 8.0 , no updates.