Cleaned up dll startup routines now that we have separate address
[wine/multimedia.git] / dlls / comctl32 / commctrl.c
blob1f5a6363159d43a39a9961ec93082c9405838c32
1 /*
2 * Common controls functions
4 * Copyright 1997 Dimitrie O. Paun
5 * Copyright 1998,2000 Eric Kohl
7 */
9 #include <string.h>
11 #include "winbase.h"
12 #include "heap.h"
13 #include "commctrl.h"
14 #include "debugtools.h"
15 #include "winerror.h"
16 #include "shlwapi.h"
18 DEFAULT_DEBUG_CHANNEL(commctrl);
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);
62 HANDLE COMCTL32_hHeap = (HANDLE)NULL;
63 LPSTR COMCTL32_aSubclass = (LPSTR)NULL;
64 HMODULE COMCTL32_hModule = 0;
65 LANGID COMCTL32_uiLang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
66 HBRUSH COMCTL32_hPattern55AABrush = (HANDLE)NULL;
68 static HBITMAP COMCTL32_hPattern55AABitmap = (HANDLE)NULL;
70 static const WORD wPattern55AA[] =
72 0x5555, 0xaaaa, 0x5555, 0xaaaa,
73 0x5555, 0xaaaa, 0x5555, 0xaaaa
77 /***********************************************************************
78 * COMCTL32_LibMain [Internal] Initializes the internal 'COMCTL32.DLL'.
80 * PARAMS
81 * hinstDLL [I] handle to the 'dlls' instance
82 * fdwReason [I]
83 * lpvReserved [I] reserverd, must be NULL
85 * RETURNS
86 * Success: TRUE
87 * Failure: FALSE
90 BOOL WINAPI
91 COMCTL32_LibMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
93 TRACE("%x,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
95 switch (fdwReason) {
96 case DLL_PROCESS_ATTACH:
97 COMCTL32_hModule = (HMODULE)hinstDLL;
99 /* create private heap */
100 COMCTL32_hHeap = HeapCreate (0, 0x10000, 0);
101 TRACE("Heap created: 0x%x\n", COMCTL32_hHeap);
103 /* add global subclassing atom (used by 'tooltip' and 'updown') */
104 COMCTL32_aSubclass = (LPSTR)(DWORD)GlobalAddAtomA ("CC32SubclassInfo");
105 TRACE("Subclassing atom added: %p\n", COMCTL32_aSubclass);
107 /* create local pattern brush */
108 COMCTL32_hPattern55AABitmap = CreateBitmap (8, 8, 1, 1, wPattern55AA);
109 COMCTL32_hPattern55AABrush = CreatePatternBrush (COMCTL32_hPattern55AABitmap);
111 /* register all Win95 common control classes */
112 ANIMATE_Register ();
113 FLATSB_Register ();
114 HEADER_Register ();
115 HOTKEY_Register ();
116 LISTVIEW_Register ();
117 PROGRESS_Register ();
118 STATUS_Register ();
119 TAB_Register ();
120 TOOLBAR_Register ();
121 TOOLTIPS_Register ();
122 TRACKBAR_Register ();
123 TREEVIEW_Register ();
124 UPDOWN_Register ();
125 break;
127 case DLL_PROCESS_DETACH:
128 /* unregister all common control classes */
129 ANIMATE_Unregister ();
130 COMBOEX_Unregister ();
131 DATETIME_Unregister ();
132 FLATSB_Unregister ();
133 HEADER_Unregister ();
134 HOTKEY_Unregister ();
135 IPADDRESS_Unregister ();
136 LISTVIEW_Unregister ();
137 MONTHCAL_Unregister ();
138 NATIVEFONT_Unregister ();
139 PAGER_Unregister ();
140 PROGRESS_Unregister ();
141 REBAR_Unregister ();
142 STATUS_Unregister ();
143 TAB_Unregister ();
144 TOOLBAR_Unregister ();
145 TOOLTIPS_Unregister ();
146 TRACKBAR_Unregister ();
147 TREEVIEW_Unregister ();
148 UPDOWN_Unregister ();
150 /* delete local pattern brush */
151 DeleteObject (COMCTL32_hPattern55AABrush);
152 COMCTL32_hPattern55AABrush = (HANDLE)NULL;
153 DeleteObject (COMCTL32_hPattern55AABitmap);
154 COMCTL32_hPattern55AABitmap = (HANDLE)NULL;
156 /* delete global subclassing atom */
157 GlobalDeleteAtom (LOWORD(COMCTL32_aSubclass));
158 TRACE("Subclassing atom deleted: %p\n", COMCTL32_aSubclass);
159 COMCTL32_aSubclass = (LPSTR)NULL;
161 /* destroy private heap */
162 HeapDestroy (COMCTL32_hHeap);
163 TRACE("Heap destroyed: 0x%x\n", COMCTL32_hHeap);
164 COMCTL32_hHeap = (HANDLE)NULL;
165 break;
168 return TRUE;
172 /***********************************************************************
173 * MenuHelp [COMCTL32.2]
175 * PARAMS
176 * uMsg [I] message (WM_MENUSELECT) (see NOTES)
177 * wParam [I] wParam of the message uMsg
178 * lParam [I] lParam of the message uMsg
179 * hMainMenu [I] handle to the application's main menu
180 * hInst [I] handle to the module that contains string resources
181 * hwndStatus [I] handle to the status bar window
182 * lpwIDs [I] pointer to an array of integers (see NOTES)
184 * RETURNS
185 * No return value
187 * NOTES
188 * The official documentation is incomplete!
189 * This is the correct documentation:
191 * uMsg:
192 * MenuHelp() does NOT handle WM_COMMAND messages! It only handles
193 * WM_MENUSELECT messages.
195 * lpwIDs:
196 * (will be written ...)
199 VOID WINAPI
200 MenuHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu,
201 HINSTANCE hInst, HWND hwndStatus, LPUINT lpwIDs)
203 UINT uMenuID = 0;
205 if (!IsWindow (hwndStatus))
206 return;
208 switch (uMsg) {
209 case WM_MENUSELECT:
210 TRACE("WM_MENUSELECT wParam=0x%X lParam=0x%lX\n",
211 wParam, lParam);
213 if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {
214 /* menu was closed */
215 TRACE("menu was closed!\n");
216 SendMessageA (hwndStatus, SB_SIMPLE, FALSE, 0);
218 else {
219 /* menu item was selected */
220 if (HIWORD(wParam) & MF_POPUP)
221 uMenuID = (UINT)*(lpwIDs+1);
222 else
223 uMenuID = (UINT)LOWORD(wParam);
224 TRACE("uMenuID = %u\n", uMenuID);
226 if (uMenuID) {
227 CHAR szText[256];
229 if (!LoadStringA (hInst, uMenuID, szText, 256))
230 szText[0] = '\0';
232 SendMessageA (hwndStatus, SB_SETTEXTA,
233 255 | SBT_NOBORDERS, (LPARAM)szText);
234 SendMessageA (hwndStatus, SB_SIMPLE, TRUE, 0);
237 break;
239 case WM_COMMAND :
240 TRACE("WM_COMMAND wParam=0x%X lParam=0x%lX\n",
241 wParam, lParam);
242 /* WM_COMMAND is not invalid since it is documented
243 * in the windows api reference. So don't output
244 * any FIXME for WM_COMMAND
246 WARN("We don't care about the WM_COMMAND\n");
247 break;
249 default:
250 FIXME("Invalid Message 0x%x!\n", uMsg);
251 break;
256 /***********************************************************************
257 * ShowHideMenuCtl [COMCTL32.3]
259 * Shows or hides controls and updates the corresponding menu item.
261 * PARAMS
262 * hwnd [I] handle to the client window.
263 * uFlags [I] menu command id.
264 * lpInfo [I] pointer to an array of integers. (See NOTES.)
266 * RETURNS
267 * Success: TRUE
268 * Failure: FALSE
270 * NOTES
271 * The official documentation is incomplete!
272 * This is the correct documentation:
274 * hwnd
275 * Handle to the window that contains the menu and controls.
277 * uFlags
278 * Identifier of the menu item to receive or loose a check mark.
280 * lpInfo
281 * The array of integers contains pairs of values. BOTH values of
282 * the first pair must be the handles to the application's main menu.
283 * Each subsequent pair consists of a menu id and control id.
286 BOOL WINAPI
287 ShowHideMenuCtl (HWND hwnd, UINT uFlags, LPINT lpInfo)
289 LPINT lpMenuId;
291 TRACE("%x, %x, %p\n", hwnd, uFlags, lpInfo);
293 if (lpInfo == NULL)
294 return FALSE;
296 if (!(lpInfo[0]) || !(lpInfo[1]))
297 return FALSE;
299 /* search for control */
300 lpMenuId = &lpInfo[2];
301 while (*lpMenuId != uFlags)
302 lpMenuId += 2;
304 if (GetMenuState (lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) {
305 /* uncheck menu item */
306 CheckMenuItem (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_UNCHECKED);
308 /* hide control */
309 lpMenuId++;
310 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
311 SWP_HIDEWINDOW);
313 else {
314 /* check menu item */
315 CheckMenuItem (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_CHECKED);
317 /* show control */
318 lpMenuId++;
319 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
320 SWP_SHOWWINDOW);
323 return TRUE;
327 /***********************************************************************
328 * GetEffectiveClientRect [COMCTL32.4]
330 * PARAMS
331 * hwnd [I] handle to the client window.
332 * lpRect [O] pointer to the rectangle of the client window
333 * lpInfo [I] pointer to an array of integers (see NOTES)
335 * RETURNS
336 * No return value.
338 * NOTES
339 * The official documentation is incomplete!
340 * This is the correct documentation:
342 * lpInfo
343 * (will be written...)
346 VOID WINAPI
347 GetEffectiveClientRect (HWND hwnd, LPRECT lpRect, LPINT lpInfo)
349 RECT rcCtrl;
350 INT *lpRun;
351 HWND hwndCtrl;
353 TRACE("(0x%08lx 0x%08lx 0x%08lx)\n",
354 (DWORD)hwnd, (DWORD)lpRect, (DWORD)lpInfo);
356 GetClientRect (hwnd, lpRect);
357 lpRun = lpInfo;
359 do {
360 lpRun += 2;
361 if (*lpRun == 0)
362 return;
363 lpRun++;
364 hwndCtrl = GetDlgItem (hwnd, *lpRun);
365 if (GetWindowLongA (hwndCtrl, GWL_STYLE) & WS_VISIBLE) {
366 TRACE("control id 0x%x\n", *lpRun);
367 GetWindowRect (hwndCtrl, &rcCtrl);
368 MapWindowPoints ((HWND)0, hwnd, (LPPOINT)&rcCtrl, 2);
369 SubtractRect (lpRect, lpRect, &rcCtrl);
371 lpRun++;
372 } while (*lpRun);
376 /***********************************************************************
377 * DrawStatusTextA [COMCTL32.5][COMCTL32.27]
379 * Draws text with borders, like in a status bar.
381 * PARAMS
382 * hdc [I] handle to the window's display context
383 * lprc [I] pointer to a rectangle
384 * text [I] pointer to the text
385 * style [I] drawing style
387 * RETURNS
388 * No return value.
390 * NOTES
391 * The style variable can have one of the following values:
392 * (will be written ...)
395 VOID WINAPI
396 DrawStatusTextA (HDC hdc, LPRECT lprc, LPCSTR text, UINT style)
398 RECT r = *lprc;
399 UINT border = BDR_SUNKENOUTER;
401 if (style & SBT_POPOUT)
402 border = BDR_RAISEDOUTER;
403 else if (style & SBT_NOBORDERS)
404 border = 0;
406 DrawEdge (hdc, &r, border, BF_RECT|BF_ADJUST|BF_MIDDLE);
408 /* now draw text */
409 if (text) {
410 int oldbkmode = SetBkMode (hdc, TRANSPARENT);
411 r.left += 3;
412 DrawTextA (hdc, text, lstrlenA(text),
413 &r, DT_LEFT|DT_VCENTER|DT_SINGLELINE);
414 if (oldbkmode != TRANSPARENT)
415 SetBkMode(hdc, oldbkmode);
420 /***********************************************************************
421 * DrawStatusTextW [COMCTL32.28]
423 * Draws text with borders, like in a status bar.
425 * PARAMS
426 * hdc [I] handle to the window's display context
427 * lprc [I] pointer to a rectangle
428 * text [I] pointer to the text
429 * style [I] drawing style
431 * RETURNS
432 * No return value.
435 VOID WINAPI
436 DrawStatusTextW (HDC hdc, LPRECT lprc, LPCWSTR text, UINT style)
438 LPSTR p = HEAP_strdupWtoA (GetProcessHeap (), 0, text);
439 DrawStatusTextA (hdc, lprc, p, style);
440 HeapFree (GetProcessHeap (), 0, p );
444 /***********************************************************************
445 * CreateStatusWindowA [COMCTL32.6][COMCTL32.21]
447 * Creates a status bar
449 * PARAMS
450 * style [I] window style
451 * text [I] pointer to the window text
452 * parent [I] handle to the parent window
453 * wid [I] control id of the status bar
455 * RETURNS
456 * Success: handle to the status window
457 * Failure: 0
460 HWND WINAPI
461 CreateStatusWindowA (INT style, LPCSTR text, HWND parent, UINT wid)
463 return CreateWindowA(STATUSCLASSNAMEA, text, style,
464 CW_USEDEFAULT, CW_USEDEFAULT,
465 CW_USEDEFAULT, CW_USEDEFAULT,
466 parent, wid, 0, 0);
470 /***********************************************************************
471 * CreateStatusWindowW [COMCTL32.22] Creates a status bar control
473 * PARAMS
474 * style [I] window style
475 * text [I] pointer to the window text
476 * parent [I] handle to the parent window
477 * wid [I] control id of the status bar
479 * RETURNS
480 * Success: handle to the status window
481 * Failure: 0
484 HWND WINAPI
485 CreateStatusWindowW (INT style, LPCWSTR text, HWND parent, UINT wid)
487 return CreateWindowW(STATUSCLASSNAMEW, text, style,
488 CW_USEDEFAULT, CW_USEDEFAULT,
489 CW_USEDEFAULT, CW_USEDEFAULT,
490 parent, wid, 0, 0);
494 /***********************************************************************
495 * CreateUpDownControl [COMCTL32.16] Creates an up-down control
497 * PARAMS
498 * style [I] window styles
499 * x [I] horizontal position of the control
500 * y [I] vertical position of the control
501 * cx [I] with of the control
502 * cy [I] height of the control
503 * parent [I] handle to the parent window
504 * id [I] the control's identifier
505 * inst [I] handle to the application's module instance
506 * buddy [I] handle to the buddy window, can be NULL
507 * maxVal [I] upper limit of the control
508 * minVal [I] lower limit of the control
509 * curVal [I] current value of the control
511 * RETURNS
512 * Success: handle to the updown control
513 * Failure: 0
516 HWND WINAPI
517 CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
518 HWND parent, INT id, HINSTANCE inst,
519 HWND buddy, INT maxVal, INT minVal, INT curVal)
521 HWND hUD =
522 CreateWindowA (UPDOWN_CLASSA, 0, style, x, y, cx, cy,
523 parent, id, inst, 0);
524 if (hUD) {
525 SendMessageA (hUD, UDM_SETBUDDY, buddy, 0);
526 SendMessageA (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));
527 SendMessageA (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));
530 return hUD;
534 /***********************************************************************
535 * InitCommonControls [COMCTL32.17]
537 * Registers the common controls.
539 * PARAMS
540 * No parameters.
542 * RETURNS
543 * No return values.
545 * NOTES
546 * This function is just a dummy.
547 * The Win95 controls are registered at the DLL's initialization.
548 * To register other controls InitCommonControlsEx() must be used.
551 VOID WINAPI
552 InitCommonControls (void)
557 /***********************************************************************
558 * InitCommonControlsEx [COMCTL32.81]
560 * Registers the common controls.
562 * PARAMS
563 * lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
565 * RETURNS
566 * Success: TRUE
567 * Failure: FALSE
569 * NOTES
570 * Only the additional common controls are registered by this function.
571 * The Win95 controls are registered at the DLL's initialization.
574 BOOL WINAPI
575 InitCommonControlsEx (LPINITCOMMONCONTROLSEX lpInitCtrls)
577 INT cCount;
578 DWORD dwMask;
580 if (!lpInitCtrls)
581 return FALSE;
582 if (lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
583 return FALSE;
585 TRACE("(0x%08lx)\n", lpInitCtrls->dwICC);
587 for (cCount = 0; cCount < 32; cCount++) {
588 dwMask = 1 << cCount;
589 if (!(lpInitCtrls->dwICC & dwMask))
590 continue;
592 switch (lpInitCtrls->dwICC & dwMask) {
593 /* dummy initialization */
594 case ICC_ANIMATE_CLASS:
595 case ICC_BAR_CLASSES:
596 case ICC_LISTVIEW_CLASSES:
597 case ICC_TREEVIEW_CLASSES:
598 case ICC_TAB_CLASSES:
599 case ICC_UPDOWN_CLASS:
600 case ICC_PROGRESS_CLASS:
601 case ICC_HOTKEY_CLASS:
602 break;
604 /* advanced classes - not included in Win95 */
605 case ICC_DATE_CLASSES:
606 MONTHCAL_Register ();
607 DATETIME_Register ();
608 break;
610 case ICC_USEREX_CLASSES:
611 COMBOEX_Register ();
612 break;
614 case ICC_COOL_CLASSES:
615 REBAR_Register ();
616 break;
618 case ICC_INTERNET_CLASSES:
619 IPADDRESS_Register ();
620 break;
622 case ICC_PAGESCROLLER_CLASS:
623 PAGER_Register ();
624 break;
626 case ICC_NATIVEFNTCTL_CLASS:
627 NATIVEFONT_Register ();
628 break;
630 default:
631 FIXME("Unknown class! dwICC=0x%lX\n", dwMask);
632 break;
636 return TRUE;
640 /***********************************************************************
641 * CreateToolbarEx [COMCTL32.32] Creates a tool bar window
643 * PARAMS
644 * hwnd
645 * style
646 * wID
647 * nBitmaps
648 * hBMInst
649 * wBMID
650 * lpButtons
651 * iNumButtons
652 * dxButton
653 * dyButton
654 * dxBitmap
655 * dyBitmap
656 * uStructSize
658 * RETURNS
659 * Success: handle to the tool bar control
660 * Failure: 0
663 HWND WINAPI
664 CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
665 HINSTANCE hBMInst, UINT wBMID, LPCTBBUTTON lpButtons,
666 INT iNumButtons, INT dxButton, INT dyButton,
667 INT dxBitmap, INT dyBitmap, UINT uStructSize)
669 HWND hwndTB;
671 /* If not position is specified then put it at the top */
672 if ((style & CCS_BOTTOM) == 0) {
673 style|=CCS_TOP;
676 hwndTB =
677 CreateWindowExA (0, TOOLBARCLASSNAMEA, "", style|WS_CHILD, 0, 0, 0, 0,
678 hwnd, (HMENU)wID, 0, NULL);
679 if(hwndTB) {
680 TBADDBITMAP tbab;
682 SendMessageA (hwndTB, TB_BUTTONSTRUCTSIZE,
683 (WPARAM)uStructSize, 0);
685 /* set bitmap and button size */
686 /*If CreateToolbarEx receives 0, windows sets default values*/
687 if (dxBitmap <= 0)
688 dxBitmap = 16;
689 if (dyBitmap <= 0)
690 dyBitmap = 15;
691 SendMessageA (hwndTB, TB_SETBITMAPSIZE, 0,
692 MAKELPARAM((WORD)dxBitmap, (WORD)dyBitmap));
694 if (dxButton <= 0)
695 dxButton = 24;
696 if (dyButton <= 0)
697 dyButton = 22;
698 SendMessageA (hwndTB, TB_SETBUTTONSIZE, 0,
699 MAKELPARAM((WORD)dxButton, (WORD)dyButton));
702 /* add bitmaps */
703 if (nBitmaps > 0)
705 tbab.hInst = hBMInst;
706 tbab.nID = wBMID;
708 SendMessageA (hwndTB, TB_ADDBITMAP,
709 (WPARAM)nBitmaps, (LPARAM)&tbab);
711 /* add buttons */
712 if(iNumButtons > 0)
713 SendMessageA (hwndTB, TB_ADDBUTTONSA,
714 (WPARAM)iNumButtons, (LPARAM)lpButtons);
717 return hwndTB;
721 /***********************************************************************
722 * CreateMappedBitmap [COMCTL32.8]
724 * PARAMS
725 * hInstance [I]
726 * idBitmap [I]
727 * wFlags [I]
728 * lpColorMap [I]
729 * iNumMaps [I]
731 * RETURNS
732 * Success: handle to the new bitmap
733 * Failure: 0
736 HBITMAP WINAPI
737 CreateMappedBitmap (HINSTANCE hInstance, INT idBitmap, UINT wFlags,
738 LPCOLORMAP lpColorMap, INT iNumMaps)
740 HGLOBAL hglb;
741 HRSRC hRsrc;
742 LPBITMAPINFOHEADER lpBitmap, lpBitmapInfo;
743 UINT nSize, nColorTableSize;
744 RGBQUAD *pColorTable;
745 INT iColor, i, iMaps, nWidth, nHeight;
746 HDC hdcScreen;
747 HBITMAP hbm;
748 LPCOLORMAP sysColorMap;
749 COLORREF cRef;
750 COLORMAP internalColorMap[4] =
751 {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
753 /* initialize pointer to colortable and default color table */
754 if (lpColorMap) {
755 iMaps = iNumMaps;
756 sysColorMap = lpColorMap;
758 else {
759 internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT);
760 internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW);
761 internalColorMap[2].to = GetSysColor (COLOR_BTNFACE);
762 internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT);
763 iMaps = 4;
764 sysColorMap = (LPCOLORMAP)internalColorMap;
767 hRsrc = FindResourceA (hInstance, (LPSTR)idBitmap, RT_BITMAPA);
768 if (hRsrc == 0)
769 return 0;
770 hglb = LoadResource (hInstance, hRsrc);
771 if (hglb == 0)
772 return 0;
773 lpBitmap = (LPBITMAPINFOHEADER)LockResource (hglb);
774 if (lpBitmap == NULL)
775 return 0;
777 nColorTableSize = (1 << lpBitmap->biBitCount);
778 nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
779 lpBitmapInfo = (LPBITMAPINFOHEADER)GlobalAlloc (GMEM_FIXED, nSize);
780 if (lpBitmapInfo == NULL)
781 return 0;
782 RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);
784 pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo)+(UINT)lpBitmapInfo->biSize);
786 for (iColor = 0; iColor < nColorTableSize; iColor++) {
787 for (i = 0; i < iMaps; i++) {
788 cRef = RGB(pColorTable[iColor].rgbRed,
789 pColorTable[iColor].rgbGreen,
790 pColorTable[iColor].rgbBlue);
791 if ( cRef == sysColorMap[i].from) {
792 #if 0
793 if (wFlags & CBS_MASKED) {
794 if (sysColorMap[i].to != COLOR_BTNTEXT)
795 pColorTable[iColor] = RGB(255, 255, 255);
797 else
798 #endif
799 pColorTable[iColor].rgbBlue = GetBValue(sysColorMap[i].to);
800 pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);
801 pColorTable[iColor].rgbRed = GetRValue(sysColorMap[i].to);
802 break;
806 nWidth = (INT)lpBitmapInfo->biWidth;
807 nHeight = (INT)lpBitmapInfo->biHeight;
808 hdcScreen = GetDC ((HWND)0);
809 hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
810 if (hbm) {
811 HDC hdcDst = CreateCompatibleDC (hdcScreen);
812 HBITMAP hbmOld = SelectObject (hdcDst, hbm);
813 LPBYTE lpBits = (LPBYTE)(lpBitmap + 1);
814 lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
815 StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
816 lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
817 SRCCOPY);
818 SelectObject (hdcDst, hbmOld);
819 DeleteDC (hdcDst);
821 ReleaseDC ((HWND)0, hdcScreen);
822 GlobalFree ((HGLOBAL)lpBitmapInfo);
823 FreeResource (hglb);
825 return hbm;
829 /***********************************************************************
830 * CreateToolbar [COMCTL32.7] Creates a tool bar control
832 * PARAMS
833 * hwnd
834 * style
835 * wID
836 * nBitmaps
837 * hBMInst
838 * wBMID
839 * lpButtons
840 * iNumButtons
842 * RETURNS
843 * Success: handle to the tool bar control
844 * Failure: 0
846 * NOTES
847 * Do not use this functions anymore. Use CreateToolbarEx instead.
850 HWND WINAPI
851 CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
852 HINSTANCE hBMInst, UINT wBMID,
853 LPCOLDTBBUTTON lpButtons,INT iNumButtons)
855 return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
856 hBMInst, wBMID, (LPCTBBUTTON)lpButtons,
857 iNumButtons, 0, 0, 0, 0, sizeof (OLDTBBUTTON));
861 /***********************************************************************
862 * DllGetVersion [COMCTL32.25]
864 * Retrieves version information of the 'COMCTL32.DLL'
866 * PARAMS
867 * pdvi [O] pointer to version information structure.
869 * RETURNS
870 * Success: S_OK
871 * Failure: E_INVALIDARG
873 * NOTES
874 * Returns version of a comctl32.dll from IE4.01 SP1.
877 HRESULT WINAPI
878 COMCTL32_DllGetVersion (DLLVERSIONINFO *pdvi)
880 if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
881 WARN("wrong DLLVERSIONINFO size from app");
882 return E_INVALIDARG;
885 pdvi->dwMajorVersion = 5;
886 pdvi->dwMinorVersion = 0;
887 pdvi->dwBuildNumber = 2919;
888 pdvi->dwPlatformID = 6304;
890 TRACE("%lu.%lu.%lu.%lu\n",
891 pdvi->dwMajorVersion, pdvi->dwMinorVersion,
892 pdvi->dwBuildNumber, pdvi->dwPlatformID);
894 return S_OK;
897 /***********************************************************************
898 * DllInstall (COMCTL32.@)
900 HRESULT WINAPI COMCTL32_DllInstall(BOOL bInstall, LPCWSTR cmdline)
902 FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
903 debugstr_w(cmdline));
905 return S_OK;
909 typedef struct __TRACKINGLIST {
910 TRACKMOUSEEVENT tme;
911 POINT pos; /* center of hover rectangle */
912 INT iHoverTime; /* elapsed time the cursor has been inside of the hover rect */
913 } _TRACKINGLIST;
915 static _TRACKINGLIST TrackingList[10];
916 static int iTrackMax = 0;
917 static UINT_PTR timer;
918 static const INT iTimerInterval = 50; /* msec for timer interval */
920 /* FIXME: need to implement WM_NCMOUSELEAVE and WM_NCMOUSEHOVER for */
921 /* TrackMouseEventProc and _TrackMouseEvent */
922 static void CALLBACK TrackMouseEventProc(HWND hwndUnused, UINT uMsg, UINT_PTR idEvent,
923 DWORD dwTime)
925 int i = 0;
926 POINT pos;
927 HWND hwnd;
928 INT hoverwidth = 0, hoverheight = 0;
930 GetCursorPos(&pos);
931 hwnd = WindowFromPoint(pos);
933 SystemParametersInfoA(SPI_GETMOUSEHOVERWIDTH, 0, &hoverwidth, 0);
934 SystemParametersInfoA(SPI_GETMOUSEHOVERHEIGHT, 0, &hoverheight, 0);
936 /* loop through tracking events we are processing */
937 while (i < iTrackMax) {
938 /* see if this tracking event is looking for TME_LEAVE and that the */
939 /* mouse has left the window */
940 if ((TrackingList[i].tme.dwFlags & TME_LEAVE) &&
941 (TrackingList[i].tme.hwndTrack != hwnd)) {
942 PostMessageA(TrackingList[i].tme.hwndTrack, WM_MOUSELEAVE, 0, 0);
944 /* remove the TME_LEAVE flag */
945 TrackingList[i].tme.dwFlags ^= TME_LEAVE;
948 /* see if we are tracking hovering for this hwnd */
949 if(TrackingList[i].tme.dwFlags & TME_HOVER) {
950 /* add the timer interval to the hovering time */
951 TrackingList[i].iHoverTime+=iTimerInterval;
953 /* has the cursor moved outside the rectangle centered around pos? */
954 if((abs(pos.x - TrackingList[i].pos.x) > (hoverwidth / 2.0))
955 || (abs(pos.y - TrackingList[i].pos.y) > (hoverheight / 2.0)))
957 /* record this new position as the current position and reset */
958 /* the iHoverTime variable to 0 */
959 TrackingList[i].pos = pos;
960 TrackingList[i].iHoverTime = 0;
963 /* has the mouse hovered long enough? */
964 if(TrackingList[i].iHoverTime <= TrackingList[i].tme.dwHoverTime)
966 PostMessageA(TrackingList[i].tme.hwndTrack, WM_MOUSEHOVER, 0, 0);
968 /* stop tracking mouse hover */
969 TrackingList[i].tme.dwFlags ^= TME_HOVER;
973 /* see if we are still tracking TME_HOVER or TME_LEAVE for this entry */
974 if((TrackingList[i].tme.dwFlags & TME_HOVER) ||
975 (TrackingList[i].tme.dwFlags & TME_LEAVE)) {
976 i++;
977 } else { /* remove this entry from the tracking list */
978 TrackingList[i] = TrackingList[--iTrackMax];
982 /* stop the timer if the tracking list is empty */
983 if(iTrackMax == 0) {
984 KillTimer(0, timer);
985 timer = 0;
989 /***********************************************************************
990 * _TrackMouseEvent [COMCTL32.25]
992 * Requests notification of mouse events
994 * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
995 * to the hwnd specified in the ptme structure. After the event message
996 * is posted to the hwnd, the entry in the queue is removed.
998 * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
999 * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
1000 * immediately and the TME_LEAVE flag being ignored.
1002 * PARAMS
1003 * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
1005 * RETURNS
1006 * Success: non-zero
1007 * Failure: zero
1011 BOOL WINAPI
1012 _TrackMouseEvent (TRACKMOUSEEVENT *ptme)
1014 DWORD flags = 0;
1015 int i = 0;
1016 BOOL cancel = 0, hover = 0, leave = 0, query = 0;
1017 HWND hwnd;
1018 POINT pos;
1020 pos.x = 0;
1021 pos.y = 0;
1023 TRACE("%lx, %lx, %x, %lx\n", ptme->cbSize, ptme->dwFlags, ptme->hwndTrack, ptme->dwHoverTime);
1025 if (ptme->cbSize != sizeof(TRACKMOUSEEVENT)) {
1026 WARN("wrong TRACKMOUSEEVENT size from app");
1027 SetLastError(ERROR_INVALID_PARAMETER); /* FIXME not sure if this is correct */
1028 return FALSE;
1031 flags = ptme->dwFlags;
1033 /* if HOVER_DEFAULT was specified replace this with the systems current value */
1034 if(ptme->dwHoverTime == HOVER_DEFAULT)
1035 SystemParametersInfoA(SPI_GETMOUSEHOVERTIME, 0, &(ptme->dwHoverTime), 0);
1037 GetCursorPos(&pos);
1038 hwnd = WindowFromPoint(pos);
1040 if ( flags & TME_CANCEL ) {
1041 flags &= ~ TME_CANCEL;
1042 cancel = 1;
1045 if ( flags & TME_HOVER ) {
1046 flags &= ~ TME_HOVER;
1047 hover = 1;
1050 if ( flags & TME_LEAVE ) {
1051 flags &= ~ TME_LEAVE;
1052 leave = 1;
1055 /* fill the TRACKMOUSEEVENT struct with the current tracking for the given hwnd */
1056 if ( flags & TME_QUERY ) {
1057 flags &= ~ TME_QUERY;
1058 query = 1;
1059 i = 0;
1061 /* Find the tracking list entry with the matching hwnd */
1062 while((i < iTrackMax) && (TrackingList[i].tme.hwndTrack != ptme->hwndTrack)) {
1063 i++;
1066 /* hwnd found, fill in the ptme struct */
1067 if(i < iTrackMax)
1068 *ptme = TrackingList[i].tme;
1069 else
1070 ptme->dwFlags = 0;
1072 return TRUE; /* return here, TME_QUERY is retrieving information */
1075 if ( flags )
1076 FIXME("Unknown flag(s) %08lx\n", flags );
1078 if(cancel) {
1079 /* find a matching hwnd if one exists */
1080 i = 0;
1082 while((i < iTrackMax) && (TrackingList[i].tme.hwndTrack != ptme->hwndTrack)) {
1083 i++;
1086 if(i < iTrackMax) {
1087 TrackingList[i].tme.dwFlags &= ~(ptme->dwFlags & ~TME_CANCEL);
1089 /* if we aren't tracking on hover or leave remove this entry */
1090 if(!((TrackingList[i].tme.dwFlags & TME_HOVER) ||
1091 (TrackingList[i].tme.dwFlags & TME_LEAVE)))
1093 TrackingList[i] = TrackingList[--iTrackMax];
1095 if(iTrackMax == 0) {
1096 KillTimer(0, timer);
1097 timer = 0;
1101 } else {
1102 /* see if hwndTrack isn't the current window */
1103 if(ptme->hwndTrack != hwnd) {
1104 if(leave) {
1105 PostMessageA(ptme->hwndTrack, WM_MOUSELEAVE, 0, 0);
1107 } else {
1108 /* See if this hwnd is already being tracked and update the tracking flags */
1109 for(i = 0; i < iTrackMax; i++) {
1110 if(TrackingList[i].tme.hwndTrack == ptme->hwndTrack) {
1111 if(hover) {
1112 TrackingList[i].tme.dwFlags |= TME_HOVER;
1113 TrackingList[i].tme.dwHoverTime = ptme->dwHoverTime;
1116 if(leave)
1117 TrackingList[i].tme.dwFlags |= TME_LEAVE;
1119 /* reset iHoverTime as per winapi specs */
1120 TrackingList[i].iHoverTime = 0;
1122 return TRUE;
1126 /* if the tracking list is full return FALSE */
1127 if (iTrackMax == sizeof (TrackingList) / sizeof(*TrackingList)) {
1128 return FALSE;
1131 /* Adding new mouse event to the tracking list */
1132 TrackingList[iTrackMax].tme = *ptme;
1134 /* Initialize HoverInfo variables even if not hover tracking */
1135 TrackingList[iTrackMax].iHoverTime = 0;
1136 TrackingList[iTrackMax].pos = pos;
1138 iTrackMax++;
1140 if (!timer) {
1141 timer = SetTimer(0, 0, iTimerInterval, TrackMouseEventProc);
1146 return TRUE;
1150 /*************************************************************************
1151 * GetMUILanguage [COMCTL32.39]
1153 * FIXME: What's this supposed to do? Apparently some i18n thing.
1156 LANGID WINAPI GetMUILanguage (VOID)
1158 return COMCTL32_uiLang;
1162 /*************************************************************************
1163 * InitMUILanguage [COMCTL32.85]
1165 * FIXME: What's this supposed to do? Apparently some i18n thing.
1169 VOID WINAPI InitMUILanguage (LANGID uiLang)
1171 COMCTL32_uiLang = uiLang;
1175 /***********************************************************************
1176 * COMCTL32_CreateToolTip [NOT AN API]
1178 * Creates a tooltip for the control specified in hwnd and does all
1179 * necessary setup and notifications.
1181 * PARAMS
1182 * hwndOwner [I] Handle to the window that will own the tool tip.
1184 * RETURNS
1185 * Success: Handle of tool tip window.
1186 * Failure: NULL
1188 HWND
1189 COMCTL32_CreateToolTip(HWND hwndOwner)
1191 HWND hwndToolTip;
1193 hwndToolTip = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
1194 CW_USEDEFAULT, CW_USEDEFAULT,
1195 CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner,
1196 0, 0, 0);
1198 /* Send NM_TOOLTIPSCREATED notification */
1199 if (hwndToolTip)
1201 NMTOOLTIPSCREATED nmttc;
1202 /* true owner can be different if hwndOwner is a child window */
1203 HWND hwndTrueOwner = GetWindow(hwndToolTip, GW_OWNER);
1204 nmttc.hdr.hwndFrom = hwndTrueOwner;
1205 nmttc.hdr.idFrom = GetWindowLongA(hwndTrueOwner, GWL_ID);
1206 nmttc.hdr.code = NM_TOOLTIPSCREATED;
1207 nmttc.hwndToolTips = hwndToolTip;
1209 SendMessageA(GetParent(hwndTrueOwner), WM_NOTIFY,
1210 (WPARAM)GetWindowLongA(hwndTrueOwner, GWL_ID),
1211 (LPARAM)&nmttc);
1214 return hwndToolTip;