2 * Common controls functions
4 * Copyright 1997 Dimitrie O. Paun
5 * Copyright 1998,2000 Eric Kohl
14 #include "debugtools.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'.
81 * hinstDLL [I] handle to the 'dlls' instance
83 * lpvReserved [I] reserverd, must be NULL
91 COMCTL32_LibMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
93 TRACE("%x,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
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 */
116 LISTVIEW_Register ();
117 PROGRESS_Register ();
121 TOOLTIPS_Register ();
122 TRACKBAR_Register ();
123 TREEVIEW_Register ();
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 ();
140 PROGRESS_Unregister ();
142 STATUS_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;
172 /***********************************************************************
173 * MenuHelp [COMCTL32.2]
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)
188 * The official documentation is incomplete!
189 * This is the correct documentation:
192 * MenuHelp() does NOT handle WM_COMMAND messages! It only handles
193 * WM_MENUSELECT messages.
196 * (will be written ...)
200 MenuHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu,
201 HINSTANCE hInst, HWND hwndStatus, LPUINT lpwIDs)
205 if (!IsWindow (hwndStatus))
210 TRACE("WM_MENUSELECT wParam=0x%X lParam=0x%lX\n",
213 if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {
214 /* menu was closed */
215 TRACE("menu was closed!\n");
216 SendMessageA (hwndStatus, SB_SIMPLE, FALSE, 0);
219 /* menu item was selected */
220 if (HIWORD(wParam) & MF_POPUP)
221 uMenuID = (UINT)*(lpwIDs+1);
223 uMenuID = (UINT)LOWORD(wParam);
224 TRACE("uMenuID = %u\n", uMenuID);
229 if (!LoadStringA (hInst, uMenuID, szText, 256))
232 SendMessageA (hwndStatus, SB_SETTEXTA,
233 255 | SBT_NOBORDERS, (LPARAM)szText);
234 SendMessageA (hwndStatus, SB_SIMPLE, TRUE, 0);
240 TRACE("WM_COMMAND wParam=0x%X lParam=0x%lX\n",
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");
250 FIXME("Invalid Message 0x%x!\n", uMsg);
256 /***********************************************************************
257 * ShowHideMenuCtl [COMCTL32.3]
259 * Shows or hides controls and updates the corresponding menu item.
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.)
271 * The official documentation is incomplete!
272 * This is the correct documentation:
275 * Handle to the window that contains the menu and controls.
278 * Identifier of the menu item to receive or loose a check mark.
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.
287 ShowHideMenuCtl (HWND hwnd, UINT uFlags, LPINT lpInfo)
291 TRACE("%x, %x, %p\n", hwnd, uFlags, lpInfo);
296 if (!(lpInfo[0]) || !(lpInfo[1]))
299 /* search for control */
300 lpMenuId = &lpInfo[2];
301 while (*lpMenuId != uFlags)
304 if (GetMenuState (lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) {
305 /* uncheck menu item */
306 CheckMenuItem (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_UNCHECKED);
310 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
314 /* check menu item */
315 CheckMenuItem (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_CHECKED);
319 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
327 /***********************************************************************
328 * GetEffectiveClientRect [COMCTL32.4]
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)
339 * The official documentation is incomplete!
340 * This is the correct documentation:
343 * (will be written...)
347 GetEffectiveClientRect (HWND hwnd, LPRECT lpRect, LPINT lpInfo)
353 TRACE("(0x%08lx 0x%08lx 0x%08lx)\n",
354 (DWORD)hwnd, (DWORD)lpRect, (DWORD)lpInfo);
356 GetClientRect (hwnd, lpRect);
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);
376 /***********************************************************************
377 * DrawStatusTextA [COMCTL32.5][COMCTL32.27]
379 * Draws text with borders, like in a status bar.
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
391 * The style variable can have one of the following values:
392 * (will be written ...)
396 DrawStatusTextA (HDC hdc, LPRECT lprc, LPCSTR text, UINT style)
399 UINT border = BDR_SUNKENOUTER;
401 if (style & SBT_POPOUT)
402 border = BDR_RAISEDOUTER;
403 else if (style & SBT_NOBORDERS)
406 DrawEdge (hdc, &r, border, BF_RECT|BF_ADJUST|BF_MIDDLE);
410 int oldbkmode = SetBkMode (hdc, TRANSPARENT);
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.
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
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
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
456 * Success: handle to the status window
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,
470 /***********************************************************************
471 * CreateStatusWindowW [COMCTL32.22] Creates a status bar control
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
480 * Success: handle to the status window
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,
494 /***********************************************************************
495 * CreateUpDownControl [COMCTL32.16] Creates an up-down control
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
512 * Success: handle to the updown control
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)
522 CreateWindowA (UPDOWN_CLASSA, 0, style, x, y, cx, cy,
523 parent, id, inst, 0);
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));
534 /***********************************************************************
535 * InitCommonControls [COMCTL32.17]
537 * Registers the common controls.
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.
552 InitCommonControls (void)
557 /***********************************************************************
558 * InitCommonControlsEx [COMCTL32.81]
560 * Registers the common controls.
563 * lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
570 * Only the additional common controls are registered by this function.
571 * The Win95 controls are registered at the DLL's initialization.
575 InitCommonControlsEx (LPINITCOMMONCONTROLSEX lpInitCtrls)
582 if (lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
585 TRACE("(0x%08lx)\n", lpInitCtrls->dwICC);
587 for (cCount = 0; cCount < 32; cCount++) {
588 dwMask = 1 << cCount;
589 if (!(lpInitCtrls->dwICC & dwMask))
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:
604 /* advanced classes - not included in Win95 */
605 case ICC_DATE_CLASSES:
606 MONTHCAL_Register ();
607 DATETIME_Register ();
610 case ICC_USEREX_CLASSES:
614 case ICC_COOL_CLASSES:
618 case ICC_INTERNET_CLASSES:
619 IPADDRESS_Register ();
622 case ICC_PAGESCROLLER_CLASS:
626 case ICC_NATIVEFNTCTL_CLASS:
627 NATIVEFONT_Register ();
631 FIXME("Unknown class! dwICC=0x%lX\n", dwMask);
640 /***********************************************************************
641 * CreateToolbarEx [COMCTL32.32] Creates a tool bar window
659 * Success: handle to the tool bar control
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)
671 /* If not position is specified then put it at the top */
672 if ((style & CCS_BOTTOM) == 0) {
677 CreateWindowExA (0, TOOLBARCLASSNAMEA, "", style|WS_CHILD, 0, 0, 0, 0,
678 hwnd, (HMENU)wID, 0, NULL);
682 SendMessageA (hwndTB, TB_BUTTONSTRUCTSIZE,
683 (WPARAM)uStructSize, 0);
685 /* set bitmap and button size */
686 /*If CreateToolbarEx receives 0, windows sets default values*/
691 SendMessageA (hwndTB, TB_SETBITMAPSIZE, 0,
692 MAKELPARAM((WORD)dxBitmap, (WORD)dyBitmap));
698 SendMessageA (hwndTB, TB_SETBUTTONSIZE, 0,
699 MAKELPARAM((WORD)dxButton, (WORD)dyButton));
705 tbab.hInst = hBMInst;
708 SendMessageA (hwndTB, TB_ADDBITMAP,
709 (WPARAM)nBitmaps, (LPARAM)&tbab);
713 SendMessageA (hwndTB, TB_ADDBUTTONSA,
714 (WPARAM)iNumButtons, (LPARAM)lpButtons);
721 /***********************************************************************
722 * CreateMappedBitmap [COMCTL32.8]
732 * Success: handle to the new bitmap
737 CreateMappedBitmap (HINSTANCE hInstance, INT idBitmap, UINT wFlags,
738 LPCOLORMAP lpColorMap, INT iNumMaps)
742 LPBITMAPINFOHEADER lpBitmap, lpBitmapInfo;
743 UINT nSize, nColorTableSize;
744 RGBQUAD *pColorTable;
745 INT iColor, i, iMaps, nWidth, nHeight;
748 LPCOLORMAP sysColorMap;
750 COLORMAP internalColorMap[4] =
751 {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
753 /* initialize pointer to colortable and default color table */
756 sysColorMap = lpColorMap;
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);
764 sysColorMap = (LPCOLORMAP)internalColorMap;
767 hRsrc = FindResourceA (hInstance, (LPSTR)idBitmap, RT_BITMAPA);
770 hglb = LoadResource (hInstance, hRsrc);
773 lpBitmap = (LPBITMAPINFOHEADER)LockResource (hglb);
774 if (lpBitmap == NULL)
777 nColorTableSize = (1 << lpBitmap->biBitCount);
778 nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
779 lpBitmapInfo = (LPBITMAPINFOHEADER)GlobalAlloc (GMEM_FIXED, nSize);
780 if (lpBitmapInfo == NULL)
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) {
793 if (wFlags & CBS_MASKED) {
794 if (sysColorMap[i].to != COLOR_BTNTEXT)
795 pColorTable[iColor] = RGB(255, 255, 255);
799 pColorTable[iColor].rgbBlue = GetBValue(sysColorMap[i].to);
800 pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);
801 pColorTable[iColor].rgbRed = GetRValue(sysColorMap[i].to);
806 nWidth = (INT)lpBitmapInfo->biWidth;
807 nHeight = (INT)lpBitmapInfo->biHeight;
808 hdcScreen = GetDC ((HWND)0);
809 hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
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,
818 SelectObject (hdcDst, hbmOld);
821 ReleaseDC ((HWND)0, hdcScreen);
822 GlobalFree ((HGLOBAL)lpBitmapInfo);
829 /***********************************************************************
830 * CreateToolbar [COMCTL32.7] Creates a tool bar control
843 * Success: handle to the tool bar control
847 * Do not use this functions anymore. Use CreateToolbarEx instead.
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'
867 * pdvi [O] pointer to version information structure.
871 * Failure: E_INVALIDARG
874 * Returns version of a comctl32.dll from IE4.01 SP1.
878 COMCTL32_DllGetVersion (DLLVERSIONINFO *pdvi)
880 if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
881 WARN("wrong DLLVERSIONINFO size from app");
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);
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));
909 typedef struct __TRACKINGLIST {
911 POINT pos; /* center of hover rectangle */
912 INT iHoverTime; /* elapsed time the cursor has been inside of the hover rect */
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,
928 INT hoverwidth = 0, hoverheight = 0;
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)) {
977 } else { /* remove this entry from the tracking list */
978 TrackingList[i] = TrackingList[--iTrackMax];
982 /* stop the timer if the tracking list is empty */
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.
1003 * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
1012 _TrackMouseEvent (TRACKMOUSEEVENT *ptme)
1016 BOOL cancel = 0, hover = 0, leave = 0, query = 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 */
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);
1038 hwnd = WindowFromPoint(pos);
1040 if ( flags & TME_CANCEL ) {
1041 flags &= ~ TME_CANCEL;
1045 if ( flags & TME_HOVER ) {
1046 flags &= ~ TME_HOVER;
1050 if ( flags & TME_LEAVE ) {
1051 flags &= ~ TME_LEAVE;
1055 /* fill the TRACKMOUSEEVENT struct with the current tracking for the given hwnd */
1056 if ( flags & TME_QUERY ) {
1057 flags &= ~ TME_QUERY;
1061 /* Find the tracking list entry with the matching hwnd */
1062 while((i < iTrackMax) && (TrackingList[i].tme.hwndTrack != ptme->hwndTrack)) {
1066 /* hwnd found, fill in the ptme struct */
1068 *ptme = TrackingList[i].tme;
1072 return TRUE; /* return here, TME_QUERY is retrieving information */
1076 FIXME("Unknown flag(s) %08lx\n", flags );
1079 /* find a matching hwnd if one exists */
1082 while((i < iTrackMax) && (TrackingList[i].tme.hwndTrack != ptme->hwndTrack)) {
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);
1102 /* see if hwndTrack isn't the current window */
1103 if(ptme->hwndTrack != hwnd) {
1105 PostMessageA(ptme->hwndTrack, WM_MOUSELEAVE, 0, 0);
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) {
1112 TrackingList[i].tme.dwFlags |= TME_HOVER;
1113 TrackingList[i].tme.dwHoverTime = ptme->dwHoverTime;
1117 TrackingList[i].tme.dwFlags |= TME_LEAVE;
1119 /* reset iHoverTime as per winapi specs */
1120 TrackingList[i].iHoverTime = 0;
1126 /* if the tracking list is full return FALSE */
1127 if (iTrackMax == sizeof (TrackingList) / sizeof(*TrackingList)) {
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;
1141 timer = SetTimer(0, 0, iTimerInterval, TrackMouseEventProc);
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.
1182 * hwndOwner [I] Handle to the window that will own the tool tip.
1185 * Success: Handle of tool tip window.
1189 COMCTL32_CreateToolTip(HWND hwndOwner)
1193 hwndToolTip = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
1194 CW_USEDEFAULT, CW_USEDEFAULT,
1195 CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner,
1198 /* Send NM_TOOLTIPSCREATED notification */
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),