2 * Support for system colors
4 * Copyright David W. Metcalfe, 1993
5 * Copyright Alexandre Julliard, 1994
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include "wine/winbase16.h"
31 #include "wine/winuser16.h"
36 #include "gdi.h" /* sic */
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(syscolor
);
41 static const char * const DefSysColors
[] =
43 "Scrollbar", "192 192 192", /* COLOR_SCROLLBAR */
44 "Background", "0 128 128", /* COLOR_BACKGROUND */
45 "ActiveTitle", "0 0 128", /* COLOR_ACTIVECAPTION */
46 "InactiveTitle", "128 128 128", /* COLOR_INACTIVECAPTION */
47 "Menu", "192 192 192", /* COLOR_MENU */
48 "Window", "255 255 255", /* COLOR_WINDOW */
49 "WindowFrame", "0 0 0", /* COLOR_WINDOWFRAME */
50 "MenuText", "0 0 0", /* COLOR_MENUTEXT */
51 "WindowText", "0 0 0", /* COLOR_WINDOWTEXT */
52 "TitleText", "255 255 255", /* COLOR_CAPTIONTEXT */
53 "ActiveBorder", "192 192 192", /* COLOR_ACTIVEBORDER */
54 "InactiveBorder", "192 192 192", /* COLOR_INACTIVEBORDER */
55 "AppWorkSpace", "128 128 128", /* COLOR_APPWORKSPACE */
56 "Hilight", "0 0 128", /* COLOR_HIGHLIGHT */
57 "HilightText", "255 255 255", /* COLOR_HIGHLIGHTTEXT */
58 "ButtonFace", "192 192 192", /* COLOR_BTNFACE */
59 "ButtonShadow", "128 128 128", /* COLOR_BTNSHADOW */
60 "GrayText", "128 128 128", /* COLOR_GRAYTEXT */
61 "ButtonText", "0 0 0", /* COLOR_BTNTEXT */
62 "InactiveTitleText", "192 192 192",/* COLOR_INACTIVECAPTIONTEXT */
63 "ButtonHilight", "255 255 255", /* COLOR_BTNHIGHLIGHT */
64 "ButtonDkShadow", "0 0 0", /* COLOR_3DDKSHADOW */
65 "ButtonLight", "224 224 224", /* COLOR_3DLIGHT */
66 "InfoText", "0 0 0", /* COLOR_INFOTEXT */
67 "InfoWindow", "255 255 225", /* COLOR_INFOBK */
68 "ButtonAlternateFace", "180 180 180", /* COLOR_ALTERNATEBTNFACE */
69 "HotTrackingColor", "0 0 255", /* COLOR_HOTLIGHT */
70 "GradientActiveTitle", "16 132 208", /* COLOR_GRADIENTACTIVECAPTION */
71 "GradientInactiveTitle", "181 181 181",/* COLOR_GRADIENTINACTIVECAPTION */
72 "MenuHilight", "0 0 0", /* COLOR_MENUHILIGHT */
73 "MenuBar", "192 192 192" /* COLOR_MENUBAR */
77 #define NUM_SYS_COLORS (COLOR_MENUBAR+1)
79 static COLORREF SysColors
[NUM_SYS_COLORS
];
80 static HBRUSH SysColorBrushes
[NUM_SYS_COLORS
];
81 static HPEN SysColorPens
[NUM_SYS_COLORS
];
84 /*************************************************************************
85 * SYSCOLOR_MakeObjectSystem
87 * OK, now for a very ugly hack.
88 * USER somehow has to tell GDI that its system brushes and pens are
90 * We don't want to export a function from GDI doing this for us,
91 * so we just do that ourselves by "wildly flipping some bits in memory".
92 * For a description of the GDI object magics and their flags,
93 * see "Undocumented Windows" (wrong about the OBJECT_NOSYSTEM flag, though).
95 static void SYSCOLOR_MakeObjectSystem( HGDIOBJ16 handle
, BOOL set
)
97 static WORD heap_sel
= 0;
100 if (!heap_sel
) heap_sel
= LoadLibrary16( "gdi" );
103 ptr
= (LPWORD
)LOCAL_Lock(heap_sel
, handle
);
105 /* touch the "system" bit of the wMagic field of a GDIOBJHDR */
107 *(ptr
+1) &= ~OBJECT_NOSYSTEM
;
109 *(ptr
+1) |= OBJECT_NOSYSTEM
;
110 LOCAL_Unlock( heap_sel
, handle
);
114 /*************************************************************************
117 static void SYSCOLOR_SetColor( int index
, COLORREF color
)
119 if (index
< 0 || index
>= NUM_SYS_COLORS
) return;
120 SysColors
[index
] = color
;
121 if (SysColorBrushes
[index
])
123 SYSCOLOR_MakeObjectSystem( HBRUSH_16(SysColorBrushes
[index
]), FALSE
);
124 DeleteObject( SysColorBrushes
[index
] );
126 SysColorBrushes
[index
] = CreateSolidBrush( color
);
127 SYSCOLOR_MakeObjectSystem( HBRUSH_16(SysColorBrushes
[index
]), TRUE
);
129 if (SysColorPens
[index
])
131 SYSCOLOR_MakeObjectSystem( HPEN_16(SysColorPens
[index
]), FALSE
);
132 DeleteObject( SysColorPens
[index
] );
134 SysColorPens
[index
] = CreatePen( PS_SOLID
, 1, color
);
135 SYSCOLOR_MakeObjectSystem( HPEN_16(SysColorPens
[index
]), TRUE
);
139 /*************************************************************************
142 void SYSCOLOR_Init(void)
146 BOOL bOk
= FALSE
, bNoReg
= FALSE
;
149 /* first, try to read the values from the registry */
150 if (RegCreateKeyExA(HKEY_CURRENT_USER
, "Control Panel\\Colors", 0, 0, 0, KEY_ALL_ACCESS
, 0, &hKey
, 0))
152 for (i
= 0; i
< NUM_SYS_COLORS
; i
++)
155 /* first try, registry */
158 DWORD dwDataSize
= sizeof(buffer
);
159 if (!(RegQueryValueExA(hKey
,DefSysColors
[i
*2], 0, 0, buffer
, &dwDataSize
)))
160 if (sscanf( buffer
, "%d %d %d", &r
, &g
, &b
) == 3)
164 /* second try, win.ini */
166 { GetProfileStringA( "colors", DefSysColors
[i
*2], DefSysColors
[i
*2+1], buffer
, 100 );
167 if (sscanf( buffer
, " %d %d %d", &r
, &g
, &b
) == 3)
171 /* last chance, take the default */
173 { int iNumColors
= sscanf( DefSysColors
[i
*2+1], " %d %d %d", &r
, &g
, &b
);
174 assert (iNumColors
==3);
177 SYSCOLOR_SetColor( i
, RGB(r
,g
,b
) );
184 /*************************************************************************
185 * GetSysColor (USER32.@)
187 COLORREF WINAPI
GetSysColor( INT nIndex
)
189 if (nIndex
>= 0 && nIndex
< NUM_SYS_COLORS
)
190 return SysColors
[nIndex
];
196 /*************************************************************************
197 * SetSysColors (USER32.@)
199 BOOL WINAPI
SetSysColors( INT nChanges
, const INT
*lpSysColor
,
200 const COLORREF
*lpColorValues
)
204 for (i
= 0; i
< nChanges
; i
++)
206 SYSCOLOR_SetColor( lpSysColor
[i
], lpColorValues
[i
] );
209 /* Send WM_SYSCOLORCHANGE message to all windows */
211 SendMessageTimeoutW( HWND_BROADCAST
, WM_SYSCOLORCHANGE
, 0, 0,
212 SMTO_ABORTIFHUNG
, 2000, NULL
);
214 /* Repaint affected portions of all visible windows */
216 RedrawWindow( GetDesktopWindow(), NULL
, 0,
217 RDW_INVALIDATE
| RDW_ERASE
| RDW_UPDATENOW
| RDW_ALLCHILDREN
);
221 /*************************************************************************
222 * SetSysColorsTemp (USER32.@)
226 * Called by W98SE desk.cpl Control Panel Applet:
227 * handle = SetSysColorsTemp(ptr, ptr, nCount); ("set" call)
228 * result = SetSysColorsTemp(NULL, NULL, handle); ("restore" call)
230 * pPens is an array of COLORREF values, which seems to be used
231 * to indicate the color values to create new pens with.
233 * pBrushes is an array of solid brush handles (returned by a previous
234 * CreateSolidBrush), which seems to contain the brush handles to set
235 * for the system colors.
237 * n seems to be used for
238 * a) indicating the number of entries to operate on (length of pPens,
240 * b) passing the handle that points to the previously used color settings.
241 * I couldn't figure out in hell what kind of handle this is on
242 * Windows. I just use a heap handle instead. Shouldn't matter anyway.
245 * heap handle of our own copy of the current syscolors in case of
246 * "set" call, i.e. pPens, pBrushes != NULL.
247 * TRUE (unconditionally !) in case of "restore" call,
248 * i.e. pPens, pBrushes == NULL.
249 * FALSE in case of either pPens != NULL and pBrushes == NULL
250 * or pPens == NULL and pBrushes != NULL.
252 * I'm not sure whether this implementation is 100% correct. [AM]
254 DWORD WINAPI
SetSysColorsTemp( const COLORREF
*pPens
, const HBRUSH
*pBrushes
, DWORD n
)
258 if (pPens
&& pBrushes
) /* "set" call */
260 /* allocate our structure to remember old colors */
261 LPVOID pOldCol
= HeapAlloc(GetProcessHeap(), 0, sizeof(DWORD
)+n
*sizeof(HPEN
)+n
*sizeof(HBRUSH
));
263 *(DWORD
*)p
= n
; p
= (char*)p
+ sizeof(DWORD
);
264 memcpy(p
, SysColorPens
, n
*sizeof(HPEN
)); p
= (char*)p
+ n
*sizeof(HPEN
);
265 memcpy(p
, SysColorBrushes
, n
*sizeof(HBRUSH
)); p
= (char*)p
+ n
*sizeof(HBRUSH
);
267 for (i
=0; i
< n
; i
++)
269 SysColorPens
[i
] = CreatePen( PS_SOLID
, 1, pPens
[i
] );
270 SysColorBrushes
[i
] = pBrushes
[i
];
273 return (DWORD
)pOldCol
;
275 if ((!pPens
) && (!pBrushes
)) /* "restore" call */
277 LPVOID pOldCol
= (LPVOID
)n
;
279 DWORD nCount
= *(DWORD
*)p
;
280 p
= (char*)p
+ sizeof(DWORD
);
282 for (i
=0; i
< nCount
; i
++)
284 DeleteObject(SysColorPens
[i
]);
285 SysColorPens
[i
] = *(HPEN
*)p
; p
= (char*)p
+ sizeof(HPEN
);
287 for (i
=0; i
< nCount
; i
++)
289 SysColorBrushes
[i
] = *(HBRUSH
*)p
; p
= (char*)p
+ sizeof(HBRUSH
);
291 /* get rid of storage structure */
292 HeapFree(GetProcessHeap(), 0, pOldCol
);
299 /***********************************************************************
300 * GetSysColorBrush (USER32.@)
302 HBRUSH WINAPI
GetSysColorBrush( INT index
)
304 if (0 <= index
&& index
< NUM_SYS_COLORS
)
305 return SysColorBrushes
[index
];
306 WARN("Unknown index(%d)\n", index
);
307 return GetStockObject(LTGRAY_BRUSH
);
311 /***********************************************************************
314 HPEN
SYSCOLOR_GetPen( INT index
)
316 /* We can assert here, because this function is internal to Wine */
317 assert (0 <= index
&& index
< NUM_SYS_COLORS
);
318 return SysColorPens
[index
];