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