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