Converted to the new debug interface, using script written by Patrik
[wine] / dlls / comctl32 / commctrl.c
1 /*              
2  * Common controls functions
3  *
4  * Copyright 1997 Dimitrie O. Paun
5  * Copyright 1998 Eric Kohl
6  *
7  */
8
9 #include "winbase.h"
10 #include "heap.h"
11 #include "commctrl.h"
12 #include "animate.h"
13 #include "comboex.h"
14 #include "datetime.h"
15 #include "flatsb.h"
16 #include "header.h"
17 #include "hotkey.h"
18 #include "ipaddress.h"
19 #include "listview.h"
20 #include "monthcal.h"
21 #include "nativefont.h"
22 #include "pager.h"
23 #include "progress.h"
24 #include "rebar.h"
25 #include "status.h"
26 #include "tab.h"
27 #include "toolbar.h"
28 #include "tooltips.h"
29 #include "trackbar.h"
30 #include "treeview.h"
31 #include "updown.h"
32 #include "debugtools.h"
33 #include "winerror.h"
34
35 DEFAULT_DEBUG_CHANNEL(commctrl)
36
37
38 HANDLE COMCTL32_hHeap = (HANDLE)NULL;
39 DWORD    COMCTL32_dwProcessesAttached = 0;
40 LPSTR    COMCTL32_aSubclass = (LPSTR)NULL;
41 HMODULE COMCTL32_hModule = 0;
42
43
44 /***********************************************************************
45  * COMCTL32_LibMain [Internal] Initializes the internal 'COMCTL32.DLL'.
46  *
47  * PARAMS
48  *     hinstDLL    [I] handle to the 'dlls' instance
49  *     fdwReason   [I]
50  *     lpvReserved [I] reserverd, must be NULL
51  *
52  * RETURNS
53  *     Success: TRUE
54  *     Failure: FALSE
55  */
56
57 BOOL WINAPI
58 COMCTL32_LibMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
59 {
60     TRACE("%x,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
61
62     switch (fdwReason) {
63         case DLL_PROCESS_ATTACH:
64             if (COMCTL32_dwProcessesAttached == 0) {
65
66                 /* This will be wrong for any other process attching in this address-space! */
67                 COMCTL32_hModule = (HMODULE)hinstDLL;
68
69                 /* create private heap */
70                 COMCTL32_hHeap = HeapCreate (0, 0x10000, 0);
71                 TRACE("Heap created: 0x%x\n", COMCTL32_hHeap);
72
73                 /* add global subclassing atom (used by 'tooltip' and 'updown') */
74                 COMCTL32_aSubclass = (LPSTR)(DWORD)GlobalAddAtomA ("CC32SubclassInfo");
75                 TRACE("Subclassing atom added: %p\n",
76                        COMCTL32_aSubclass);
77
78                 /* register all Win95 common control classes */
79                 ANIMATE_Register ();
80                 FLATSB_Register ();
81                 HEADER_Register ();
82                 HOTKEY_Register ();
83                 LISTVIEW_Register ();
84                 PROGRESS_Register ();
85                 STATUS_Register ();
86                 TAB_Register ();
87                 TOOLBAR_Register ();
88                 TOOLTIPS_Register ();
89                 TRACKBAR_Register ();
90                 TREEVIEW_Register ();
91                 UPDOWN_Register ();
92             }
93             COMCTL32_dwProcessesAttached++;
94             break;
95
96         case DLL_PROCESS_DETACH:
97             COMCTL32_dwProcessesAttached--;
98             if (COMCTL32_dwProcessesAttached == 0) {
99                 /* unregister all common control classes */
100                 ANIMATE_Unregister ();
101                 COMBOEX_Unregister ();
102                 DATETIME_Unregister ();
103                 FLATSB_Unregister ();
104                 HEADER_Unregister ();
105                 HOTKEY_Unregister ();
106                 IPADDRESS_Unregister ();
107                 LISTVIEW_Unregister ();
108                 MONTHCAL_Unregister ();
109                 NATIVEFONT_Unregister ();
110                 PAGER_Unregister ();
111                 PROGRESS_Unregister ();
112                 REBAR_Unregister ();
113                 STATUS_Unregister ();
114                 TAB_Unregister ();
115                 TOOLBAR_Unregister ();
116                 TOOLTIPS_Unregister ();
117                 TRACKBAR_Unregister ();
118                 TREEVIEW_Unregister ();
119                 UPDOWN_Unregister ();
120
121                 /* delete global subclassing atom */
122                 GlobalDeleteAtom (LOWORD(COMCTL32_aSubclass));
123                 TRACE("Subclassing atom deleted: %p\n",
124                        COMCTL32_aSubclass);
125                 COMCTL32_aSubclass = (LPSTR)NULL;
126
127                 /* destroy private heap */
128                 HeapDestroy (COMCTL32_hHeap);
129                 TRACE("Heap destroyed: 0x%x\n", COMCTL32_hHeap);
130                 COMCTL32_hHeap = (HANDLE)NULL;
131             }
132             break;
133     }
134
135     return TRUE;
136 }
137
138
139 /***********************************************************************
140  * MenuHelp [COMCTL32.2]
141  *
142  * PARAMS
143  *     uMsg       [I] message (WM_MENUSELECT) (see NOTES)
144  *     wParam     [I] wParam of the message uMsg
145  *     lParam     [I] lParam of the message uMsg
146  *     hMainMenu  [I] handle to the application's main menu
147  *     hInst      [I] handle to the module that contains string resources
148  *     hwndStatus [I] handle to the status bar window
149  *     lpwIDs     [I] pointer to an array of intergers (see NOTES)
150  *
151  * RETURNS
152  *     No return value
153  *
154  * NOTES
155  *     The official documentation is incomplete!
156  *     This is the correct documentation:
157  *
158  *     uMsg:
159  *     MenuHelp() does NOT handle WM_COMMAND messages! It only handes
160  *     WM_MENUSELECT messages.
161  *
162  *     lpwIDs:
163  *     (will be written ...)
164  */
165
166 VOID WINAPI
167 MenuHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu,
168           HINSTANCE hInst, HWND hwndStatus, LPUINT lpwIDs)
169 {
170     UINT uMenuID = 0;
171
172     if (!IsWindow (hwndStatus))
173         return;
174
175     switch (uMsg) {
176         case WM_MENUSELECT:
177             TRACE("WM_MENUSELECT wParam=0x%X lParam=0x%lX\n",
178                    wParam, lParam);
179
180             if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {
181                 /* menu was closed */
182                 TRACE("menu was closed!\n");
183                 SendMessageA (hwndStatus, SB_SIMPLE, FALSE, 0);
184             }
185             else {
186                 /* menu item was selected */
187                 if (HIWORD(wParam) & MF_POPUP)
188                     uMenuID = (UINT)*(lpwIDs+1);
189                 else
190                     uMenuID = (UINT)LOWORD(wParam);
191                 TRACE("uMenuID = %u\n", uMenuID);
192
193                 if (uMenuID) {
194                     CHAR szText[256];
195
196                     if (!LoadStringA (hInst, uMenuID, szText, 256))
197                         szText[0] = '\0';
198
199                     SendMessageA (hwndStatus, SB_SETTEXTA,
200                                     255 | SBT_NOBORDERS, (LPARAM)szText);
201                     SendMessageA (hwndStatus, SB_SIMPLE, TRUE, 0);
202                 }
203             }
204             break;
205
206         default:
207             FIXME("Invalid Message 0x%x!\n", uMsg);
208             break;
209     }
210 }
211
212
213 /***********************************************************************
214  * ShowHideMenuCtl [COMCTL32.3] 
215  *
216  * Shows or hides controls and updates the corresponding menu item.
217  *
218  * PARAMS
219  *     hwnd   [I] handle to the client window.
220  *     uFlags [I] menu command id.
221  *     lpInfo [I] pointer to an array of integers. (See NOTES.)
222  *
223  * RETURNS
224  *     Success: TRUE
225  *     Failure: FALSE
226  *
227  * NOTES
228  *     The official documentation is incomplete!
229  *     This is the correct documentation:
230  *
231  *     hwnd
232  *     Handle to the window that contains the menu and controls.
233  *
234  *     uFlags
235  *     Identifier of the menu item to receive or loose a check mark.
236  *
237  *     lpInfo
238  *     The array of integers contains pairs of values. BOTH values of
239  *     the first pair must be the handles to the application's main menu.
240  *     Each subsequent pair consists of a menu id and control id.
241  */
242
243 BOOL WINAPI
244 ShowHideMenuCtl (HWND hwnd, UINT uFlags, LPINT lpInfo)
245 {
246     LPINT lpMenuId;
247
248     TRACE("%x, %x, %p\n", hwnd, uFlags, lpInfo);
249
250     if (lpInfo == NULL)
251         return FALSE;
252
253     if (!(lpInfo[0]) || !(lpInfo[1]))
254         return FALSE;
255
256     /* search for control */
257     lpMenuId = &lpInfo[2];
258     while (*lpMenuId != uFlags)
259         lpMenuId += 2;
260
261     if (GetMenuState (lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) {
262         /* uncheck menu item */
263         CheckMenuItem (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_UNCHECKED);
264
265         /* hide control */
266         lpMenuId++;
267         SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
268                         SWP_HIDEWINDOW);
269     }
270     else {
271         /* check menu item */
272         CheckMenuItem (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_CHECKED);
273
274         /* show control */
275         lpMenuId++;
276         SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
277                         SWP_SHOWWINDOW);
278     }
279
280     return TRUE;
281 }
282
283
284 /***********************************************************************
285  * GetEffectiveClientRect [COMCTL32.4]
286  *
287  * PARAMS
288  *     hwnd   [I] handle to the client window.
289  *     lpRect [O] pointer to the rectangle of the client window
290  *     lpInfo [I] pointer to an array of integers (see NOTES)
291  *
292  * RETURNS
293  *     No return value.
294  *
295  * NOTES
296  *     The official documentation is incomplete!
297  *     This is the correct documentation:
298  *
299  *     lpInfo
300  *     (will be written...)
301  */
302
303 VOID WINAPI
304 GetEffectiveClientRect (HWND hwnd, LPRECT lpRect, LPINT lpInfo)
305 {
306     RECT rcCtrl;
307     INT  *lpRun;
308     HWND hwndCtrl;
309
310     TRACE("(0x%08lx 0x%08lx 0x%08lx)\n",
311            (DWORD)hwnd, (DWORD)lpRect, (DWORD)lpInfo);
312
313     GetClientRect (hwnd, lpRect);
314     lpRun = lpInfo;
315
316     do {
317         lpRun += 2;
318         if (*lpRun == 0)
319             return;
320         lpRun++;
321         hwndCtrl = GetDlgItem (hwnd, *lpRun);
322         if (GetWindowLongA (hwndCtrl, GWL_STYLE) & WS_VISIBLE) {
323             TRACE("control id 0x%x\n", *lpRun);
324             GetWindowRect (hwndCtrl, &rcCtrl);
325             MapWindowPoints ((HWND)0, hwnd, (LPPOINT)&rcCtrl, 2);
326             SubtractRect (lpRect, lpRect, &rcCtrl);
327         }
328         lpRun++;
329     } while (*lpRun);
330 }
331
332
333 /***********************************************************************
334  * DrawStatusText32A [COMCTL32.5][COMCTL32.27]
335  *
336  * Draws text with borders, like in a status bar.
337  *
338  * PARAMS
339  *     hdc   [I] handle to the window's display context
340  *     lprc  [I] pointer to a rectangle
341  *     text  [I] pointer to the text
342  *     style [I] drawing style
343  *
344  * RETURNS
345  *     No return value.
346  *
347  * NOTES
348  *     The style variable can have one of the following values:
349  *     (will be written ...)
350  */
351
352 VOID WINAPI
353 DrawStatusTextA (HDC hdc, LPRECT lprc, LPCSTR text, UINT style)
354 {
355     RECT r = *lprc;
356     UINT border = BDR_SUNKENOUTER;
357
358     if (style & SBT_POPOUT)
359       border = BDR_RAISEDOUTER;
360     else if (style & SBT_NOBORDERS)
361       border = 0;
362
363     DrawEdge (hdc, &r, border, BF_RECT|BF_ADJUST|BF_MIDDLE);
364
365     /* now draw text */
366     if (text) {
367       int oldbkmode = SetBkMode (hdc, TRANSPARENT);
368       r.left += 3;
369       DrawTextA (hdc, text, lstrlenA(text),
370                    &r, DT_LEFT|DT_VCENTER|DT_SINGLELINE);  
371       if (oldbkmode != TRANSPARENT)
372         SetBkMode(hdc, oldbkmode);
373     }
374 }
375
376
377 /***********************************************************************
378  * DrawStatusText32W [COMCTL32.28]
379  *
380  * Draws text with borders, like in a status bar.
381  *
382  * PARAMS
383  *     hdc   [I] handle to the window's display context
384  *     lprc  [I] pointer to a rectangle
385  *     text  [I] pointer to the text
386  *     style [I] drawing style
387  *
388  * RETURNS
389  *     No return value.
390  */
391
392 VOID WINAPI
393 DrawStatusTextW (HDC hdc, LPRECT lprc, LPCWSTR text, UINT style)
394 {
395     LPSTR p = HEAP_strdupWtoA (GetProcessHeap (), 0, text);
396     DrawStatusTextA (hdc, lprc, p, style);
397     HeapFree (GetProcessHeap (), 0, p );
398 }
399
400
401 /***********************************************************************
402  * CreateStatusWindow32A [COMCTL32.6][COMCTL32.21]
403  *
404  * Creates a status bar
405  *
406  * PARAMS
407  *     style  [I] window style
408  *     text   [I] pointer to the window text
409  *     parent [I] handle to the parent window
410  *     wid    [I] control id of the status bar
411  *
412  * RETURNS
413  *     Success: handle to the status window
414  *     Failure: 0
415  */
416
417 HWND WINAPI
418 CreateStatusWindowA (INT style, LPCSTR text, HWND parent, UINT wid)
419 {
420     return CreateWindowA(STATUSCLASSNAMEA, text, style, 
421                            CW_USEDEFAULT, CW_USEDEFAULT,
422                            CW_USEDEFAULT, CW_USEDEFAULT, 
423                            parent, wid, 0, 0);
424 }
425
426
427 /***********************************************************************
428  * CreateStatusWindow32W [COMCTL32.22] Creates a status bar control
429  *
430  * PARAMS
431  *     style  [I] window style
432  *     text   [I] pointer to the window text
433  *     parent [I] handle to the parent window
434  *     wid    [I] control id of the status bar
435  *
436  * RETURNS
437  *     Success: handle to the status window
438  *     Failure: 0
439  */
440
441 HWND WINAPI
442 CreateStatusWindowW (INT style, LPCWSTR text, HWND parent, UINT wid)
443 {
444     return CreateWindowW(STATUSCLASSNAMEW, text, style,
445                            CW_USEDEFAULT, CW_USEDEFAULT,
446                            CW_USEDEFAULT, CW_USEDEFAULT,
447                            parent, wid, 0, 0);
448 }
449
450
451 /***********************************************************************
452  * CreateUpDownControl [COMCTL32.16] Creates an up-down control
453  *
454  * PARAMS
455  *     style  [I] window styles
456  *     x      [I] horizontal position of the control
457  *     y      [I] vertical position of the control
458  *     cx     [I] with of the control
459  *     cy     [I] height of the control
460  *     parent [I] handle to the parent window
461  *     id     [I] the control's identifier
462  *     inst   [I] handle to the application's module instance
463  *     buddy  [I] handle to the buddy window, can be NULL
464  *     maxVal [I] upper limit of the control
465  *     minVal [I] lower limit of the control
466  *     curVal [I] current value of the control
467  *
468  * RETURNS
469  *     Success: handle to the updown control
470  *     Failure: 0
471  */
472
473 HWND WINAPI
474 CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
475                      HWND parent, INT id, HINSTANCE inst,
476                      HWND buddy, INT maxVal, INT minVal, INT curVal)
477 {
478     HWND hUD =
479         CreateWindowA (UPDOWN_CLASSA, 0, style, x, y, cx, cy,
480                          parent, id, inst, 0);
481     if (hUD) {
482         SendMessageA (hUD, UDM_SETBUDDY, buddy, 0);
483         SendMessageA (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));
484         SendMessageA (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));     
485     }
486
487     return hUD;
488 }
489
490
491 /***********************************************************************
492  * InitCommonControls [COMCTL32.17]
493  *
494  * Registers the common controls.
495  *
496  * PARAMS
497  *     No parameters.
498  *
499  * RETURNS
500  *     No return values.
501  *
502  * NOTES
503  *     This function is just a dummy.
504  *     The Win95 controls are registered at the DLL's initialization.
505  *     To register other controls InitCommonControlsEx() must be used.
506  */
507
508 VOID WINAPI
509 InitCommonControls (void)
510 {
511 }
512
513
514 /***********************************************************************
515  * InitCommonControlsEx [COMCTL32.81]
516  *
517  * Registers the common controls.
518  *
519  * PARAMS
520  *     lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
521  *
522  * RETURNS
523  *     Success: TRUE
524  *     Failure: FALSE
525  *
526  * NOTES
527  *     Only the additinal common controls are registered by this function.
528  *     The Win95 controls are registered at the DLL's initialization.
529  */
530
531 BOOL WINAPI
532 InitCommonControlsEx (LPINITCOMMONCONTROLSEX lpInitCtrls)
533 {
534     INT cCount;
535     DWORD dwMask;
536
537     if (!lpInitCtrls)
538         return FALSE;
539     if (lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
540         return FALSE;
541
542     TRACE("(0x%08lx)\n", lpInitCtrls->dwICC);
543
544     for (cCount = 0; cCount < 32; cCount++) {
545         dwMask = 1 << cCount;
546         if (!(lpInitCtrls->dwICC & dwMask))
547             continue;
548
549         switch (lpInitCtrls->dwICC & dwMask) {
550             /* dummy initialization */
551             case ICC_ANIMATE_CLASS:
552             case ICC_BAR_CLASSES:
553             case ICC_LISTVIEW_CLASSES:
554             case ICC_TREEVIEW_CLASSES:
555             case ICC_TAB_CLASSES:
556             case ICC_UPDOWN_CLASS:
557             case ICC_PROGRESS_CLASS:
558             case ICC_HOTKEY_CLASS:
559                 break;
560
561             /* advanced classes - not included in Win95 */
562             case ICC_DATE_CLASSES:
563                 MONTHCAL_Register ();
564                 DATETIME_Register ();
565                 break;
566
567             case ICC_USEREX_CLASSES:
568                 COMBOEX_Register ();
569                 break;
570
571             case ICC_COOL_CLASSES:
572                 REBAR_Register ();
573                 break;
574
575             case ICC_INTERNET_CLASSES:
576                 IPADDRESS_Register ();
577                 break;
578
579             case ICC_PAGESCROLLER_CLASS:
580                 PAGER_Register ();
581                 break;
582
583             case ICC_NATIVEFNTCTL_CLASS:
584                 NATIVEFONT_Register ();
585                 break;
586
587             default:
588                 FIXME("Unknown class! dwICC=0x%lX\n", dwMask);
589                 break;
590         }
591     }
592
593     return TRUE;
594 }
595
596
597 /***********************************************************************
598  * CreateToolbarEx [COMCTL32.32] Creates a tool bar window
599  *
600  * PARAMS
601  *     hwnd
602  *     style
603  *     wID
604  *     nBitmaps
605  *     hBMInst
606  *     wBMID
607  *     lpButtons
608  *     iNumButtons
609  *     dxButton
610  *     dyButton
611  *     dxBitmap
612  *     dyBitmap
613  *     uStructSize
614  *
615  * RETURNS
616  *     Success: handle to the tool bar control
617  *     Failure: 0
618  */
619
620 HWND WINAPI
621 CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
622                  HINSTANCE hBMInst, UINT wBMID, LPCTBBUTTON lpButtons,
623                  INT iNumButtons, INT dxButton, INT dyButton,
624                  INT dxBitmap, INT dyBitmap, UINT uStructSize)
625 {
626     HWND hwndTB =
627         CreateWindowExA (0, TOOLBARCLASSNAMEA, "", style, 0, 0, 0, 0,
628                            hwnd, (HMENU)wID, 0, NULL);
629     if(hwndTB) {
630         TBADDBITMAP tbab;
631
632         SendMessageA (hwndTB, TB_BUTTONSTRUCTSIZE,
633                         (WPARAM)uStructSize, 0);
634
635         /* set bitmap and button size */
636         /*If CreateToolbarEx receive 0, windows set default values*/
637         if (dyBitmap < 0)
638             dyBitmap = 16;
639         if (dxBitmap < 0)
640             dxBitmap = 16;
641
642             SendMessageA (hwndTB, TB_SETBITMAPSIZE, 0,
643                             MAKELPARAM((WORD)dyBitmap, (WORD)dxBitmap));
644             SendMessageA (hwndTB, TB_SETBUTTONSIZE, 0,
645                             MAKELPARAM((WORD)dyButton, (WORD)dxButton));
646
647
648         /* add bitmaps */
649         if (nBitmaps > 0)
650         {
651         tbab.hInst = hBMInst;
652         tbab.nID   = wBMID;
653
654         SendMessageA (hwndTB, TB_ADDBITMAP,
655                         (WPARAM)nBitmaps, (LPARAM)&tbab);
656         }
657         /* add buttons */
658         if(iNumButtons > 0)
659         SendMessageA (hwndTB, TB_ADDBUTTONSA,
660                         (WPARAM)iNumButtons, (LPARAM)lpButtons);
661     }
662
663     return hwndTB;
664 }
665
666
667 /***********************************************************************
668  * CreateMappedBitmap [COMCTL32.8]
669  *
670  * PARAMS
671  *     hInstance  [I]
672  *     idBitmap   [I]
673  *     wFlags     [I]
674  *     lpColorMap [I]
675  *     iNumMaps   [I]
676  *
677  * RETURNS
678  *     Success: handle to the new bitmap
679  *     Failure: 0
680  */
681
682 HBITMAP WINAPI
683 CreateMappedBitmap (HINSTANCE hInstance, INT idBitmap, UINT wFlags,
684                     LPCOLORMAP lpColorMap, INT iNumMaps)
685 {
686     HGLOBAL hglb;
687     HRSRC hRsrc;
688     LPBITMAPINFOHEADER lpBitmap, lpBitmapInfo;
689     UINT nSize, nColorTableSize;
690     DWORD *pColorTable;
691     INT iColor, i, iMaps, nWidth, nHeight;
692     HDC hdcScreen;
693     HBITMAP hbm;
694     LPCOLORMAP sysColorMap;
695     COLORMAP internalColorMap[4] =
696         {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
697
698     /* initialize pointer to colortable and default color table */
699     if (lpColorMap) {
700         iMaps = iNumMaps;
701         sysColorMap = lpColorMap;
702     }
703     else {
704         internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT);
705         internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW);
706         internalColorMap[2].to = GetSysColor (COLOR_BTNFACE);
707         internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT);
708         iMaps = 4;
709         sysColorMap = (LPCOLORMAP)internalColorMap;
710     }
711
712     hRsrc = FindResourceA (hInstance, (LPSTR)idBitmap, RT_BITMAPA);
713     if (hRsrc == 0)
714         return 0;
715     hglb = LoadResource (hInstance, hRsrc);
716     if (hglb == 0)
717         return 0;
718     lpBitmap = (LPBITMAPINFOHEADER)LockResource (hglb);
719     if (lpBitmap == NULL)
720         return 0;
721
722     nColorTableSize = (1 << lpBitmap->biBitCount);
723     nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
724     lpBitmapInfo = (LPBITMAPINFOHEADER)GlobalAlloc (GMEM_FIXED, nSize);
725     if (lpBitmapInfo == NULL)
726         return 0;
727     RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);
728
729     pColorTable = (DWORD*)(((LPBYTE)lpBitmapInfo)+(UINT)lpBitmapInfo->biSize);
730
731     for (iColor = 0; iColor < nColorTableSize; iColor++) {
732         for (i = 0; i < iMaps; i++) {
733             if (pColorTable[iColor] == sysColorMap[i].from) {
734 #if 0
735                 if (wFlags & CBS_MASKED) {
736                     if (sysColorMap[i].to != COLOR_BTNTEXT)
737                         pColorTable[iColor] = RGB(255, 255, 255);
738                 }
739                 else
740 #endif
741                     pColorTable[iColor] = sysColorMap[i].to;
742                 break;
743             }
744         }
745     }
746
747     nWidth  = (INT)lpBitmapInfo->biWidth;
748     nHeight = (INT)lpBitmapInfo->biHeight;
749     hdcScreen = GetDC ((HWND)0);
750     hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
751     if (hbm) {
752         HDC hdcDst = CreateCompatibleDC (hdcScreen);
753         HBITMAP hbmOld = SelectObject (hdcDst, hbm);
754         LPBYTE lpBits = (LPBYTE)(lpBitmap + 1);
755         lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
756         StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
757                          lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
758                          SRCCOPY);
759         SelectObject (hdcDst, hbmOld);
760         DeleteDC (hdcDst);
761     }
762     ReleaseDC ((HWND)0, hdcScreen);
763     GlobalFree ((HGLOBAL)lpBitmapInfo);
764     FreeResource (hglb);
765
766     return hbm;
767 }
768
769
770 /***********************************************************************
771  * CreateToolbar [COMCTL32.7] Creates a tool bar control
772  *
773  * PARAMS
774  *     hwnd
775  *     style
776  *     wID
777  *     nBitmaps
778  *     hBMInst
779  *     wBMID
780  *     lpButtons
781  *     iNumButtons
782  *
783  * RETURNS
784  *     Success: handle to the tool bar control
785  *     Failure: 0
786  *
787  * NOTES
788  *     Do not use this functions anymore. Use CreateToolbarEx instead.
789  */
790
791 HWND WINAPI
792 CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
793                HINSTANCE hBMInst, UINT wBMID,
794                LPCOLDTBBUTTON lpButtons,INT iNumButtons)
795 {
796     return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
797                             hBMInst, wBMID, (LPCTBBUTTON)lpButtons,
798                             iNumButtons, 0, 0, 0, 0, sizeof (OLDTBBUTTON));
799 }
800
801
802 /***********************************************************************
803  * DllGetVersion [COMCTL32.25]
804  *
805  * Retrieves version information of the 'COMCTL32.DLL'
806  *
807  * PARAMS
808  *     pdvi [O] pointer to version information structure.
809  *
810  * RETURNS
811  *     Success: S_OK
812  *     Failure: E_INVALIDARG
813  *
814  * NOTES
815  *     Returns version of a comctl32.dll from IE4.01 SP1.
816  */
817
818 HRESULT WINAPI
819 COMCTL32_DllGetVersion (DLLVERSIONINFO *pdvi)
820 {
821     if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
822         WARN("wrong DLLVERSIONINFO size from app");
823         return E_INVALIDARG;
824     }
825
826     pdvi->dwMajorVersion = 4;
827     pdvi->dwMinorVersion = 72;
828     pdvi->dwBuildNumber = 3110;
829     pdvi->dwPlatformID = 1;
830
831     TRACE("%lu.%lu.%lu.%lu\n",
832            pdvi->dwMajorVersion, pdvi->dwMinorVersion,
833            pdvi->dwBuildNumber, pdvi->dwPlatformID);
834
835     return S_OK;
836 }