Blog
Drawing windows BUTTONs on coloured backgrounds
Date: 4/7/2016
Tags: windows
The default windows BUTTON drawing behaviour draws a 1px grey border around buttons. If you place the button on a parent window that is a different colour you get an ugly border like this:



So I decided to see what I could do about that. It turns out that there is no "setting" that can fix that. You either draw the whole control yourself or let the system draw it. Now I want the system look without the wrong coloured border. So I reimplemented the WM_PAINT like so:
case WM_PAINT:
{
    if (!GetCss())
        break;

    // This is the effective background of the parent window:
    GCss::ColorDef bk = GetCss()->NoPaintColor();

    // If it's not the default...
    if (!bk.IsValid())
        break;

    // Then create a screen device context for painting
    GScreenDC dc(this);
    
    // Get the control to draw itself into a bitmap
    GRect c = GetPos();
    
    // Create a HBITMAP in the same size as the control 
    // and the same bit depth as the screen
    GMemDC m(c.X(), c.Y(), GdcD->GetColourSpace());
    // Create a HDC for the bitmap
    HDC hdc = m.StartDC();					
    // Ask the control to draw itself into the memory bitmap
    SendMessage(_View, WM_PRINT, (WPARAM)hdc, PRF_ERASEBKGND|PRF_CLIENT);
    // End the HDC
    m.EndDC();

    // Draw correct background
    m.Colour(bk.Rgb32, 32);
    // The outside 1px border (unfilled rect)
    m.Box(0, 0, c.X()-1, c.Y()-1);
    // The 4 pixels at the corners
    m.Set(1, 1);
    m.Set(c.X()-2, 1);
    m.Set(1, c.Y()-2);
    m.Set(c.X()-2, c.Y()-2);

    // Now stick it on the screen
    dc.Blt(0, 0, &m);

    // Skip over calling the parent class' callback procedure.
    return true;
    break;
}
What it does is get the system to draw the button into a memory bitmap and then "fix" the border, before blting the whole thing to the screen. Now it's implemented with LGI types and classes, but the whole idea is fairly straight forward that you could implement in raw Win32 API calls. This fixes the border and still looks native:



The key is re-purposing the WM_PRINT message to get a copy of the control's native look. For the moment I've limited this to just when running on Windows 7, because I think Windows 8 and 10 use flat colour controls and [possibly] don't need fixing like this.
 
Reply
From:
Email (optional): (Will be HTML encoded to evade harvesting)
Message:
 
Remember username and/or email in a cookie.
Notify me of new posts in this thread via email.
BBcode:
[q]text[/q]
[url=link]description[/url]
[img]url_to_image[/img]
[pre]some_code[/pre]
[b]bold_text[/b]