Various cosmetic changes.
[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  */
8
9 #include <string.h>
10 #include <stdlib.h>
11
12 #include "winbase.h"
13 #include "commctrl.h"
14 #include "winerror.h"
15 #include "winreg.h"
16 #define NO_SHLWAPI_STREAM
17 #include "shlwapi.h"
18 #include "comctl32.h"
19 #include "debugtools.h"
20
21 DEFAULT_DEBUG_CHANNEL(commctrl);
22
23 extern void ANIMATE_Register(void);
24 extern void ANIMATE_Unregister(void);
25 extern void COMBOEX_Register(void);
26 extern void COMBOEX_Unregister(void);
27 extern void DATETIME_Register(void);
28 extern void DATETIME_Unregister(void);
29 extern void FLATSB_Register(void);
30 extern void FLATSB_Unregister(void);
31 extern void HEADER_Register(void);
32 extern void HEADER_Unregister(void);
33 extern void HOTKEY_Register(void);
34 extern void HOTKEY_Unregister(void);
35 extern void IPADDRESS_Register(void);
36 extern void IPADDRESS_Unregister(void);
37 extern void LISTVIEW_Register(void);
38 extern void LISTVIEW_Unregister(void);
39 extern void MONTHCAL_Register(void);
40 extern void MONTHCAL_Unregister(void);
41 extern void NATIVEFONT_Register(void);
42 extern void NATIVEFONT_Unregister(void);
43 extern void PAGER_Register(void);
44 extern void PAGER_Unregister(void);
45 extern void PROGRESS_Register(void);
46 extern void PROGRESS_Unregister(void);
47 extern void REBAR_Register(void);
48 extern void REBAR_Unregister(void);
49 extern void STATUS_Register(void);
50 extern void STATUS_Unregister(void);
51 extern void TAB_Register(void);
52 extern void TAB_Unregister(void);
53 extern void TOOLBAR_Register(void);
54 extern void TOOLBAR_Unregister(void);
55 extern void TOOLTIPS_Register(void);
56 extern void TOOLTIPS_Unregister(void);
57 extern void TRACKBAR_Register(void);
58 extern void TRACKBAR_Unregister(void);
59 extern void TREEVIEW_Register(void);
60 extern void TREEVIEW_Unregister(void);
61 extern void UPDOWN_Register(void);
62 extern void UPDOWN_Unregister(void);
63
64
65 HANDLE COMCTL32_hHeap = (HANDLE)NULL;
66 LPSTR    COMCTL32_aSubclass = (LPSTR)NULL;
67 HMODULE COMCTL32_hModule = 0;
68 LANGID  COMCTL32_uiLang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
69 HBRUSH  COMCTL32_hPattern55AABrush = (HANDLE)NULL;
70
71 static HBITMAP COMCTL32_hPattern55AABitmap = (HANDLE)NULL;
72
73 static const WORD wPattern55AA[] =
74 {
75     0x5555, 0xaaaa, 0x5555, 0xaaaa,
76     0x5555, 0xaaaa, 0x5555, 0xaaaa
77 };
78
79
80 /***********************************************************************
81  * COMCTL32_LibMain [Internal] Initializes the internal 'COMCTL32.DLL'.
82  *
83  * PARAMS
84  *     hinstDLL    [I] handle to the 'dlls' instance
85  *     fdwReason   [I]
86  *     lpvReserved [I] reserverd, must be NULL
87  *
88  * RETURNS
89  *     Success: TRUE
90  *     Failure: FALSE
91  */
92
93 BOOL WINAPI
94 COMCTL32_LibMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
95 {
96     TRACE("%x,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
97
98     switch (fdwReason) {
99         case DLL_PROCESS_ATTACH:
100             COMCTL32_hModule = (HMODULE)hinstDLL;
101
102             /* create private heap */
103             COMCTL32_hHeap = HeapCreate (0, 0x10000, 0);
104             TRACE("Heap created: 0x%x\n", COMCTL32_hHeap);
105
106             /* add global subclassing atom (used by 'tooltip' and 'updown') */
107             COMCTL32_aSubclass = (LPSTR)(DWORD)GlobalAddAtomA ("CC32SubclassInfo");
108             TRACE("Subclassing atom added: %p\n", COMCTL32_aSubclass);
109
110             /* create local pattern brush */
111             COMCTL32_hPattern55AABitmap = CreateBitmap (8, 8, 1, 1, wPattern55AA);
112             COMCTL32_hPattern55AABrush = CreatePatternBrush (COMCTL32_hPattern55AABitmap);
113
114             /* register all Win95 common control classes */
115             ANIMATE_Register ();
116             FLATSB_Register ();
117             HEADER_Register ();
118             HOTKEY_Register ();
119             LISTVIEW_Register ();
120             PROGRESS_Register ();
121             STATUS_Register ();
122             TAB_Register ();
123             TOOLBAR_Register ();
124             TOOLTIPS_Register ();
125             TRACKBAR_Register ();
126             TREEVIEW_Register ();
127             UPDOWN_Register ();
128             break;
129
130         case DLL_PROCESS_DETACH:
131             /* unregister all common control classes */
132             ANIMATE_Unregister ();
133             COMBOEX_Unregister ();
134             DATETIME_Unregister ();
135             FLATSB_Unregister ();
136             HEADER_Unregister ();
137             HOTKEY_Unregister ();
138             IPADDRESS_Unregister ();
139             LISTVIEW_Unregister ();
140             MONTHCAL_Unregister ();
141             NATIVEFONT_Unregister ();
142             PAGER_Unregister ();
143             PROGRESS_Unregister ();
144             REBAR_Unregister ();
145             STATUS_Unregister ();
146             TAB_Unregister ();
147             TOOLBAR_Unregister ();
148             TOOLTIPS_Unregister ();
149             TRACKBAR_Unregister ();
150             TREEVIEW_Unregister ();
151             UPDOWN_Unregister ();
152
153             /* delete local pattern brush */
154             DeleteObject (COMCTL32_hPattern55AABrush);
155             COMCTL32_hPattern55AABrush = (HANDLE)NULL;
156             DeleteObject (COMCTL32_hPattern55AABitmap);
157             COMCTL32_hPattern55AABitmap = (HANDLE)NULL;
158
159             /* delete global subclassing atom */
160             GlobalDeleteAtom (LOWORD(COMCTL32_aSubclass));
161             TRACE("Subclassing atom deleted: %p\n", COMCTL32_aSubclass);
162             COMCTL32_aSubclass = (LPSTR)NULL;
163
164             /* destroy private heap */
165             HeapDestroy (COMCTL32_hHeap);
166             TRACE("Heap destroyed: 0x%x\n", COMCTL32_hHeap);
167             COMCTL32_hHeap = (HANDLE)NULL;
168             break;
169     }
170
171     return TRUE;
172 }
173
174
175 /***********************************************************************
176  * MenuHelp [COMCTL32.2]
177  *
178  * PARAMS
179  *     uMsg       [I] message (WM_MENUSELECT) (see NOTES)
180  *     wParam     [I] wParam of the message uMsg
181  *     lParam     [I] lParam of the message uMsg
182  *     hMainMenu  [I] handle to the application's main menu
183  *     hInst      [I] handle to the module that contains string resources
184  *     hwndStatus [I] handle to the status bar window
185  *     lpwIDs     [I] pointer to an array of integers (see NOTES)
186  *
187  * RETURNS
188  *     No return value
189  *
190  * NOTES
191  *     The official documentation is incomplete!
192  *     This is the correct documentation:
193  *
194  *     uMsg:
195  *     MenuHelp() does NOT handle WM_COMMAND messages! It only handles
196  *     WM_MENUSELECT messages.
197  *
198  *     lpwIDs:
199  *     (will be written ...)
200  */
201
202 VOID WINAPI
203 MenuHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu,
204           HINSTANCE hInst, HWND hwndStatus, LPUINT lpwIDs)
205 {
206     UINT uMenuID = 0;
207
208     if (!IsWindow (hwndStatus))
209         return;
210
211     switch (uMsg) {
212         case WM_MENUSELECT:
213             TRACE("WM_MENUSELECT wParam=0x%X lParam=0x%lX\n",
214                    wParam, lParam);
215
216             if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {
217                 /* menu was closed */
218                 TRACE("menu was closed!\n");
219                 SendMessageA (hwndStatus, SB_SIMPLE, FALSE, 0);
220             }
221             else {
222                 /* menu item was selected */
223                 if (HIWORD(wParam) & MF_POPUP)
224                     uMenuID = (UINT)*(lpwIDs+1);
225                 else
226                     uMenuID = (UINT)LOWORD(wParam);
227                 TRACE("uMenuID = %u\n", uMenuID);
228
229                 if (uMenuID) {
230                     CHAR szText[256];
231
232                     if (!LoadStringA (hInst, uMenuID, szText, 256))
233                         szText[0] = '\0';
234
235                     SendMessageA (hwndStatus, SB_SETTEXTA,
236                                     255 | SBT_NOBORDERS, (LPARAM)szText);
237                     SendMessageA (hwndStatus, SB_SIMPLE, TRUE, 0);
238                 }
239             }
240             break;
241
242         case WM_COMMAND :
243             TRACE("WM_COMMAND wParam=0x%X lParam=0x%lX\n",
244                    wParam, lParam);
245             /* WM_COMMAND is not invalid since it is documented
246              * in the windows api reference. So don't output
247              * any FIXME for WM_COMMAND
248              */
249             WARN("We don't care about the WM_COMMAND\n");
250             break;
251
252         default:
253             FIXME("Invalid Message 0x%x!\n", uMsg);
254             break;
255     }
256 }
257
258
259 /***********************************************************************
260  * ShowHideMenuCtl [COMCTL32.3] 
261  *
262  * Shows or hides controls and updates the corresponding menu item.
263  *
264  * PARAMS
265  *     hwnd   [I] handle to the client window.
266  *     uFlags [I] menu command id.
267  *     lpInfo [I] pointer to an array of integers. (See NOTES.)
268  *
269  * RETURNS
270  *     Success: TRUE
271  *     Failure: FALSE
272  *
273  * NOTES
274  *     The official documentation is incomplete!
275  *     This is the correct documentation:
276  *
277  *     hwnd
278  *     Handle to the window that contains the menu and controls.
279  *
280  *     uFlags
281  *     Identifier of the menu item to receive or loose a check mark.
282  *
283  *     lpInfo
284  *     The array of integers contains pairs of values. BOTH values of
285  *     the first pair must be the handles to the application's main menu.
286  *     Each subsequent pair consists of a menu id and control id.
287  */
288
289 BOOL WINAPI
290 ShowHideMenuCtl (HWND hwnd, UINT uFlags, LPINT lpInfo)
291 {
292     LPINT lpMenuId;
293
294     TRACE("%x, %x, %p\n", hwnd, uFlags, lpInfo);
295
296     if (lpInfo == NULL)
297         return FALSE;
298
299     if (!(lpInfo[0]) || !(lpInfo[1]))
300         return FALSE;
301
302     /* search for control */
303     lpMenuId = &lpInfo[2];
304     while (*lpMenuId != uFlags)
305         lpMenuId += 2;
306
307     if (GetMenuState (lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) {
308         /* uncheck menu item */
309         CheckMenuItem (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_UNCHECKED);
310
311         /* hide control */
312         lpMenuId++;
313         SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
314                         SWP_HIDEWINDOW);
315     }
316     else {
317         /* check menu item */
318         CheckMenuItem (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_CHECKED);
319
320         /* show control */
321         lpMenuId++;
322         SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
323                         SWP_SHOWWINDOW);
324     }
325
326     return TRUE;
327 }
328
329
330 /***********************************************************************
331  * GetEffectiveClientRect [COMCTL32.4]
332  *
333  * PARAMS
334  *     hwnd   [I] handle to the client window.
335  *     lpRect [O] pointer to the rectangle of the client window
336  *     lpInfo [I] pointer to an array of integers (see NOTES)
337  *
338  * RETURNS
339  *     No return value.
340  *
341  * NOTES
342  *     The official documentation is incomplete!
343  *     This is the correct documentation:
344  *
345  *     lpInfo
346  *     (will be written...)
347  */
348
349 VOID WINAPI
350 GetEffectiveClientRect (HWND hwnd, LPRECT lpRect, LPINT lpInfo)
351 {
352     RECT rcCtrl;
353     INT  *lpRun;
354     HWND hwndCtrl;
355
356     TRACE("(0x%08lx 0x%08lx 0x%08lx)\n",
357            (DWORD)hwnd, (DWORD)lpRect, (DWORD)lpInfo);
358
359     GetClientRect (hwnd, lpRect);
360     lpRun = lpInfo;
361
362     do {
363         lpRun += 2;
364         if (*lpRun == 0)
365             return;
366         lpRun++;
367         hwndCtrl = GetDlgItem (hwnd, *lpRun);
368         if (GetWindowLongA (hwndCtrl, GWL_STYLE) & WS_VISIBLE) {
369             TRACE("control id 0x%x\n", *lpRun);
370             GetWindowRect (hwndCtrl, &rcCtrl);
371             MapWindowPoints ((HWND)0, hwnd, (LPPOINT)&rcCtrl, 2);
372             SubtractRect (lpRect, lpRect, &rcCtrl);
373         }
374         lpRun++;
375     } while (*lpRun);
376 }
377
378
379 /***********************************************************************
380  * DrawStatusTextW [COMCTL32.28]
381  *
382  * Draws text with borders, like in a status bar.
383  *
384  * PARAMS
385  *     hdc   [I] handle to the window's display context
386  *     lprc  [I] pointer to a rectangle
387  *     text  [I] pointer to the text
388  *     style [I] drawing style
389  *
390  * RETURNS
391  *     No return value.
392  *
393  * NOTES
394  *     The style variable can have one of the following values:
395  *     (will be written ...)
396  */
397
398 VOID WINAPI
399 DrawStatusTextW (HDC hdc, LPRECT lprc, LPCWSTR text, UINT style)
400 {
401     RECT r = *lprc;
402     UINT border = BDR_SUNKENOUTER;
403
404     if (style & SBT_POPOUT)
405       border = BDR_RAISEDOUTER;
406     else if (style & SBT_NOBORDERS)
407       border = 0;
408
409     DrawEdge (hdc, &r, border, BF_RECT|BF_ADJUST|BF_MIDDLE);
410
411     /* now draw text */
412     if (text) {
413       int oldbkmode = SetBkMode (hdc, TRANSPARENT);
414       r.left += 3;
415       DrawTextW (hdc, text, lstrlenW(text),
416                    &r, DT_LEFT|DT_VCENTER|DT_SINGLELINE);  
417       if (oldbkmode != TRANSPARENT)
418         SetBkMode(hdc, oldbkmode);
419     }
420 }
421
422
423 /***********************************************************************
424  * DrawStatusText  [COMCTL32.27]
425  * DrawStatusTextA [COMCTL32.5]
426  *
427  * Draws text with borders, like in a status bar.
428  *
429  * PARAMS
430  *     hdc   [I] handle to the window's display context
431  *     lprc  [I] pointer to a rectangle
432  *     text  [I] pointer to the text
433  *     style [I] drawing style
434  *
435  * RETURNS
436  *     No return value.
437  */
438
439 VOID WINAPI
440 DrawStatusTextA (HDC hdc, LPRECT lprc, LPCSTR text, UINT style)
441 {
442     INT len;
443     LPWSTR textW = NULL;
444
445     if ( text ) {
446         if ( (len = MultiByteToWideChar( CP_ACP, 0, text, -1, NULL, 0 )) ) {
447             if ( (textW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )) )
448                 MultiByteToWideChar( CP_ACP, 0, text, -1, textW, len );
449         }
450     }
451     DrawStatusTextW( hdc, lprc, textW, style );
452     HeapFree( GetProcessHeap(), 0, textW );
453 }
454
455
456 /***********************************************************************
457  * CreateStatusWindow  [COMCTL32.21]
458  * CreateStatusWindowA [COMCTL32.6]
459  *
460  * Creates a status bar
461  *
462  * PARAMS
463  *     style  [I] window style
464  *     text   [I] pointer to the window text
465  *     parent [I] handle to the parent window
466  *     wid    [I] control id of the status bar
467  *
468  * RETURNS
469  *     Success: handle to the status window
470  *     Failure: 0
471  */
472
473 HWND WINAPI
474 CreateStatusWindowA (INT style, LPCSTR text, HWND parent, UINT wid)
475 {
476     return CreateWindowA(STATUSCLASSNAMEA, text, style, 
477                            CW_USEDEFAULT, CW_USEDEFAULT,
478                            CW_USEDEFAULT, CW_USEDEFAULT, 
479                            parent, wid, 0, 0);
480 }
481
482
483 /***********************************************************************
484  * CreateStatusWindowW [COMCTL32.22] Creates a status bar control
485  *
486  * PARAMS
487  *     style  [I] window style
488  *     text   [I] pointer to the window text
489  *     parent [I] handle to the parent window
490  *     wid    [I] control id of the status bar
491  *
492  * RETURNS
493  *     Success: handle to the status window
494  *     Failure: 0
495  */
496
497 HWND WINAPI
498 CreateStatusWindowW (INT style, LPCWSTR text, HWND parent, UINT wid)
499 {
500     return CreateWindowW(STATUSCLASSNAMEW, text, style,
501                            CW_USEDEFAULT, CW_USEDEFAULT,
502                            CW_USEDEFAULT, CW_USEDEFAULT,
503                            parent, wid, 0, 0);
504 }
505
506
507 /***********************************************************************
508  * CreateUpDownControl [COMCTL32.16] Creates an up-down control
509  *
510  * PARAMS
511  *     style  [I] window styles
512  *     x      [I] horizontal position of the control
513  *     y      [I] vertical position of the control
514  *     cx     [I] with of the control
515  *     cy     [I] height of the control
516  *     parent [I] handle to the parent window
517  *     id     [I] the control's identifier
518  *     inst   [I] handle to the application's module instance
519  *     buddy  [I] handle to the buddy window, can be NULL
520  *     maxVal [I] upper limit of the control
521  *     minVal [I] lower limit of the control
522  *     curVal [I] current value of the control
523  *
524  * RETURNS
525  *     Success: handle to the updown control
526  *     Failure: 0
527  */
528
529 HWND WINAPI
530 CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
531                      HWND parent, INT id, HINSTANCE inst,
532                      HWND buddy, INT maxVal, INT minVal, INT curVal)
533 {
534     HWND hUD =
535         CreateWindowA (UPDOWN_CLASSA, 0, style, x, y, cx, cy,
536                          parent, id, inst, 0);
537     if (hUD) {
538         SendMessageA (hUD, UDM_SETBUDDY, buddy, 0);
539         SendMessageA (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));
540         SendMessageA (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));     
541     }
542
543     return hUD;
544 }
545
546
547 /***********************************************************************
548  * InitCommonControls [COMCTL32.17]
549  *
550  * Registers the common controls.
551  *
552  * PARAMS
553  *     No parameters.
554  *
555  * RETURNS
556  *     No return values.
557  *
558  * NOTES
559  *     This function is just a dummy.
560  *     The Win95 controls are registered at the DLL's initialization.
561  *     To register other controls InitCommonControlsEx() must be used.
562  */
563
564 VOID WINAPI
565 InitCommonControls (void)
566 {
567 }
568
569
570 /***********************************************************************
571  * InitCommonControlsEx [COMCTL32.84]
572  *
573  * Registers the common controls.
574  *
575  * PARAMS
576  *     lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
577  *
578  * RETURNS
579  *     Success: TRUE
580  *     Failure: FALSE
581  *
582  * NOTES
583  *     Only the additional common controls are registered by this function.
584  *     The Win95 controls are registered at the DLL's initialization.
585  */
586
587 BOOL WINAPI
588 InitCommonControlsEx (LPINITCOMMONCONTROLSEX lpInitCtrls)
589 {
590     INT cCount;
591     DWORD dwMask;
592
593     if (!lpInitCtrls)
594         return FALSE;
595     if (lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
596         return FALSE;
597
598     TRACE("(0x%08lx)\n", lpInitCtrls->dwICC);
599
600     for (cCount = 0; cCount < 32; cCount++) {
601         dwMask = 1 << cCount;
602         if (!(lpInitCtrls->dwICC & dwMask))
603             continue;
604
605         switch (lpInitCtrls->dwICC & dwMask) {
606             /* dummy initialization */
607             case ICC_ANIMATE_CLASS:
608             case ICC_BAR_CLASSES:
609             case ICC_LISTVIEW_CLASSES:
610             case ICC_TREEVIEW_CLASSES:
611             case ICC_TAB_CLASSES:
612             case ICC_UPDOWN_CLASS:
613             case ICC_PROGRESS_CLASS:
614             case ICC_HOTKEY_CLASS:
615                 break;
616
617             /* advanced classes - not included in Win95 */
618             case ICC_DATE_CLASSES:
619                 MONTHCAL_Register ();
620                 DATETIME_Register ();
621                 break;
622
623             case ICC_USEREX_CLASSES:
624                 COMBOEX_Register ();
625                 break;
626
627             case ICC_COOL_CLASSES:
628                 REBAR_Register ();
629                 break;
630
631             case ICC_INTERNET_CLASSES:
632                 IPADDRESS_Register ();
633                 break;
634
635             case ICC_PAGESCROLLER_CLASS:
636                 PAGER_Register ();
637                 break;
638
639             case ICC_NATIVEFNTCTL_CLASS:
640                 NATIVEFONT_Register ();
641                 break;
642
643             default:
644                 FIXME("Unknown class! dwICC=0x%lX\n", dwMask);
645                 break;
646         }
647     }
648
649     return TRUE;
650 }
651
652
653 /***********************************************************************
654  * CreateToolbarEx [COMCTL32.23] Creates a tool bar window
655  *
656  * PARAMS
657  *     hwnd
658  *     style
659  *     wID
660  *     nBitmaps
661  *     hBMInst
662  *     wBMID
663  *     lpButtons
664  *     iNumButtons
665  *     dxButton
666  *     dyButton
667  *     dxBitmap
668  *     dyBitmap
669  *     uStructSize
670  *
671  * RETURNS
672  *     Success: handle to the tool bar control
673  *     Failure: 0
674  */
675
676 HWND WINAPI
677 CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
678                  HINSTANCE hBMInst, UINT wBMID, LPCTBBUTTON lpButtons,
679                  INT iNumButtons, INT dxButton, INT dyButton,
680                  INT dxBitmap, INT dyBitmap, UINT uStructSize)
681 {
682     HWND hwndTB;
683
684     /* If not position is specified then put it at the top */
685     if ((style & CCS_BOTTOM) == 0) {
686       style|=CCS_TOP;
687     }
688
689     hwndTB =
690         CreateWindowExA (0, TOOLBARCLASSNAMEA, "", style|WS_CHILD, 0, 0, 0, 0,
691                            hwnd, (HMENU)wID, 0, NULL);
692     if(hwndTB) {
693         TBADDBITMAP tbab;
694
695         SendMessageA (hwndTB, TB_BUTTONSTRUCTSIZE,
696                         (WPARAM)uStructSize, 0);
697
698        /* set bitmap and button size */
699        /*If CreateToolbarEx receives 0, windows sets default values*/
700        if (dxBitmap <= 0)
701            dxBitmap = 16;
702        if (dyBitmap <= 0)
703            dyBitmap = 15;
704        SendMessageA (hwndTB, TB_SETBITMAPSIZE, 0,
705                        MAKELPARAM((WORD)dxBitmap, (WORD)dyBitmap));
706
707        if (dxButton <= 0)
708            dxButton = 24;
709        if (dyButton <= 0)
710            dyButton = 22;
711        SendMessageA (hwndTB, TB_SETBUTTONSIZE, 0,
712                        MAKELPARAM((WORD)dxButton, (WORD)dyButton));
713
714
715         /* add bitmaps */
716         if (nBitmaps > 0)
717         {
718         tbab.hInst = hBMInst;
719         tbab.nID   = wBMID;
720
721         SendMessageA (hwndTB, TB_ADDBITMAP,
722                         (WPARAM)nBitmaps, (LPARAM)&tbab);
723         }
724         /* add buttons */
725         if(iNumButtons > 0)
726         SendMessageA (hwndTB, TB_ADDBUTTONSA,
727                         (WPARAM)iNumButtons, (LPARAM)lpButtons);
728     }
729
730     return hwndTB;
731 }
732
733
734 /***********************************************************************
735  * CreateMappedBitmap [COMCTL32.8]
736  *
737  * PARAMS
738  *     hInstance  [I]
739  *     idBitmap   [I]
740  *     wFlags     [I]
741  *     lpColorMap [I]
742  *     iNumMaps   [I]
743  *
744  * RETURNS
745  *     Success: handle to the new bitmap
746  *     Failure: 0
747  */
748
749 HBITMAP WINAPI
750 CreateMappedBitmap (HINSTANCE hInstance, INT idBitmap, UINT wFlags,
751                     LPCOLORMAP lpColorMap, INT iNumMaps)
752 {
753     HGLOBAL hglb;
754     HRSRC hRsrc;
755     LPBITMAPINFOHEADER lpBitmap, lpBitmapInfo;
756     UINT nSize, nColorTableSize;
757     RGBQUAD *pColorTable;
758     INT iColor, i, iMaps, nWidth, nHeight;
759     HDC hdcScreen;
760     HBITMAP hbm;
761     LPCOLORMAP sysColorMap;
762     COLORREF cRef;
763     COLORMAP internalColorMap[4] =
764         {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
765
766     /* initialize pointer to colortable and default color table */
767     if (lpColorMap) {
768         iMaps = iNumMaps;
769         sysColorMap = lpColorMap;
770     }
771     else {
772         internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT);
773         internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW);
774         internalColorMap[2].to = GetSysColor (COLOR_BTNFACE);
775         internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT);
776         iMaps = 4;
777         sysColorMap = (LPCOLORMAP)internalColorMap;
778     }
779
780     hRsrc = FindResourceA (hInstance, (LPSTR)idBitmap, RT_BITMAPA);
781     if (hRsrc == 0)
782         return 0;
783     hglb = LoadResource (hInstance, hRsrc);
784     if (hglb == 0)
785         return 0;
786     lpBitmap = (LPBITMAPINFOHEADER)LockResource (hglb);
787     if (lpBitmap == NULL)
788         return 0;
789
790     nColorTableSize = (1 << lpBitmap->biBitCount);
791     nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
792     lpBitmapInfo = (LPBITMAPINFOHEADER)GlobalAlloc (GMEM_FIXED, nSize);
793     if (lpBitmapInfo == NULL)
794         return 0;
795     RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);
796
797     pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo)+(UINT)lpBitmapInfo->biSize);
798
799     for (iColor = 0; iColor < nColorTableSize; iColor++) {
800         for (i = 0; i < iMaps; i++) {
801             cRef = RGB(pColorTable[iColor].rgbRed,
802                        pColorTable[iColor].rgbGreen,
803                        pColorTable[iColor].rgbBlue);
804             if ( cRef  == sysColorMap[i].from) {
805 #if 0
806                 if (wFlags & CBS_MASKED) {
807                     if (sysColorMap[i].to != COLOR_BTNTEXT)
808                         pColorTable[iColor] = RGB(255, 255, 255);
809                 }
810                 else
811 #endif
812                     pColorTable[iColor].rgbBlue  = GetBValue(sysColorMap[i].to);
813                     pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);
814                     pColorTable[iColor].rgbRed   = GetRValue(sysColorMap[i].to);
815                 break;
816             }
817         }
818     }
819     nWidth  = (INT)lpBitmapInfo->biWidth;
820     nHeight = (INT)lpBitmapInfo->biHeight;
821     hdcScreen = GetDC ((HWND)0);
822     hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
823     if (hbm) {
824         HDC hdcDst = CreateCompatibleDC (hdcScreen);
825         HBITMAP hbmOld = SelectObject (hdcDst, hbm);
826         LPBYTE lpBits = (LPBYTE)(lpBitmap + 1);
827         lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
828         StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
829                          lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
830                          SRCCOPY);
831         SelectObject (hdcDst, hbmOld);
832         DeleteDC (hdcDst);
833     }
834     ReleaseDC ((HWND)0, hdcScreen);
835     GlobalFree ((HGLOBAL)lpBitmapInfo);
836     FreeResource (hglb);
837
838     return hbm;
839 }
840
841
842 /***********************************************************************
843  * CreateToolbar [COMCTL32.7] Creates a tool bar control
844  *
845  * PARAMS
846  *     hwnd
847  *     style
848  *     wID
849  *     nBitmaps
850  *     hBMInst
851  *     wBMID
852  *     lpButtons
853  *     iNumButtons
854  *
855  * RETURNS
856  *     Success: handle to the tool bar control
857  *     Failure: 0
858  *
859  * NOTES
860  *     Do not use this functions anymore. Use CreateToolbarEx instead.
861  */
862
863 HWND WINAPI
864 CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
865                HINSTANCE hBMInst, UINT wBMID,
866                LPCOLDTBBUTTON lpButtons,INT iNumButtons)
867 {
868     return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
869                             hBMInst, wBMID, (LPCTBBUTTON)lpButtons,
870                             iNumButtons, 0, 0, 0, 0, sizeof (OLDTBBUTTON));
871 }
872
873
874 /***********************************************************************
875  * DllGetVersion [COMCTL32.25]
876  *
877  * Retrieves version information of the 'COMCTL32.DLL'
878  *
879  * PARAMS
880  *     pdvi [O] pointer to version information structure.
881  *
882  * RETURNS
883  *     Success: S_OK
884  *     Failure: E_INVALIDARG
885  *
886  * NOTES
887  *     Returns version of a comctl32.dll from IE4.01 SP1.
888  */
889
890 HRESULT WINAPI
891 COMCTL32_DllGetVersion (DLLVERSIONINFO *pdvi)
892 {
893     if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
894         WARN("wrong DLLVERSIONINFO size from app\n");
895         return E_INVALIDARG;
896     }
897
898     pdvi->dwMajorVersion = COMCTL32_VERSION;
899     pdvi->dwMinorVersion = COMCTL32_VERSION_MINOR;
900     pdvi->dwBuildNumber = 2919;
901     pdvi->dwPlatformID = 6304;
902
903     TRACE("%lu.%lu.%lu.%lu\n",
904            pdvi->dwMajorVersion, pdvi->dwMinorVersion,
905            pdvi->dwBuildNumber, pdvi->dwPlatformID);
906
907     return S_OK;
908 }
909
910 /***********************************************************************
911  *              DllInstall (COMCTL32.26)
912  */
913 HRESULT WINAPI COMCTL32_DllInstall(BOOL bInstall, LPCWSTR cmdline)
914 {
915   FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE", 
916         debugstr_w(cmdline));
917
918   return S_OK;
919 }
920
921 /***********************************************************************
922  * _TrackMouseEvent [COMCTL32.91]
923  *
924  * Requests notification of mouse events
925  *
926  * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
927  * to the hwnd specified in the ptme structure.  After the event message
928  * is posted to the hwnd, the entry in the queue is removed.
929  *
930  * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
931  * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
932  * immediately and the TME_LEAVE flag being ignored.
933  *
934  * PARAMS
935  *     ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
936  *
937  * RETURNS
938  *     Success: non-zero
939  *     Failure: zero
940  *
941  * IMPLEMENTATION moved to USER32.TrackMouseEvent
942  *
943  */
944
945 BOOL WINAPI
946 _TrackMouseEvent (TRACKMOUSEEVENT *ptme)
947 {
948     return TrackMouseEvent (ptme);
949 }
950
951 /*************************************************************************
952  * GetMUILanguage [COMCTL32.39]
953  *
954  * FIXME: What's this supposed to do?  Apparently some i18n thing.
955  *
956  */
957 LANGID WINAPI GetMUILanguage (VOID)
958 {
959     return COMCTL32_uiLang;
960 }
961
962
963 /*************************************************************************
964  * InitMUILanguage [COMCTL32.85]
965  *
966  * FIXME: What's this supposed to do?  Apparently some i18n thing.
967  *
968  */
969
970 VOID WINAPI InitMUILanguage (LANGID uiLang)
971 {
972    COMCTL32_uiLang = uiLang;
973 }
974
975
976 /***********************************************************************
977  * COMCTL32_CreateToolTip [NOT AN API]
978  *
979  * Creates a tooltip for the control specified in hwnd and does all
980  * necessary setup and notifications.
981  *
982  * PARAMS
983  *     hwndOwner [I] Handle to the window that will own the tool tip.
984  *
985  * RETURNS
986  *     Success: Handle of tool tip window.
987  *     Failure: NULL
988  */
989 HWND
990 COMCTL32_CreateToolTip(HWND hwndOwner)
991 {
992     HWND hwndToolTip;
993
994     hwndToolTip = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
995                                   CW_USEDEFAULT, CW_USEDEFAULT,
996                                   CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner,
997                                   0, 0, 0);
998
999     /* Send NM_TOOLTIPSCREATED notification */
1000     if (hwndToolTip)
1001     {
1002         NMTOOLTIPSCREATED nmttc;
1003         /* true owner can be different if hwndOwner is a child window */
1004         HWND hwndTrueOwner = GetWindow(hwndToolTip, GW_OWNER);
1005         nmttc.hdr.hwndFrom = hwndTrueOwner;
1006         nmttc.hdr.idFrom = GetWindowLongA(hwndTrueOwner, GWL_ID);
1007         nmttc.hdr.code = NM_TOOLTIPSCREATED;
1008         nmttc.hwndToolTips = hwndToolTip;
1009
1010        SendMessageA(GetParent(hwndTrueOwner), WM_NOTIFY,
1011                     (WPARAM)GetWindowLongA(hwndTrueOwner, GWL_ID),
1012                      (LPARAM)&nmttc);
1013     }
1014
1015     return hwndToolTip;
1016 }