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