25

I am trying to change my application' s title bar and border colors programmatically. I tried lots of things but with no success, and decided to change these colors system-wide. Because it is also acceptable for me to change title bar and border colors as my application is running, and revert them back in the end of my application. (Managed environment, with small set of applications running)

Is it possible to change these colors dynamically(process-wide, or system-wide unless process-wide change is possible)? Can you suggest any way to achieve this?

I tried something like the following but it doesn' t do what I want:

int aElements[2] = {COLOR_WINDOW, COLOR_ACTIVECAPTION};
DWORD aOldColors[2];
DWORD aNewColors[2];

aOldColors[0] = GetSysColor(aElements[0]); 
aOldColors[1] = GetSysColor(aElements[1]); 
aNewColors[0] = RGB(0x80, 0x80, 0x80);  // light gray 
aNewColors[1] = RGB(0x80, 0x00, 0x80);  // dark purple 

SetSysColors(2, aElements, aNewColors);
SetSysColors(2, aElements, aOldColors);

Thanks in advance

EDIT

This is exactly what I want:

enter image description here

Alpay
  • 1,350
  • 2
  • 24
  • 56
  • 5
    If you're on Windows 10 you're stuck with a big blob of white. – Jonathan Potter Aug 31 '15 at 11:39
  • 1
    Windows 8.1 for the time being. I forgot to mention that thank you :) – Alpay Aug 31 '15 at 11:48
  • Override `NC_PAINT` and draw the title bar yourself. You can use `DrawFrameControl` to draw all the buttons and whatever else is needed. – Brandon Aug 31 '15 at 13:20
  • 3
    @Brandon: Have you used Microsoft Office lately? There's more to rendering the non-client area of a window than a call to `DrawFrameControl`. Ignoring themes is not very good style either. – IInspectable Aug 31 '15 at 13:50
  • 3
    Raymond Chen says this better than I could: [Don't use global state to manage a local problem](http://blogs.msdn.com/b/oldnewthing/archive/2008/12/11/9193695.aspx) Also, [What if two programs did this?](http://blogs.msdn.com/b/oldnewthing/archive/2005/06/07/426294.aspx) – theB Aug 31 '15 at 14:42
  • It is possible. Two ways: 1. firefox way. dwmextended to the client. draw title bar yourself with drawthemebackground... or drawframecontrol. 2. remove the title bar anddraw all the content yourself. – Jichao Sep 01 '15 at 07:09
  • @Jichao I just want to play with the color of borders and title bar. Can you suggest me any example? – Alpay Sep 01 '15 at 08:43
  • 1
    But it is not easy to custom the title bar color. https://msdn.microsoft.com/en-us/library/windows/desktop/bb688195(v=vs.85).aspx http://www.catch22.net/tuts/custom-titlebar – Jichao Sep 01 '15 at 10:07
  • 1
    have you tried COLOR_WINDOW+1 and COLOR_ACTIVECAPTION+1 instead? – AndersK Sep 02 '15 at 11:35
  • 1
    I tried that one, but it didn' t change caption color :( – Alpay Sep 02 '15 at 11:59
  • The only way I know is to implement all of `WM_NCPAINT` yourself, but that's not trivial. – Mark Ransom Sep 03 '15 at 03:08
  • Ok I understood this, I searched over internet for days, but couldn' t find any example that changes these colors. Do you have any such example? My request is very simple. I only want to change title bar and border colors. – Alpay Sep 03 '15 at 06:48
  • The title bar & border are part of the non-client area, and painted via WM_NCPAINT. There aren't any easy ways to customize it; it's an all-or-nothing deal. – Eric Brown Sep 04 '15 at 20:28
  • Have you tried using the DWM? Similar question (but in C#) can be found here: http://stackoverflow.com/questions/13660976/get-the-active-color-of-windows-8-automatic-color-theme If you can 'get' the color then you can probably 'set' the color. – Jonathan Sep 07 '15 at 09:15
  • Can you explain why this answer is not useful? I clearly mentioned that from this code block you can get some idea. –  Sep 09 '15 at 06:25

3 Answers3

4

I don't recommend to customize border and title redrawing. It's really hard to do it the right way. Office just draws everything by itself in the client area but using normal border. Using NC_PAINT the right way is a pain and may introduce flickering. Especially positioning the minimize,maximize and close buttons is difficult, because every windows does it differently. Also take into account accessibility, larger fonts used, customized user settings.

Whats the purpose of changing the colors?

To change the global colors you have to at least separate your code

// call this once at startup of your application (e.g. in WM_CREATE)

SetSysColors(2, aElements, aNewColors); 

// call this when closing you application (e.g. in WM_DESTROY)

SetSysColors(2, aElements, aOldColors); 
lexx9999
  • 736
  • 3
  • 9
3

I know you are using C++, but I am handy with C#. So that you may get some idea, take look at the following code, which modifies form appearance.

[DllImport("User32.dll", CharSet = CharSet.Auto)]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);

[DllImport("User32.dll")]
private static extern IntPtr GetWindowDC(IntPtr hWnd);

protected override void WndProc(ref Message m)
{
    base.WndProc(ref m);
    const int WM_NCPAINT = 0x85;
    if (m.Msg == WM_NCPAINT)
    {
        IntPtr hdc = GetWindowDC(m.HWnd);
        if ((int)hdc != 0)
        {
            Graphics g = Graphics.FromHdc(hdc);
            g.FillRectangle(Brushes.Green, new Rectangle(0, 0, 4800, 23));
            g.Flush();
            ReleaseDC(m.HWnd, hdc);
        }
    }
}

Also, you could use the Drawing Custom Borders in Windows Forms project from CodePlex. This project is a tiny library that allows users to customize Windows Forms, like customizing a windows' non-client area.

gustafbstrom
  • 1,622
  • 4
  • 25
  • 44
  • Can you explain why this answer is not useful? I clearly mentioned that from this code block you can get some idea. –  Sep 09 '15 at 06:24
  • Mark as answer if this suggestion is helpful. –  Sep 09 '15 at 11:15
  • 2
    Disclaimer: I've cast no vote. However, reasons I imagine this answer has been beaten-up include **(a)** No return value. **(b)** Calls the rough equivalent of DefWindowProc before painting over - does this not obscure the buttons? **(c)** Makes no reference to the HRGN passed with the WM_NCPAINT **(d)** uses hard-coded values for the size of the rect to paint (and also paints over the client area) **(e)** code really very different to C++ code, the use of the GDI+ Graphics class is almost the only thing in common. **(f)** appears to be for rep points for you rather than an answer for the OP. – enhzflep Sep 09 '15 at 11:27
  • 1
    This code just doesn' t do anything in Win8.1. I saw this approach on the internet and tried this one, but Desktop Window Manager doesn' t allow this kind of code to make any change on the window titles, or borders (Actually any non-client area object) I believe this won' t do anything on the systems running Vista or higher – Alpay Sep 09 '15 at 12:29
  • This answer is just give some idea regrading customizing form title bar. Please look at http://www.geekswithblogs.net/kobush/articles/CustomBorderForms.aspx again I am not that much handy with C++ so sharing other language example. –  Sep 09 '15 at 12:37
  • Programming language is not important, but this article is from 2005, and Windows no longer supports changing non-client area stuff like that. They produced DWM api for these things. Therefore, your answer unfortunately does not give any appropriate idea. Thanks anyway – Alpay Sep 09 '15 at 12:53
2

Remove the second SetSysColors(2, aElements, aOldColors); line of code, which reverts back to the orignal color and then try again. The code example you have seems almost identical to the MSDN link https://msdn.microsoft.com/en-us/library/windows/desktop/ms724940%28v=vs.85%29.aspx link minus the sleep. Their example shows how to set color, sleeps and then reverts back.

Joe
  • 21
  • 2