Added missing RemoveProp calls.
[wine] / dlls / comctl32 / commctrl.c
1 /*
2  * Common controls functions
3  *
4  * Copyright 1997 Dimitrie O. Paun
5  * Copyright 1998,2000 Eric Kohl
6  *
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.
11  *
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.
16  *
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
20  */
21
22 #include <string.h>
23 #include <stdlib.h>
24
25 #include "winbase.h"
26 #include "commctrl.h"
27 #include "winerror.h"
28 #include "winreg.h"
29 #define NO_SHLWAPI_STREAM
30 #include "shlwapi.h"
31 #include "comctl32.h"
32 #include "wine/debug.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(commctrl);
35
36 extern void ANIMATE_Register(void);
37 extern void ANIMATE_Unregister(void);
38 extern void COMBOEX_Register(void);
39 extern void COMBOEX_Unregister(void);
40 extern void DATETIME_Register(void);
41 extern void DATETIME_Unregister(void);
42 extern void FLATSB_Register(void);
43 extern void FLATSB_Unregister(void);
44 extern void HEADER_Register(void);
45 extern void HEADER_Unregister(void);
46 extern void HOTKEY_Register(void);
47 extern void HOTKEY_Unregister(void);
48 extern void IPADDRESS_Register(void);
49 extern void IPADDRESS_Unregister(void);
50 extern void LISTVIEW_Register(void);
51 extern void LISTVIEW_Unregister(void);
52 extern void MONTHCAL_Register(void);
53 extern void MONTHCAL_Unregister(void);
54 extern void NATIVEFONT_Register(void);
55 extern void NATIVEFONT_Unregister(void);
56 extern void PAGER_Register(void);
57 extern void PAGER_Unregister(void);
58 extern void PROGRESS_Register(void);
59 extern void PROGRESS_Unregister(void);
60 extern void REBAR_Register(void);
61 extern void REBAR_Unregister(void);
62 extern void STATUS_Register(void);
63 extern void STATUS_Unregister(void);
64 extern void TAB_Register(void);
65 extern void TAB_Unregister(void);
66 extern void TOOLBAR_Register(void);
67 extern void TOOLBAR_Unregister(void);
68 extern void TOOLTIPS_Register(void);
69 extern void TOOLTIPS_Unregister(void);
70 extern void TRACKBAR_Register(void);
71 extern void TRACKBAR_Unregister(void);
72 extern void TREEVIEW_Register(void);
73 extern void TREEVIEW_Unregister(void);
74 extern void UPDOWN_Register(void);
75 extern void UPDOWN_Unregister(void);
76
77
78 HANDLE COMCTL32_hHeap = (HANDLE)NULL;
79 LPSTR    COMCTL32_aSubclass = (LPSTR)NULL;
80 HMODULE COMCTL32_hModule = 0;
81 LANGID  COMCTL32_uiLang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
82 HBRUSH  COMCTL32_hPattern55AABrush = (HANDLE)NULL;
83 COMCTL32_SysColor  comctl32_color;
84
85 static HBITMAP COMCTL32_hPattern55AABitmap = (HANDLE)NULL;
86
87 static const WORD wPattern55AA[] =
88 {
89     0x5555, 0xaaaa, 0x5555, 0xaaaa,
90     0x5555, 0xaaaa, 0x5555, 0xaaaa
91 };
92
93
94 /***********************************************************************
95  * COMCTL32_LibMain [Internal] Initializes the internal 'COMCTL32.DLL'.
96  *
97  * PARAMS
98  *     hinstDLL    [I] handle to the 'dlls' instance
99  *     fdwReason   [I]
100  *     lpvReserved [I] reserverd, must be NULL
101  *
102  * RETURNS
103  *     Success: TRUE
104  *     Failure: FALSE
105  */
106
107 BOOL WINAPI
108 COMCTL32_LibMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
109 {
110     TRACE("%x,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
111
112     switch (fdwReason) {
113         case DLL_PROCESS_ATTACH:
114             COMCTL32_hModule = (HMODULE)hinstDLL;
115
116             /* create private heap */
117             COMCTL32_hHeap = HeapCreate (0, 0x10000, 0);
118             TRACE("Heap created: 0x%x\n", COMCTL32_hHeap);
119
120             /* add global subclassing atom (used by 'tooltip' and 'updown') */
121             COMCTL32_aSubclass = (LPSTR)(DWORD)GlobalAddAtomA ("CC32SubclassInfo");
122             TRACE("Subclassing atom added: %p\n", COMCTL32_aSubclass);
123
124             /* create local pattern brush */
125             COMCTL32_hPattern55AABitmap = CreateBitmap (8, 8, 1, 1, wPattern55AA);
126             COMCTL32_hPattern55AABrush = CreatePatternBrush (COMCTL32_hPattern55AABitmap);
127
128             /* Get all the colors at DLL load */
129             COMCTL32_RefreshSysColors();
130
131             /* register all Win95 common control classes */
132             ANIMATE_Register ();
133             FLATSB_Register ();
134             HEADER_Register ();
135             HOTKEY_Register ();
136             LISTVIEW_Register ();
137             PROGRESS_Register ();
138             STATUS_Register ();
139             TAB_Register ();
140             TOOLBAR_Register ();
141             TOOLTIPS_Register ();
142             TRACKBAR_Register ();
143             TREEVIEW_Register ();
144             UPDOWN_Register ();
145             break;
146
147         case DLL_PROCESS_DETACH:
148             /* unregister all common control classes */
149             ANIMATE_Unregister ();
150             COMBOEX_Unregister ();
151             DATETIME_Unregister ();
152             FLATSB_Unregister ();
153             HEADER_Unregister ();
154             HOTKEY_Unregister ();
155             IPADDRESS_Unregister ();
156             LISTVIEW_Unregister ();
157             MONTHCAL_Unregister ();
158             NATIVEFONT_Unregister ();
159             PAGER_Unregister ();
160             PROGRESS_Unregister ();
161             REBAR_Unregister ();
162             STATUS_Unregister ();
163             TAB_Unregister ();
164             TOOLBAR_Unregister ();
165             TOOLTIPS_Unregister ();
166             TRACKBAR_Unregister ();
167             TREEVIEW_Unregister ();
168             UPDOWN_Unregister ();
169
170             /* delete local pattern brush */
171             DeleteObject (COMCTL32_hPattern55AABrush);
172             COMCTL32_hPattern55AABrush = (HANDLE)NULL;
173             DeleteObject (COMCTL32_hPattern55AABitmap);
174             COMCTL32_hPattern55AABitmap = (HANDLE)NULL;
175
176             /* delete global subclassing atom */
177             GlobalDeleteAtom (LOWORD(COMCTL32_aSubclass));
178             TRACE("Subclassing atom deleted: %p\n", COMCTL32_aSubclass);
179             COMCTL32_aSubclass = (LPSTR)NULL;
180
181             /* destroy private heap */
182             HeapDestroy (COMCTL32_hHeap);
183             TRACE("Heap destroyed: 0x%x\n", COMCTL32_hHeap);
184             COMCTL32_hHeap = (HANDLE)NULL;
185             break;
186     }
187
188     return TRUE;
189 }
190
191
192 /***********************************************************************
193  * MenuHelp [COMCTL32.2]
194  *
195  * PARAMS
196  *     uMsg       [I] message (WM_MENUSELECT) (see NOTES)
197  *     wParam     [I] wParam of the message uMsg
198  *     lParam     [I] lParam of the message uMsg
199  *     hMainMenu  [I] handle to the application's main menu
200  *     hInst      [I] handle to the module that contains string resources
201  *     hwndStatus [I] handle to the status bar window
202  *     lpwIDs     [I] pointer to an array of integers (see NOTES)
203  *
204  * RETURNS
205  *     No return value
206  *
207  * NOTES
208  *     The official documentation is incomplete!
209  *     This is the correct documentation:
210  *
211  *     uMsg:
212  *     MenuHelp() does NOT handle WM_COMMAND messages! It only handles
213  *     WM_MENUSELECT messages.
214  *
215  *     lpwIDs:
216  *     (will be written ...)
217  */
218
219 VOID WINAPI
220 MenuHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu,
221           HINSTANCE hInst, HWND hwndStatus, UINT* lpwIDs)
222 {
223     UINT uMenuID = 0;
224
225     if (!IsWindow (hwndStatus))
226         return;
227
228     switch (uMsg) {
229         case WM_MENUSELECT:
230             TRACE("WM_MENUSELECT wParam=0x%X lParam=0x%lX\n",
231                    wParam, lParam);
232
233             if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {
234                 /* menu was closed */
235                 TRACE("menu was closed!\n");
236                 SendMessageA (hwndStatus, SB_SIMPLE, FALSE, 0);
237             }
238             else {
239                 /* menu item was selected */
240                 if (HIWORD(wParam) & MF_POPUP)
241                     uMenuID = (UINT)*(lpwIDs+1);
242                 else
243                     uMenuID = (UINT)LOWORD(wParam);
244                 TRACE("uMenuID = %u\n", uMenuID);
245
246                 if (uMenuID) {
247                     CHAR szText[256];
248
249                     if (!LoadStringA (hInst, uMenuID, szText, 256))
250                         szText[0] = '\0';
251
252                     SendMessageA (hwndStatus, SB_SETTEXTA,
253                                     255 | SBT_NOBORDERS, (LPARAM)szText);
254                     SendMessageA (hwndStatus, SB_SIMPLE, TRUE, 0);
255                 }
256             }
257             break;
258
259         case WM_COMMAND :
260             TRACE("WM_COMMAND wParam=0x%X lParam=0x%lX\n",
261                    wParam, lParam);
262             /* WM_COMMAND is not invalid since it is documented
263              * in the windows api reference. So don't output
264              * any FIXME for WM_COMMAND
265              */
266             WARN("We don't care about the WM_COMMAND\n");
267             break;
268
269         default:
270             FIXME("Invalid Message 0x%x!\n", uMsg);
271             break;
272     }
273 }
274
275
276 /***********************************************************************
277  * ShowHideMenuCtl [COMCTL32.3]
278  *
279  * Shows or hides controls and updates the corresponding menu item.
280  *
281  * PARAMS
282  *     hwnd   [I] handle to the client window.
283  *     uFlags [I] menu command id.
284  *     lpInfo [I] pointer to an array of integers. (See NOTES.)
285  *
286  * RETURNS
287  *     Success: TRUE
288  *     Failure: FALSE
289  *
290  * NOTES
291  *     The official documentation is incomplete!
292  *     This is the correct documentation:
293  *
294  *     hwnd
295  *     Handle to the window that contains the menu and controls.
296  *
297  *     uFlags
298  *     Identifier of the menu item to receive or loose a check mark.
299  *
300  *     lpInfo
301  *     The array of integers contains pairs of values. BOTH values of
302  *     the first pair must be the handles to the application's main menu.
303  *     Each subsequent pair consists of a menu id and control id.
304  */
305
306 BOOL WINAPI
307 ShowHideMenuCtl (HWND hwnd, UINT uFlags, LPINT lpInfo)
308 {
309     LPINT lpMenuId;
310
311     TRACE("%x, %x, %p\n", hwnd, uFlags, lpInfo);
312
313     if (lpInfo == NULL)
314         return FALSE;
315
316     if (!(lpInfo[0]) || !(lpInfo[1]))
317         return FALSE;
318
319     /* search for control */
320     lpMenuId = &lpInfo[2];
321     while (*lpMenuId != uFlags)
322         lpMenuId += 2;
323
324     if (GetMenuState (lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) {
325         /* uncheck menu item */
326         CheckMenuItem (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_UNCHECKED);
327
328         /* hide control */
329         lpMenuId++;
330         SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
331                         SWP_HIDEWINDOW);
332     }
333     else {
334         /* check menu item */
335         CheckMenuItem (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_CHECKED);
336
337         /* show control */
338         lpMenuId++;
339         SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
340                         SWP_SHOWWINDOW);
341     }
342
343     return TRUE;
344 }
345
346
347 /***********************************************************************
348  * GetEffectiveClientRect [COMCTL32.4]
349  *
350  * PARAMS
351  *     hwnd   [I] handle to the client window.
352  *     lpRect [O] pointer to the rectangle of the client window
353  *     lpInfo [I] pointer to an array of integers (see NOTES)
354  *
355  * RETURNS
356  *     No return value.
357  *
358  * NOTES
359  *     The official documentation is incomplete!
360  *     This is the correct documentation:
361  *
362  *     lpInfo
363  *     (will be written...)
364  */
365
366 VOID WINAPI
367 GetEffectiveClientRect (HWND hwnd, LPRECT lpRect, LPINT lpInfo)
368 {
369     RECT rcCtrl;
370     INT  *lpRun;
371     HWND hwndCtrl;
372
373     TRACE("(0x%08lx 0x%08lx 0x%08lx)\n",
374            (DWORD)hwnd, (DWORD)lpRect, (DWORD)lpInfo);
375
376     GetClientRect (hwnd, lpRect);
377     lpRun = lpInfo;
378
379     do {
380         lpRun += 2;
381         if (*lpRun == 0)
382             return;
383         lpRun++;
384         hwndCtrl = GetDlgItem (hwnd, *lpRun);
385         if (GetWindowLongA (hwndCtrl, GWL_STYLE) & WS_VISIBLE) {
386             TRACE("control id 0x%x\n", *lpRun);
387             GetWindowRect (hwndCtrl, &rcCtrl);
388             MapWindowPoints ((HWND)0, hwnd, (LPPOINT)&rcCtrl, 2);
389             SubtractRect (lpRect, lpRect, &rcCtrl);
390         }
391         lpRun++;
392     } while (*lpRun);
393 }
394
395
396 /***********************************************************************
397  * DrawStatusTextW [COMCTL32.@]
398  *
399  * Draws text with borders, like in a status bar.
400  *
401  * PARAMS
402  *     hdc   [I] handle to the window's display context
403  *     lprc  [I] pointer to a rectangle
404  *     text  [I] pointer to the text
405  *     style [I] drawing style
406  *
407  * RETURNS
408  *     No return value.
409  *
410  * NOTES
411  *     The style variable can have one of the following values:
412  *     (will be written ...)
413  */
414
415 void WINAPI DrawStatusTextW (HDC hdc, LPRECT lprc, LPCWSTR text, UINT style)
416 {
417     RECT r = *lprc;
418     UINT border = BDR_SUNKENOUTER;
419
420     if (style & SBT_POPOUT)
421         border = BDR_RAISEDOUTER;
422     else if (style & SBT_NOBORDERS)
423         border = 0;
424
425     DrawEdge (hdc, &r, border, BF_RECT|BF_ADJUST);
426
427     /* now draw text */
428     if (text) {
429         int oldbkmode = SetBkMode (hdc, TRANSPARENT);
430         UINT align = DT_LEFT;
431         if (*text == L'\t') {
432             text++;
433             align = DT_CENTER;
434             if (*text == L'\t') {
435                 text++;
436                 align = DT_RIGHT;
437             }
438         }
439         r.left += 3;
440         if (style & SBT_RTLREADING)
441             FIXME("Unsupported RTL style!\n");
442         DrawTextW (hdc, text, -1, &r, align|DT_VCENTER|DT_SINGLELINE);
443         SetBkMode(hdc, oldbkmode);
444     }
445 }
446
447
448 /***********************************************************************
449  * DrawStatusText  [COMCTL32.@]
450  * DrawStatusTextA [COMCTL32.5]
451  *
452  * Draws text with borders, like in a status bar.
453  *
454  * PARAMS
455  *     hdc   [I] handle to the window's display context
456  *     lprc  [I] pointer to a rectangle
457  *     text  [I] pointer to the text
458  *     style [I] drawing style
459  *
460  * RETURNS
461  *     No return value.
462  */
463
464 void WINAPI DrawStatusTextA (HDC hdc, LPRECT lprc, LPCSTR text, UINT style)
465 {
466     INT len;
467     LPWSTR textW = NULL;
468
469     if ( text ) {
470         if ( (len = MultiByteToWideChar( CP_ACP, 0, text, -1, NULL, 0 )) ) {
471             if ( (textW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )) )
472                 MultiByteToWideChar( CP_ACP, 0, text, -1, textW, len );
473         }
474     }
475     DrawStatusTextW( hdc, lprc, textW, style );
476     HeapFree( GetProcessHeap(), 0, textW );
477 }
478
479
480 /***********************************************************************
481  * CreateStatusWindow  [COMCTL32.@]
482  * CreateStatusWindowA [COMCTL32.6]
483  *
484  * Creates a status bar
485  *
486  * PARAMS
487  *     style  [I] window style
488  *     text   [I] pointer to the window text
489  *     parent [I] handle to the parent window
490  *     wid    [I] control id of the status bar
491  *
492  * RETURNS
493  *     Success: handle to the status window
494  *     Failure: 0
495  */
496
497 HWND WINAPI
498 CreateStatusWindowA (INT style, LPCSTR text, HWND parent, UINT wid)
499 {
500     return CreateWindowA(STATUSCLASSNAMEA, text, style,
501                            CW_USEDEFAULT, CW_USEDEFAULT,
502                            CW_USEDEFAULT, CW_USEDEFAULT,
503                            parent, wid, 0, 0);
504 }
505
506
507 /***********************************************************************
508  * CreateStatusWindowW [COMCTL32.@] Creates a status bar control
509  *
510  * PARAMS
511  *     style  [I] window style
512  *     text   [I] pointer to the window text
513  *     parent [I] handle to the parent window
514  *     wid    [I] control id of the status bar
515  *
516  * RETURNS
517  *     Success: handle to the status window
518  *     Failure: 0
519  */
520
521 HWND WINAPI
522 CreateStatusWindowW (INT style, LPCWSTR text, HWND parent, UINT wid)
523 {
524     return CreateWindowW(STATUSCLASSNAMEW, text, style,
525                            CW_USEDEFAULT, CW_USEDEFAULT,
526                            CW_USEDEFAULT, CW_USEDEFAULT,
527                            parent, wid, 0, 0);
528 }
529
530
531 /***********************************************************************
532  * CreateUpDownControl [COMCTL32.16] Creates an up-down control
533  *
534  * PARAMS
535  *     style  [I] window styles
536  *     x      [I] horizontal position of the control
537  *     y      [I] vertical position of the control
538  *     cx     [I] with of the control
539  *     cy     [I] height of the control
540  *     parent [I] handle to the parent window
541  *     id     [I] the control's identifier
542  *     inst   [I] handle to the application's module instance
543  *     buddy  [I] handle to the buddy window, can be NULL
544  *     maxVal [I] upper limit of the control
545  *     minVal [I] lower limit of the control
546  *     curVal [I] current value of the control
547  *
548  * RETURNS
549  *     Success: handle to the updown control
550  *     Failure: 0
551  */
552
553 HWND WINAPI
554 CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
555                      HWND parent, INT id, HINSTANCE inst,
556                      HWND buddy, INT maxVal, INT minVal, INT curVal)
557 {
558     HWND hUD =
559         CreateWindowA (UPDOWN_CLASSA, 0, style, x, y, cx, cy,
560                          parent, id, inst, 0);
561     if (hUD) {
562         SendMessageA (hUD, UDM_SETBUDDY, (WPARAM)buddy, 0);
563         SendMessageA (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));
564         SendMessageA (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));
565     }
566
567     return hUD;
568 }
569
570
571 /***********************************************************************
572  * InitCommonControls [COMCTL32.17]
573  *
574  * Registers the common controls.
575  *
576  * PARAMS
577  *     No parameters.
578  *
579  * RETURNS
580  *     No return values.
581  *
582  * NOTES
583  *     This function is just a dummy.
584  *     The Win95 controls are registered at the DLL's initialization.
585  *     To register other controls InitCommonControlsEx() must be used.
586  */
587
588 VOID WINAPI
589 InitCommonControls (void)
590 {
591 }
592
593
594 /***********************************************************************
595  * InitCommonControlsEx [COMCTL32.@]
596  *
597  * Registers the common controls.
598  *
599  * PARAMS
600  *     lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
601  *
602  * RETURNS
603  *     Success: TRUE
604  *     Failure: FALSE
605  *
606  * NOTES
607  *     Only the additional common controls are registered by this function.
608  *     The Win95 controls are registered at the DLL's initialization.
609  */
610
611 BOOL WINAPI
612 InitCommonControlsEx (LPINITCOMMONCONTROLSEX lpInitCtrls)
613 {
614     INT cCount;
615     DWORD dwMask;
616
617     if (!lpInitCtrls)
618         return FALSE;
619     if (lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
620         return FALSE;
621
622     TRACE("(0x%08lx)\n", lpInitCtrls->dwICC);
623
624     for (cCount = 0; cCount < 32; cCount++) {
625         dwMask = 1 << cCount;
626         if (!(lpInitCtrls->dwICC & dwMask))
627             continue;
628
629         switch (lpInitCtrls->dwICC & dwMask) {
630             /* dummy initialization */
631             case ICC_ANIMATE_CLASS:
632             case ICC_BAR_CLASSES:
633             case ICC_LISTVIEW_CLASSES:
634             case ICC_TREEVIEW_CLASSES:
635             case ICC_TAB_CLASSES:
636             case ICC_UPDOWN_CLASS:
637             case ICC_PROGRESS_CLASS:
638             case ICC_HOTKEY_CLASS:
639                 break;
640
641             /* advanced classes - not included in Win95 */
642             case ICC_DATE_CLASSES:
643                 MONTHCAL_Register ();
644                 DATETIME_Register ();
645                 break;
646
647             case ICC_USEREX_CLASSES:
648                 COMBOEX_Register ();
649                 break;
650
651             case ICC_COOL_CLASSES:
652                 REBAR_Register ();
653                 break;
654
655             case ICC_INTERNET_CLASSES:
656                 IPADDRESS_Register ();
657                 break;
658
659             case ICC_PAGESCROLLER_CLASS:
660                 PAGER_Register ();
661                 break;
662
663             case ICC_NATIVEFNTCTL_CLASS:
664                 NATIVEFONT_Register ();
665                 break;
666
667             default:
668                 FIXME("Unknown class! dwICC=0x%lX\n", dwMask);
669                 break;
670         }
671     }
672
673     return TRUE;
674 }
675
676
677 /***********************************************************************
678  * CreateToolbarEx [COMCTL32.@] Creates a tool bar window
679  *
680  * PARAMS
681  *     hwnd
682  *     style
683  *     wID
684  *     nBitmaps
685  *     hBMInst
686  *     wBMID
687  *     lpButtons
688  *     iNumButtons
689  *     dxButton
690  *     dyButton
691  *     dxBitmap
692  *     dyBitmap
693  *     uStructSize
694  *
695  * RETURNS
696  *     Success: handle to the tool bar control
697  *     Failure: 0
698  */
699
700 HWND WINAPI
701 CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
702                  HINSTANCE hBMInst, UINT wBMID, LPCTBBUTTON lpButtons,
703                  INT iNumButtons, INT dxButton, INT dyButton,
704                  INT dxBitmap, INT dyBitmap, UINT uStructSize)
705 {
706     HWND hwndTB;
707
708     /* If not position is specified then put it at the top */
709     if ((style & CCS_BOTTOM) == 0) {
710       style|=CCS_TOP;
711     }
712
713     hwndTB =
714         CreateWindowExA (0, TOOLBARCLASSNAMEA, "", style|WS_CHILD, 0, 0, 0, 0,
715                            hwnd, (HMENU)wID, 0, NULL);
716     if(hwndTB) {
717         TBADDBITMAP tbab;
718
719         SendMessageA (hwndTB, TB_BUTTONSTRUCTSIZE,
720                         (WPARAM)uStructSize, 0);
721
722        /* set bitmap and button size */
723        /*If CreateToolbarEx receives 0, windows sets default values*/
724        if (dxBitmap <= 0)
725            dxBitmap = 16;
726        if (dyBitmap <= 0)
727            dyBitmap = 15;
728        SendMessageA (hwndTB, TB_SETBITMAPSIZE, 0,
729                        MAKELPARAM((WORD)dxBitmap, (WORD)dyBitmap));
730
731        if (dxButton <= 0)
732            dxButton = 24;
733        if (dyButton <= 0)
734            dyButton = 22;
735        SendMessageA (hwndTB, TB_SETBUTTONSIZE, 0,
736                        MAKELPARAM((WORD)dxButton, (WORD)dyButton));
737
738
739         /* add bitmaps */
740         if (nBitmaps > 0)
741         {
742         tbab.hInst = hBMInst;
743         tbab.nID   = wBMID;
744
745         SendMessageA (hwndTB, TB_ADDBITMAP,
746                         (WPARAM)nBitmaps, (LPARAM)&tbab);
747         }
748         /* add buttons */
749         if(iNumButtons > 0)
750         SendMessageA (hwndTB, TB_ADDBUTTONSA,
751                         (WPARAM)iNumButtons, (LPARAM)lpButtons);
752     }
753
754     return hwndTB;
755 }
756
757
758 /***********************************************************************
759  * CreateMappedBitmap [COMCTL32.8]
760  *
761  * PARAMS
762  *     hInstance  [I]
763  *     idBitmap   [I]
764  *     wFlags     [I]
765  *     lpColorMap [I]
766  *     iNumMaps   [I]
767  *
768  * RETURNS
769  *     Success: handle to the new bitmap
770  *     Failure: 0
771  */
772
773 HBITMAP WINAPI
774 CreateMappedBitmap (HINSTANCE hInstance, INT idBitmap, UINT wFlags,
775                     LPCOLORMAP lpColorMap, INT iNumMaps)
776 {
777     HGLOBAL hglb;
778     HRSRC hRsrc;
779     LPBITMAPINFOHEADER lpBitmap, lpBitmapInfo;
780     UINT nSize, nColorTableSize;
781     RGBQUAD *pColorTable;
782     INT iColor, i, iMaps, nWidth, nHeight;
783     HDC hdcScreen;
784     HBITMAP hbm;
785     LPCOLORMAP sysColorMap;
786     COLORREF cRef;
787     COLORMAP internalColorMap[4] =
788         {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
789
790     /* initialize pointer to colortable and default color table */
791     if (lpColorMap) {
792         iMaps = iNumMaps;
793         sysColorMap = lpColorMap;
794     }
795     else {
796         internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT);
797         internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW);
798         internalColorMap[2].to = GetSysColor (COLOR_BTNFACE);
799         internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT);
800         iMaps = 4;
801         sysColorMap = (LPCOLORMAP)internalColorMap;
802     }
803
804     hRsrc = FindResourceA (hInstance, (LPSTR)idBitmap, RT_BITMAPA);
805     if (hRsrc == 0)
806         return 0;
807     hglb = LoadResource (hInstance, hRsrc);
808     if (hglb == 0)
809         return 0;
810     lpBitmap = (LPBITMAPINFOHEADER)LockResource (hglb);
811     if (lpBitmap == NULL)
812         return 0;
813
814     nColorTableSize = (1 << lpBitmap->biBitCount);
815     nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
816     lpBitmapInfo = (LPBITMAPINFOHEADER)GlobalAlloc (GMEM_FIXED, nSize);
817     if (lpBitmapInfo == NULL)
818         return 0;
819     RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);
820
821     pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo)+(UINT)lpBitmapInfo->biSize);
822
823     for (iColor = 0; iColor < nColorTableSize; iColor++) {
824         for (i = 0; i < iMaps; i++) {
825             cRef = RGB(pColorTable[iColor].rgbRed,
826                        pColorTable[iColor].rgbGreen,
827                        pColorTable[iColor].rgbBlue);
828             if ( cRef  == sysColorMap[i].from) {
829 #if 0
830                 if (wFlags & CBS_MASKED) {
831                     if (sysColorMap[i].to != COLOR_BTNTEXT)
832                         pColorTable[iColor] = RGB(255, 255, 255);
833                 }
834                 else
835 #endif
836                     pColorTable[iColor].rgbBlue  = GetBValue(sysColorMap[i].to);
837                     pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);
838                     pColorTable[iColor].rgbRed   = GetRValue(sysColorMap[i].to);
839                 break;
840             }
841         }
842     }
843     nWidth  = (INT)lpBitmapInfo->biWidth;
844     nHeight = (INT)lpBitmapInfo->biHeight;
845     hdcScreen = GetDC ((HWND)0);
846     hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
847     if (hbm) {
848         HDC hdcDst = CreateCompatibleDC (hdcScreen);
849         HBITMAP hbmOld = SelectObject (hdcDst, hbm);
850         LPBYTE lpBits = (LPBYTE)(lpBitmap + 1);
851         lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
852         StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
853                          lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
854                          SRCCOPY);
855         SelectObject (hdcDst, hbmOld);
856         DeleteDC (hdcDst);
857     }
858     ReleaseDC ((HWND)0, hdcScreen);
859     GlobalFree ((HGLOBAL)lpBitmapInfo);
860     FreeResource (hglb);
861
862     return hbm;
863 }
864
865
866 /***********************************************************************
867  * CreateToolbar [COMCTL32.7] Creates a tool bar control
868  *
869  * PARAMS
870  *     hwnd
871  *     style
872  *     wID
873  *     nBitmaps
874  *     hBMInst
875  *     wBMID
876  *     lpButtons
877  *     iNumButtons
878  *
879  * RETURNS
880  *     Success: handle to the tool bar control
881  *     Failure: 0
882  *
883  * NOTES
884  *     Do not use this functions anymore. Use CreateToolbarEx instead.
885  */
886
887 HWND WINAPI
888 CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
889                HINSTANCE hBMInst, UINT wBMID,
890                LPCOLDTBBUTTON lpButtons,INT iNumButtons)
891 {
892     return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
893                             hBMInst, wBMID, (LPCTBBUTTON)lpButtons,
894                             iNumButtons, 0, 0, 0, 0, sizeof (OLDTBBUTTON));
895 }
896
897
898 /***********************************************************************
899  * DllGetVersion [COMCTL32.@]
900  *
901  * Retrieves version information of the 'COMCTL32.DLL'
902  *
903  * PARAMS
904  *     pdvi [O] pointer to version information structure.
905  *
906  * RETURNS
907  *     Success: S_OK
908  *     Failure: E_INVALIDARG
909  *
910  * NOTES
911  *     Returns version of a comctl32.dll from IE4.01 SP1.
912  */
913
914 HRESULT WINAPI
915 COMCTL32_DllGetVersion (DLLVERSIONINFO *pdvi)
916 {
917     if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
918         WARN("wrong DLLVERSIONINFO size from app\n");
919         return E_INVALIDARG;
920     }
921
922     pdvi->dwMajorVersion = COMCTL32_VERSION;
923     pdvi->dwMinorVersion = COMCTL32_VERSION_MINOR;
924     pdvi->dwBuildNumber = 2919;
925     pdvi->dwPlatformID = 6304;
926
927     TRACE("%lu.%lu.%lu.%lu\n",
928            pdvi->dwMajorVersion, pdvi->dwMinorVersion,
929            pdvi->dwBuildNumber, pdvi->dwPlatformID);
930
931     return S_OK;
932 }
933
934 /***********************************************************************
935  *              DllInstall (COMCTL32.@)
936  */
937 HRESULT WINAPI COMCTL32_DllInstall(BOOL bInstall, LPCWSTR cmdline)
938 {
939   FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
940         debugstr_w(cmdline));
941
942   return S_OK;
943 }
944
945 /***********************************************************************
946  * _TrackMouseEvent [COMCTL32.@]
947  *
948  * Requests notification of mouse events
949  *
950  * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
951  * to the hwnd specified in the ptme structure.  After the event message
952  * is posted to the hwnd, the entry in the queue is removed.
953  *
954  * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
955  * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
956  * immediately and the TME_LEAVE flag being ignored.
957  *
958  * PARAMS
959  *     ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
960  *
961  * RETURNS
962  *     Success: non-zero
963  *     Failure: zero
964  *
965  * IMPLEMENTATION moved to USER32.TrackMouseEvent
966  *
967  */
968
969 BOOL WINAPI
970 _TrackMouseEvent (TRACKMOUSEEVENT *ptme)
971 {
972     return TrackMouseEvent (ptme);
973 }
974
975 /*************************************************************************
976  * GetMUILanguage [COMCTL32.@]
977  *
978  * FIXME: What's this supposed to do?  Apparently some i18n thing.
979  *
980  */
981 LANGID WINAPI GetMUILanguage (VOID)
982 {
983     return COMCTL32_uiLang;
984 }
985
986
987 /*************************************************************************
988  * InitMUILanguage [COMCTL32.@]
989  *
990  * FIXME: What's this supposed to do?  Apparently some i18n thing.
991  *
992  */
993
994 VOID WINAPI InitMUILanguage (LANGID uiLang)
995 {
996    COMCTL32_uiLang = uiLang;
997 }
998
999
1000 /***********************************************************************
1001  * SetWindowSubclass [COMCTL32.@]
1002  *
1003  * Starts a window subclass
1004  *
1005  * PARAMS
1006  *     hWnd [in] handle to window subclass.
1007  *     pfnSubclass [in] Pointer to new window procedure.
1008  *     uIDSubclass [in] Unique identifier of sublass together with pfnSubclass.
1009  *     dwRef [in] Reference data to pass to window procedure.
1010  *
1011  * RETURNS
1012  *     Success: non-zero
1013  *     Failure: zero
1014  *
1015  * BUGS
1016  *     If an application manually subclasses a window after subclassing it with
1017  *      this API and then with this API again, then none of the previous 
1018  *      subclasses get called or the origional window procedure.
1019  */
1020 BOOL WINAPI SetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
1021                         UINT_PTR uIDSubclass, DWORD_PTR dwRef)
1022 {
1023    LPSUBCLASS_INFO stack;
1024    int newnum, n;
1025
1026    TRACE ("(%x, %p, %x, %lx)\n", hWnd, pfnSubclass, uIDSubclass, dwRef);
1027
1028    /* Since the window procedure that we set here has two additional arguments,
1029     * we can't simply set it as the new window procedure of the window. So we
1030     * set our own window procedure and then calculate the other two arguments
1031     * from there. */
1032
1033    /* See if we have been called for this window */
1034    stack = (LPSUBCLASS_INFO)GetPropA (hWnd, COMCTL32_aSubclass);
1035    if (!stack) {
1036       /* allocate stack */
1037       stack = (LPSUBCLASS_INFO)HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY,
1038                                          sizeof(SUBCLASS_INFO));
1039       if (!stack) {
1040          ERR ("Failed to allocate our Subclassing stack");
1041          return FALSE;
1042       }
1043       SetPropA (hWnd, COMCTL32_aSubclass, (HANDLE)stack);
1044
1045       /* set window procedure to our own and save the current one */
1046       if (IsWindowUnicode (hWnd))
1047          stack->origproc = (WNDPROC)SetWindowLongW (hWnd, GWL_WNDPROC,
1048                                                    (LONG)DefSubclassProc);
1049       else
1050          stack->origproc = (WNDPROC)SetWindowLongA (hWnd, GWL_WNDPROC,
1051                                                    (LONG)DefSubclassProc);
1052    } else {
1053       WNDPROC current;
1054       if (IsWindowUnicode (hWnd))
1055          current = (WNDPROC)GetWindowLongW (hWnd, GWL_WNDPROC);
1056       else
1057          current = (WNDPROC)GetWindowLongA (hWnd, GWL_WNDPROC);
1058
1059       if (current != DefSubclassProc) {
1060          ERR ("Application has subclassed with our procedure, then manually, then with us again.  The current implementation can't handle this.\n");
1061          return FALSE;
1062       }
1063    }
1064
1065    /* Check to see if we have called this function with the same uIDSubClass
1066     * and pfnSubclass */
1067    for (n = 0; n <= stack->stacknum + stack->stacknew - 1; n++)
1068       if ((stack->SubclassProcs[n].id == uIDSubclass) && 
1069          (stack->SubclassProcs[n].subproc == pfnSubclass)) {
1070          stack->SubclassProcs[n].ref = dwRef;
1071          return TRUE;
1072       }
1073
1074    if ((stack->stacknum + stack->stacknew) >= 32) {
1075       ERR ("We have a Subclass stack overflow, please increment size");
1076       return FALSE;
1077    }
1078
1079    /* we can't simply increment both stackpos and stacknum because there might
1080     * be a window procedure running lower in the stack, we can only get them
1081     * up to date once the last window procedure has run */
1082    if (stack->stacknum == stack->stackpos) {
1083       stack->stacknum++;
1084       stack->stackpos++;
1085    } else
1086       stack->stacknew++;
1087
1088    newnum = stack->stacknew + stack->stacknum - 1;
1089
1090    stack->SubclassProcs[newnum].subproc = pfnSubclass;
1091    stack->SubclassProcs[newnum].ref = dwRef;
1092    stack->SubclassProcs[newnum].id = uIDSubclass;
1093    
1094    return TRUE;
1095 }
1096
1097
1098 /***********************************************************************
1099  * GetWindowSubclass [COMCTL32.@]
1100  *
1101  * Gets the Reference data from a subclass.
1102  *
1103  * PARAMS
1104  *     hWnd [in] Handle to window which were subclassing
1105  *     pfnSubclass [in] Pointer to the subclass procedure
1106  *     iID [in] Unique indentifier of the subclassing procedure
1107  *     pdwRef [out] Pointer to the reference data
1108  *
1109  * RETURNS
1110  *     Success: non-sero
1111  *     Failure: zero
1112  */
1113 BOOL WINAPI GetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
1114                               UINT_PTR uID, DWORD_PTR *pdwRef)
1115 {
1116    LPSUBCLASS_INFO stack;
1117    int n;
1118
1119    TRACE ("(%x, %p, %x, %p)\n", hWnd, pfnSubclass, uID, pdwRef);
1120
1121    /* See if we have been called for this window */
1122    stack = (LPSUBCLASS_INFO)GetPropA (hWnd, COMCTL32_aSubclass);
1123    if (!stack)
1124       return FALSE;
1125
1126    for (n = 0; n <= stack->stacknum + stack->stacknew - 1; n++)
1127       if ((stack->SubclassProcs[n].id == uID) &&
1128          (stack->SubclassProcs[n].subproc == pfnSubclass)) {
1129          *pdwRef = stack->SubclassProcs[n].ref;
1130          return TRUE;
1131       }
1132
1133    return FALSE;
1134 }
1135
1136
1137 /***********************************************************************
1138  * RemoveWindowSubclass [COMCTL32.@]
1139  *
1140  * Removes a window subclass.
1141  *
1142  * PARAMS
1143  *     hWnd [in] Handle to the window were subclassing
1144  *     pfnSubclass [in] Pointer to the subclass procedure
1145  *     uID [in] Unique identifier of this subclass
1146  *
1147  * RETURNS
1148  *     Success: non-zero
1149  *     Failure: zero
1150  */
1151 BOOL WINAPI RemoveWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR uID)
1152 {
1153    LPSUBCLASS_INFO stack;
1154    int n;
1155
1156    TRACE ("(%x, %p, %x)\n", hWnd, pfnSubclass, uID);
1157
1158    /* Find the Subclass to remove */
1159    stack = (LPSUBCLASS_INFO)GetPropA (hWnd, COMCTL32_aSubclass);
1160    if (!stack)
1161       return FALSE;
1162
1163    if ((stack->stacknum == stack->stackpos == 1) && !stack->stacknew) {
1164       TRACE("Last Subclass removed, cleaning up\n");
1165       /* clean up our heap and reset the origional window procedure */
1166       if (IsWindowUnicode (hWnd))
1167          SetWindowLongW (hWnd, GWL_WNDPROC, (LONG)stack->origproc);
1168       else
1169          SetWindowLongA (hWnd, GWL_WNDPROC, (LONG)stack->origproc);
1170       HeapFree (GetProcessHeap (), 0, stack);
1171       RemovePropA( hWnd, COMCTL32_aSubclass );
1172       return TRUE;
1173    }
1174  
1175    for (n = stack->stacknum + stack->stacknew - 1; n >= 0; n--)
1176       if ((stack->SubclassProcs[n].id == uID) &&
1177          (stack->SubclassProcs[n].subproc == pfnSubclass)) {
1178          if (n != (stack->stacknum + stack->stacknew))
1179             /* Fill the hole in the stack */
1180             memmove (&stack->SubclassProcs[n], &stack->SubclassProcs[n + 1],
1181                     sizeof(stack->SubclassProcs[0]) * (stack->stacknew + stack->stacknum - n));
1182          stack->SubclassProcs[n].subproc = NULL;
1183          stack->SubclassProcs[n].ref = 0;
1184          stack->SubclassProcs[n].id = 0;
1185
1186          /* If we are currently running a window procedure we have to manipulate
1187           * the stack position pointers so that we don't corrupt the stack */
1188          if ((n < stack->stackpos) || (stack->stackpos == stack->stacknum)) {
1189             stack->stacknum--;
1190             stack->stackpos--;
1191          } else if (n >= stack->stackpos)
1192             stack->stacknew--;
1193          return TRUE;
1194       }
1195
1196    return FALSE;
1197 }
1198
1199
1200 /***********************************************************************
1201  * DefSubclassProc [COMCTL32.@]
1202  *
1203  * Calls the next window procedure (ie. the one before this subclass)
1204  *
1205  * PARAMS
1206  *     hWnd [in] The window that we're subclassing
1207  *     uMsg [in] Message
1208  *     wParam [in] WPARAM
1209  *     lParam [in] LPARAM
1210  *
1211  * RETURNS
1212  *     Success: non-zero
1213  *     Failure: zero
1214  */
1215 LRESULT WINAPI DefSubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1216 {
1217    LPSUBCLASS_INFO stack;
1218    int stackpos;
1219    LRESULT ret;
1220
1221    /* retrieve our little stack from the Properties */
1222    stack = (LPSUBCLASS_INFO)GetPropA (hWnd, COMCTL32_aSubclass);
1223    if (!stack) {
1224       ERR ("Our sub classing stack got erased for %x!! Nothing we can do\n", hWnd);
1225       return 0;
1226    }
1227
1228    /* If we are at pos 0 then we have to call the origional window procedure */
1229    if (stack->stackpos == 0) {
1230       if (IsWindowUnicode (hWnd))
1231          return CallWindowProcW (stack->origproc, hWnd, uMsg, wParam, lParam);
1232       else
1233          return CallWindowProcA (stack->origproc, hWnd, uMsg, wParam, lParam);
1234    }
1235
1236    stackpos = --stack->stackpos;
1237    /* call the Subclass procedure from the stack */
1238    ret = stack->SubclassProcs[stackpos].subproc (hWnd, uMsg, wParam, lParam,
1239          stack->SubclassProcs[stackpos].id, stack->SubclassProcs[stackpos].ref);
1240    stack->stackpos++;
1241
1242    if ((stack->stackpos == stack->stacknum) && stack->stacknew) {
1243       stack->stacknum += stack->stacknew;
1244       stack->stackpos += stack->stacknew;
1245       stack->stacknew = 0;
1246    }
1247
1248    /* If we removed the last entry in our stack while a window procedure was
1249     * running then we have to clean up */
1250    if (stack->stackpos == stack->stacknum == 0) {
1251       TRACE("Last Subclass removed, cleaning up\n");
1252       /* clean up our heap and reset the origional window procedure */
1253       if (IsWindowUnicode (hWnd))
1254          SetWindowLongW (hWnd, GWL_WNDPROC, (LONG)stack->origproc);
1255       else
1256          SetWindowLongA (hWnd, GWL_WNDPROC, (LONG)stack->origproc);
1257       HeapFree (GetProcessHeap (), 0, stack);
1258       RemovePropA( hWnd, COMCTL32_aSubclass );
1259       return TRUE;
1260    }
1261
1262    return ret;
1263 }
1264
1265
1266 /***********************************************************************
1267  * COMCTL32_CreateToolTip [NOT AN API]
1268  *
1269  * Creates a tooltip for the control specified in hwnd and does all
1270  * necessary setup and notifications.
1271  *
1272  * PARAMS
1273  *     hwndOwner [I] Handle to the window that will own the tool tip.
1274  *
1275  * RETURNS
1276  *     Success: Handle of tool tip window.
1277  *     Failure: NULL
1278  */
1279 HWND
1280 COMCTL32_CreateToolTip(HWND hwndOwner)
1281 {
1282     HWND hwndToolTip;
1283
1284     hwndToolTip = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
1285                                   CW_USEDEFAULT, CW_USEDEFAULT,
1286                                   CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner,
1287                                   0, 0, 0);
1288
1289     /* Send NM_TOOLTIPSCREATED notification */
1290     if (hwndToolTip)
1291     {
1292         NMTOOLTIPSCREATED nmttc;
1293         /* true owner can be different if hwndOwner is a child window */
1294         HWND hwndTrueOwner = GetWindow(hwndToolTip, GW_OWNER);
1295         nmttc.hdr.hwndFrom = hwndTrueOwner;
1296         nmttc.hdr.idFrom = GetWindowLongA(hwndTrueOwner, GWL_ID);
1297         nmttc.hdr.code = NM_TOOLTIPSCREATED;
1298         nmttc.hwndToolTips = hwndToolTip;
1299
1300        SendMessageA(GetParent(hwndTrueOwner), WM_NOTIFY,
1301                     (WPARAM)GetWindowLongA(hwndTrueOwner, GWL_ID),
1302                      (LPARAM)&nmttc);
1303     }
1304
1305     return hwndToolTip;
1306 }
1307
1308
1309 /***********************************************************************
1310  * COMCTL32_RefreshSysColors [NOT AN API]
1311  *
1312  * Invoked on any control recognizing a WM_SYSCOLORCHANGE message to
1313  * refresh the color values in the color structure
1314  *
1315  * PARAMS
1316  *     none
1317  *
1318  * RETURNS
1319  *     none
1320  */
1321 VOID
1322 COMCTL32_RefreshSysColors(void)
1323 {
1324     comctl32_color.clrBtnHighlight = GetSysColor (COLOR_BTNHIGHLIGHT);
1325     comctl32_color.clrBtnShadow = GetSysColor (COLOR_BTNSHADOW);
1326     comctl32_color.clrBtnText = GetSysColor (COLOR_BTNTEXT);
1327     comctl32_color.clrBtnFace = GetSysColor (COLOR_BTNFACE);
1328     comctl32_color.clrHighlight = GetSysColor (COLOR_HIGHLIGHT);
1329     comctl32_color.clrHighlightText = GetSysColor (COLOR_HIGHLIGHTTEXT);
1330     comctl32_color.clr3dHilight = GetSysColor (COLOR_3DHILIGHT);
1331     comctl32_color.clr3dShadow = GetSysColor (COLOR_3DSHADOW);
1332     comctl32_color.clr3dDkShadow = GetSysColor (COLOR_3DDKSHADOW);
1333     comctl32_color.clr3dFace = GetSysColor (COLOR_3DFACE);
1334     comctl32_color.clrWindow = GetSysColor (COLOR_WINDOW);
1335     comctl32_color.clrWindowText = GetSysColor (COLOR_WINDOWTEXT);
1336     comctl32_color.clrGrayText = GetSysColor (COLOR_GRAYTEXT);
1337     comctl32_color.clrActiveCaption = GetSysColor (COLOR_ACTIVECAPTION);
1338     comctl32_color.clrInfoBk = GetSysColor (COLOR_INFOBK);
1339     comctl32_color.clrInfoText = GetSysColor (COLOR_INFOTEXT);
1340 }