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