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