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 DWORD COMCTL32_dwProcessesAttached = 0;
64 LPSTR COMCTL32_aSubclass = (LPSTR)NULL;
65 HMODULE COMCTL32_hModule = 0;
66 LANGID COMCTL32_uiLang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
69 /***********************************************************************
70 * COMCTL32_LibMain [Internal] Initializes the internal 'COMCTL32.DLL'.
73 * hinstDLL [I] handle to the 'dlls' instance
75 * lpvReserved [I] reserverd, must be NULL
83 COMCTL32_LibMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
85 TRACE("%x,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
88 case DLL_PROCESS_ATTACH:
89 if (COMCTL32_dwProcessesAttached == 0) {
91 /* This will be wrong for any other process attching in this address-space! */
92 COMCTL32_hModule = (HMODULE)hinstDLL;
94 /* create private heap */
95 COMCTL32_hHeap = HeapCreate (0, 0x10000, 0);
96 TRACE("Heap created: 0x%x\n", COMCTL32_hHeap);
98 /* add global subclassing atom (used by 'tooltip' and 'updown') */
99 COMCTL32_aSubclass = (LPSTR)(DWORD)GlobalAddAtomA ("CC32SubclassInfo");
100 TRACE("Subclassing atom added: %p\n",
103 /* register all Win95 common control classes */
108 LISTVIEW_Register ();
109 PROGRESS_Register ();
113 TOOLTIPS_Register ();
114 TRACKBAR_Register ();
115 TREEVIEW_Register ();
118 COMCTL32_dwProcessesAttached++;
121 case DLL_PROCESS_DETACH:
122 COMCTL32_dwProcessesAttached--;
123 if (COMCTL32_dwProcessesAttached == 0) {
124 /* unregister all common control classes */
125 ANIMATE_Unregister ();
126 COMBOEX_Unregister ();
127 DATETIME_Unregister ();
128 FLATSB_Unregister ();
129 HEADER_Unregister ();
130 HOTKEY_Unregister ();
131 IPADDRESS_Unregister ();
132 LISTVIEW_Unregister ();
133 MONTHCAL_Unregister ();
134 NATIVEFONT_Unregister ();
136 PROGRESS_Unregister ();
138 STATUS_Unregister ();
140 TOOLBAR_Unregister ();
141 TOOLTIPS_Unregister ();
142 TRACKBAR_Unregister ();
143 TREEVIEW_Unregister ();
144 UPDOWN_Unregister ();
146 /* delete global subclassing atom */
147 GlobalDeleteAtom (LOWORD(COMCTL32_aSubclass));
148 TRACE("Subclassing atom deleted: %p\n",
150 COMCTL32_aSubclass = (LPSTR)NULL;
152 /* destroy private heap */
153 HeapDestroy (COMCTL32_hHeap);
154 TRACE("Heap destroyed: 0x%x\n", COMCTL32_hHeap);
155 COMCTL32_hHeap = (HANDLE)NULL;
164 /***********************************************************************
165 * MenuHelp [COMCTL32.2]
168 * uMsg [I] message (WM_MENUSELECT) (see NOTES)
169 * wParam [I] wParam of the message uMsg
170 * lParam [I] lParam of the message uMsg
171 * hMainMenu [I] handle to the application's main menu
172 * hInst [I] handle to the module that contains string resources
173 * hwndStatus [I] handle to the status bar window
174 * lpwIDs [I] pointer to an array of intergers (see NOTES)
180 * The official documentation is incomplete!
181 * This is the correct documentation:
184 * MenuHelp() does NOT handle WM_COMMAND messages! It only handles
185 * WM_MENUSELECT messages.
188 * (will be written ...)
192 MenuHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu,
193 HINSTANCE hInst, HWND hwndStatus, LPUINT lpwIDs)
197 if (!IsWindow (hwndStatus))
202 TRACE("WM_MENUSELECT wParam=0x%X lParam=0x%lX\n",
205 if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {
206 /* menu was closed */
207 TRACE("menu was closed!\n");
208 SendMessageA (hwndStatus, SB_SIMPLE, FALSE, 0);
211 /* menu item was selected */
212 if (HIWORD(wParam) & MF_POPUP)
213 uMenuID = (UINT)*(lpwIDs+1);
215 uMenuID = (UINT)LOWORD(wParam);
216 TRACE("uMenuID = %u\n", uMenuID);
221 if (!LoadStringA (hInst, uMenuID, szText, 256))
224 SendMessageA (hwndStatus, SB_SETTEXTA,
225 255 | SBT_NOBORDERS, (LPARAM)szText);
226 SendMessageA (hwndStatus, SB_SIMPLE, TRUE, 0);
232 TRACE("WM_COMMAND wParam=0x%X lParam=0x%lX\n",
234 /* WM_COMMAND is not invalid since it is documented
235 * in the windows api reference. So don't output
236 * any FIXME for WM_COMMAND
238 WARN("We don't care about the WM_COMMAND\n");
242 FIXME("Invalid Message 0x%x!\n", uMsg);
248 /***********************************************************************
249 * ShowHideMenuCtl [COMCTL32.3]
251 * Shows or hides controls and updates the corresponding menu item.
254 * hwnd [I] handle to the client window.
255 * uFlags [I] menu command id.
256 * lpInfo [I] pointer to an array of integers. (See NOTES.)
263 * The official documentation is incomplete!
264 * This is the correct documentation:
267 * Handle to the window that contains the menu and controls.
270 * Identifier of the menu item to receive or loose a check mark.
273 * The array of integers contains pairs of values. BOTH values of
274 * the first pair must be the handles to the application's main menu.
275 * Each subsequent pair consists of a menu id and control id.
279 ShowHideMenuCtl (HWND hwnd, UINT uFlags, LPINT lpInfo)
283 TRACE("%x, %x, %p\n", hwnd, uFlags, lpInfo);
288 if (!(lpInfo[0]) || !(lpInfo[1]))
291 /* search for control */
292 lpMenuId = &lpInfo[2];
293 while (*lpMenuId != uFlags)
296 if (GetMenuState (lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) {
297 /* uncheck menu item */
298 CheckMenuItem (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_UNCHECKED);
302 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
306 /* check menu item */
307 CheckMenuItem (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_CHECKED);
311 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
319 /***********************************************************************
320 * GetEffectiveClientRect [COMCTL32.4]
323 * hwnd [I] handle to the client window.
324 * lpRect [O] pointer to the rectangle of the client window
325 * lpInfo [I] pointer to an array of integers (see NOTES)
331 * The official documentation is incomplete!
332 * This is the correct documentation:
335 * (will be written...)
339 GetEffectiveClientRect (HWND hwnd, LPRECT lpRect, LPINT lpInfo)
345 TRACE("(0x%08lx 0x%08lx 0x%08lx)\n",
346 (DWORD)hwnd, (DWORD)lpRect, (DWORD)lpInfo);
348 GetClientRect (hwnd, lpRect);
356 hwndCtrl = GetDlgItem (hwnd, *lpRun);
357 if (GetWindowLongA (hwndCtrl, GWL_STYLE) & WS_VISIBLE) {
358 TRACE("control id 0x%x\n", *lpRun);
359 GetWindowRect (hwndCtrl, &rcCtrl);
360 MapWindowPoints ((HWND)0, hwnd, (LPPOINT)&rcCtrl, 2);
361 SubtractRect (lpRect, lpRect, &rcCtrl);
368 /***********************************************************************
369 * DrawStatusTextA [COMCTL32.5][COMCTL32.27]
371 * Draws text with borders, like in a status bar.
374 * hdc [I] handle to the window's display context
375 * lprc [I] pointer to a rectangle
376 * text [I] pointer to the text
377 * style [I] drawing style
383 * The style variable can have one of the following values:
384 * (will be written ...)
388 DrawStatusTextA (HDC hdc, LPRECT lprc, LPCSTR text, UINT style)
391 UINT border = BDR_SUNKENOUTER;
393 if (style & SBT_POPOUT)
394 border = BDR_RAISEDOUTER;
395 else if (style & SBT_NOBORDERS)
398 DrawEdge (hdc, &r, border, BF_RECT|BF_ADJUST|BF_MIDDLE);
402 int oldbkmode = SetBkMode (hdc, TRANSPARENT);
404 DrawTextA (hdc, text, lstrlenA(text),
405 &r, DT_LEFT|DT_VCENTER|DT_SINGLELINE);
406 if (oldbkmode != TRANSPARENT)
407 SetBkMode(hdc, oldbkmode);
412 /***********************************************************************
413 * DrawStatusTextW [COMCTL32.28]
415 * Draws text with borders, like in a status bar.
418 * hdc [I] handle to the window's display context
419 * lprc [I] pointer to a rectangle
420 * text [I] pointer to the text
421 * style [I] drawing style
428 DrawStatusTextW (HDC hdc, LPRECT lprc, LPCWSTR text, UINT style)
430 LPSTR p = HEAP_strdupWtoA (GetProcessHeap (), 0, text);
431 DrawStatusTextA (hdc, lprc, p, style);
432 HeapFree (GetProcessHeap (), 0, p );
436 /***********************************************************************
437 * CreateStatusWindowA [COMCTL32.6][COMCTL32.21]
439 * Creates a status bar
442 * style [I] window style
443 * text [I] pointer to the window text
444 * parent [I] handle to the parent window
445 * wid [I] control id of the status bar
448 * Success: handle to the status window
453 CreateStatusWindowA (INT style, LPCSTR text, HWND parent, UINT wid)
455 return CreateWindowA(STATUSCLASSNAMEA, text, style,
456 CW_USEDEFAULT, CW_USEDEFAULT,
457 CW_USEDEFAULT, CW_USEDEFAULT,
462 /***********************************************************************
463 * CreateStatusWindowW [COMCTL32.22] Creates a status bar control
466 * style [I] window style
467 * text [I] pointer to the window text
468 * parent [I] handle to the parent window
469 * wid [I] control id of the status bar
472 * Success: handle to the status window
477 CreateStatusWindowW (INT style, LPCWSTR text, HWND parent, UINT wid)
479 return CreateWindowW(STATUSCLASSNAMEW, text, style,
480 CW_USEDEFAULT, CW_USEDEFAULT,
481 CW_USEDEFAULT, CW_USEDEFAULT,
486 /***********************************************************************
487 * CreateUpDownControl [COMCTL32.16] Creates an up-down control
490 * style [I] window styles
491 * x [I] horizontal position of the control
492 * y [I] vertical position of the control
493 * cx [I] with of the control
494 * cy [I] height of the control
495 * parent [I] handle to the parent window
496 * id [I] the control's identifier
497 * inst [I] handle to the application's module instance
498 * buddy [I] handle to the buddy window, can be NULL
499 * maxVal [I] upper limit of the control
500 * minVal [I] lower limit of the control
501 * curVal [I] current value of the control
504 * Success: handle to the updown control
509 CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
510 HWND parent, INT id, HINSTANCE inst,
511 HWND buddy, INT maxVal, INT minVal, INT curVal)
514 CreateWindowA (UPDOWN_CLASSA, 0, style, x, y, cx, cy,
515 parent, id, inst, 0);
517 SendMessageA (hUD, UDM_SETBUDDY, buddy, 0);
518 SendMessageA (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));
519 SendMessageA (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));
526 /***********************************************************************
527 * InitCommonControls [COMCTL32.17]
529 * Registers the common controls.
538 * This function is just a dummy.
539 * The Win95 controls are registered at the DLL's initialization.
540 * To register other controls InitCommonControlsEx() must be used.
544 InitCommonControls (void)
549 /***********************************************************************
550 * InitCommonControlsEx [COMCTL32.81]
552 * Registers the common controls.
555 * lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
562 * Only the additional common controls are registered by this function.
563 * The Win95 controls are registered at the DLL's initialization.
567 InitCommonControlsEx (LPINITCOMMONCONTROLSEX lpInitCtrls)
574 if (lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
577 TRACE("(0x%08lx)\n", lpInitCtrls->dwICC);
579 for (cCount = 0; cCount < 32; cCount++) {
580 dwMask = 1 << cCount;
581 if (!(lpInitCtrls->dwICC & dwMask))
584 switch (lpInitCtrls->dwICC & dwMask) {
585 /* dummy initialization */
586 case ICC_ANIMATE_CLASS:
587 case ICC_BAR_CLASSES:
588 case ICC_LISTVIEW_CLASSES:
589 case ICC_TREEVIEW_CLASSES:
590 case ICC_TAB_CLASSES:
591 case ICC_UPDOWN_CLASS:
592 case ICC_PROGRESS_CLASS:
593 case ICC_HOTKEY_CLASS:
596 /* advanced classes - not included in Win95 */
597 case ICC_DATE_CLASSES:
598 MONTHCAL_Register ();
599 DATETIME_Register ();
602 case ICC_USEREX_CLASSES:
606 case ICC_COOL_CLASSES:
610 case ICC_INTERNET_CLASSES:
611 IPADDRESS_Register ();
614 case ICC_PAGESCROLLER_CLASS:
618 case ICC_NATIVEFNTCTL_CLASS:
619 NATIVEFONT_Register ();
623 FIXME("Unknown class! dwICC=0x%lX\n", dwMask);
632 /***********************************************************************
633 * CreateToolbarEx [COMCTL32.32] Creates a tool bar window
651 * Success: handle to the tool bar control
656 CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
657 HINSTANCE hBMInst, UINT wBMID, LPCTBBUTTON lpButtons,
658 INT iNumButtons, INT dxButton, INT dyButton,
659 INT dxBitmap, INT dyBitmap, UINT uStructSize)
663 /* If not position is specified then put it at the top */
664 if ((style & CCS_BOTTOM) == 0) {
669 CreateWindowExA (0, TOOLBARCLASSNAMEA, "", style|WS_CHILD, 0, 0, 0, 0,
670 hwnd, (HMENU)wID, 0, NULL);
674 SendMessageA (hwndTB, TB_BUTTONSTRUCTSIZE,
675 (WPARAM)uStructSize, 0);
677 /* set bitmap and button size */
678 /*If CreateToolbarEx receives 0, windows sets default values*/
683 SendMessageA (hwndTB, TB_SETBITMAPSIZE, 0,
684 MAKELPARAM((WORD)dxBitmap, (WORD)dyBitmap));
690 SendMessageA (hwndTB, TB_SETBUTTONSIZE, 0,
691 MAKELPARAM((WORD)dxButton, (WORD)dyButton));
697 tbab.hInst = hBMInst;
700 SendMessageA (hwndTB, TB_ADDBITMAP,
701 (WPARAM)nBitmaps, (LPARAM)&tbab);
705 SendMessageA (hwndTB, TB_ADDBUTTONSA,
706 (WPARAM)iNumButtons, (LPARAM)lpButtons);
713 /***********************************************************************
714 * CreateMappedBitmap [COMCTL32.8]
724 * Success: handle to the new bitmap
729 CreateMappedBitmap (HINSTANCE hInstance, INT idBitmap, UINT wFlags,
730 LPCOLORMAP lpColorMap, INT iNumMaps)
734 LPBITMAPINFOHEADER lpBitmap, lpBitmapInfo;
735 UINT nSize, nColorTableSize;
736 RGBQUAD *pColorTable;
737 INT iColor, i, iMaps, nWidth, nHeight;
740 LPCOLORMAP sysColorMap;
742 COLORMAP internalColorMap[4] =
743 {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
745 /* initialize pointer to colortable and default color table */
748 sysColorMap = lpColorMap;
751 internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT);
752 internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW);
753 internalColorMap[2].to = GetSysColor (COLOR_BTNFACE);
754 internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT);
756 sysColorMap = (LPCOLORMAP)internalColorMap;
759 hRsrc = FindResourceA (hInstance, (LPSTR)idBitmap, RT_BITMAPA);
762 hglb = LoadResource (hInstance, hRsrc);
765 lpBitmap = (LPBITMAPINFOHEADER)LockResource (hglb);
766 if (lpBitmap == NULL)
769 nColorTableSize = (1 << lpBitmap->biBitCount);
770 nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
771 lpBitmapInfo = (LPBITMAPINFOHEADER)GlobalAlloc (GMEM_FIXED, nSize);
772 if (lpBitmapInfo == NULL)
774 RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);
776 pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo)+(UINT)lpBitmapInfo->biSize);
778 for (iColor = 0; iColor < nColorTableSize; iColor++) {
779 for (i = 0; i < iMaps; i++) {
780 cRef = RGB(pColorTable[iColor].rgbRed,
781 pColorTable[iColor].rgbGreen,
782 pColorTable[iColor].rgbBlue);
783 if ( cRef == sysColorMap[i].from) {
785 if (wFlags & CBS_MASKED) {
786 if (sysColorMap[i].to != COLOR_BTNTEXT)
787 pColorTable[iColor] = RGB(255, 255, 255);
791 pColorTable[iColor].rgbBlue = GetBValue(sysColorMap[i].to);
792 pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);
793 pColorTable[iColor].rgbRed = GetRValue(sysColorMap[i].to);
798 nWidth = (INT)lpBitmapInfo->biWidth;
799 nHeight = (INT)lpBitmapInfo->biHeight;
800 hdcScreen = GetDC ((HWND)0);
801 hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
803 HDC hdcDst = CreateCompatibleDC (hdcScreen);
804 HBITMAP hbmOld = SelectObject (hdcDst, hbm);
805 LPBYTE lpBits = (LPBYTE)(lpBitmap + 1);
806 lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
807 StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
808 lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
810 SelectObject (hdcDst, hbmOld);
813 ReleaseDC ((HWND)0, hdcScreen);
814 GlobalFree ((HGLOBAL)lpBitmapInfo);
821 /***********************************************************************
822 * CreateToolbar [COMCTL32.7] Creates a tool bar control
835 * Success: handle to the tool bar control
839 * Do not use this functions anymore. Use CreateToolbarEx instead.
843 CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
844 HINSTANCE hBMInst, UINT wBMID,
845 LPCOLDTBBUTTON lpButtons,INT iNumButtons)
847 return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
848 hBMInst, wBMID, (LPCTBBUTTON)lpButtons,
849 iNumButtons, 0, 0, 0, 0, sizeof (OLDTBBUTTON));
853 /***********************************************************************
854 * DllGetVersion [COMCTL32.25]
856 * Retrieves version information of the 'COMCTL32.DLL'
859 * pdvi [O] pointer to version information structure.
863 * Failure: E_INVALIDARG
866 * Returns version of a comctl32.dll from IE4.01 SP1.
870 COMCTL32_DllGetVersion (DLLVERSIONINFO *pdvi)
872 if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
873 WARN("wrong DLLVERSIONINFO size from app");
877 pdvi->dwMajorVersion = 5;
878 pdvi->dwMinorVersion = 0;
879 pdvi->dwBuildNumber = 2919;
880 pdvi->dwPlatformID = 6304;
882 TRACE("%lu.%lu.%lu.%lu\n",
883 pdvi->dwMajorVersion, pdvi->dwMinorVersion,
884 pdvi->dwBuildNumber, pdvi->dwPlatformID);
889 /***********************************************************************
890 * DllInstall (COMCTL32.@)
892 HRESULT WINAPI COMCTL32_DllInstall(BOOL bInstall, LPCWSTR cmdline)
894 FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
895 debugstr_w(cmdline));
901 typedef struct __TRACKINGLIST {
903 POINT pos; /* center of hover rectangle */
904 INT iHoverTime; /* elapsed time the cursor has been inside of the hover rect */
907 static _TRACKINGLIST TrackingList[10];
908 static int iTrackMax = 0;
909 static UINT_PTR timer;
910 static const INT iTimerInterval = 50; /* msec for timer interval */
912 /* FIXME: need to implement WM_NCMOUSELEAVE and WM_NCMOUSEHOVER for */
913 /* TrackMouseEventProc and _TrackMouseEvent */
914 static void CALLBACK TrackMouseEventProc(HWND hwndUnused, UINT uMsg, UINT_PTR idEvent,
920 INT hoverwidth = 0, hoverheight = 0;
923 hwnd = WindowFromPoint(pos);
925 SystemParametersInfoA(SPI_GETMOUSEHOVERWIDTH, 0, &hoverwidth, 0);
926 SystemParametersInfoA(SPI_GETMOUSEHOVERHEIGHT, 0, &hoverheight, 0);
928 /* loop through tracking events we are processing */
929 while (i < iTrackMax) {
930 /* see if this tracking event is looking for TME_LEAVE and that the */
931 /* mouse has left the window */
932 if ((TrackingList[i].tme.dwFlags & TME_LEAVE) &&
933 (TrackingList[i].tme.hwndTrack != hwnd)) {
934 PostMessageA(TrackingList[i].tme.hwndTrack, WM_MOUSELEAVE, 0, 0);
936 /* remove the TME_LEAVE flag */
937 TrackingList[i].tme.dwFlags ^= TME_LEAVE;
940 /* see if we are tracking hovering for this hwnd */
941 if(TrackingList[i].tme.dwFlags & TME_HOVER) {
942 /* add the timer interval to the hovering time */
943 TrackingList[i].iHoverTime+=iTimerInterval;
945 /* has the cursor moved outside the rectangle centered around pos? */
946 if((abs(pos.x - TrackingList[i].pos.x) > (hoverwidth / 2.0))
947 || (abs(pos.y - TrackingList[i].pos.y) > (hoverheight / 2.0)))
949 /* record this new position as the current position and reset */
950 /* the iHoverTime variable to 0 */
951 TrackingList[i].pos = pos;
952 TrackingList[i].iHoverTime = 0;
955 /* has the mouse hovered long enough? */
956 if(TrackingList[i].iHoverTime <= TrackingList[i].tme.dwHoverTime)
958 PostMessageA(TrackingList[i].tme.hwndTrack, WM_MOUSEHOVER, 0, 0);
960 /* stop tracking mouse hover */
961 TrackingList[i].tme.dwFlags ^= TME_HOVER;
965 /* see if we are still tracking TME_HOVER or TME_LEAVE for this entry */
966 if((TrackingList[i].tme.dwFlags & TME_HOVER) ||
967 (TrackingList[i].tme.dwFlags & TME_LEAVE)) {
969 } else { /* remove this entry from the tracking list */
970 TrackingList[i] = TrackingList[--iTrackMax];
974 /* stop the timer if the tracking list is empty */
981 /***********************************************************************
982 * _TrackMouseEvent [COMCTL32.25]
984 * Requests notification of mouse events
986 * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
987 * to the hwnd specified in the ptme structure. After the event message
988 * is posted to the hwnd, the entry in the queue is removed.
990 * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
991 * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
992 * immediately and the TME_LEAVE flag being ignored.
995 * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
1004 _TrackMouseEvent (TRACKMOUSEEVENT *ptme)
1008 BOOL cancel = 0, hover = 0, leave = 0, query = 0;
1015 TRACE("%lx, %lx, %x, %lx\n", ptme->cbSize, ptme->dwFlags, ptme->hwndTrack, ptme->dwHoverTime);
1017 if (ptme->cbSize != sizeof(TRACKMOUSEEVENT)) {
1018 WARN("wrong TRACKMOUSEEVENT size from app");
1019 SetLastError(ERROR_INVALID_PARAMETER); /* FIXME not sure if this is correct */
1023 flags = ptme->dwFlags;
1025 /* if HOVER_DEFAULT was specified replace this with the systems current value */
1026 if(ptme->dwHoverTime == HOVER_DEFAULT)
1027 SystemParametersInfoA(SPI_GETMOUSEHOVERTIME, 0, &(ptme->dwHoverTime), 0);
1030 hwnd = WindowFromPoint(pos);
1032 if ( flags & TME_CANCEL ) {
1033 flags &= ~ TME_CANCEL;
1037 if ( flags & TME_HOVER ) {
1038 flags &= ~ TME_HOVER;
1042 if ( flags & TME_LEAVE ) {
1043 flags &= ~ TME_LEAVE;
1047 /* fill the TRACKMOUSEEVENT struct with the current tracking for the given hwnd */
1048 if ( flags & TME_QUERY ) {
1049 flags &= ~ TME_QUERY;
1053 /* Find the tracking list entry with the matching hwnd */
1054 while((i < iTrackMax) && (TrackingList[i].tme.hwndTrack != ptme->hwndTrack)) {
1058 /* hwnd found, fill in the ptme struct */
1060 *ptme = TrackingList[i].tme;
1064 return TRUE; /* return here, TME_QUERY is retrieving information */
1068 FIXME("Unknown flag(s) %08lx\n", flags );
1071 /* find a matching hwnd if one exists */
1074 while((i < iTrackMax) && (TrackingList[i].tme.hwndTrack != ptme->hwndTrack)) {
1079 TrackingList[i].tme.dwFlags &= ~(ptme->dwFlags & ~TME_CANCEL);
1081 /* if we aren't tracking on hover or leave remove this entry */
1082 if(!((TrackingList[i].tme.dwFlags & TME_HOVER) ||
1083 (TrackingList[i].tme.dwFlags & TME_LEAVE)))
1085 TrackingList[i] = TrackingList[--iTrackMax];
1087 if(iTrackMax == 0) {
1088 KillTimer(0, timer);
1094 /* see if hwndTrack isn't the current window */
1095 if(ptme->hwndTrack != hwnd) {
1097 PostMessageA(ptme->hwndTrack, WM_MOUSELEAVE, 0, 0);
1100 /* See if this hwnd is already being tracked and update the tracking flags */
1101 for(i = 0; i < iTrackMax; i++) {
1102 if(TrackingList[i].tme.hwndTrack == ptme->hwndTrack) {
1104 TrackingList[i].tme.dwFlags |= TME_HOVER;
1105 TrackingList[i].tme.dwHoverTime = ptme->dwHoverTime;
1109 TrackingList[i].tme.dwFlags |= TME_LEAVE;
1111 /* reset iHoverTime as per winapi specs */
1112 TrackingList[i].iHoverTime = 0;
1118 /* if the tracking list is full return FALSE */
1119 if (iTrackMax == sizeof (TrackingList) / sizeof(*TrackingList)) {
1123 /* Adding new mouse event to the tracking list */
1124 TrackingList[iTrackMax].tme = *ptme;
1126 /* Initialize HoverInfo variables even if not hover tracking */
1127 TrackingList[iTrackMax].iHoverTime = 0;
1128 TrackingList[iTrackMax].pos = pos;
1133 timer = SetTimer(0, 0, iTimerInterval, TrackMouseEventProc);
1142 /*************************************************************************
1143 * GetMUILanguage [COMCTL32.39]
1145 * FIXME: What's this supposed to do? Apparently some i18n thing.
1148 LANGID WINAPI GetMUILanguage (VOID)
1150 return COMCTL32_uiLang;
1154 /*************************************************************************
1155 * InitMUILanguage [COMCTL32.85]
1157 * FIXME: What's this supposed to do? Apparently some i18n thing.
1161 VOID WINAPI InitMUILanguage (LANGID uiLang)
1163 COMCTL32_uiLang = uiLang;
1167 /***********************************************************************
1168 * COMCTL32_CreateToolTip [NOT AN API]
1170 * Creates a tooltip for the control specified in hwnd and does all
1171 * necessary setup and notifications.
1174 * hwndOwner [I] Handle to the window that will own the tool tip.
1177 * Success: Handle of tool tip window.
1181 COMCTL32_CreateToolTip(HWND hwndOwner)
1185 hwndToolTip = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
1186 CW_USEDEFAULT, CW_USEDEFAULT,
1187 CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner,
1190 /* Send NM_TOOLTIPSCREATED notification */
1193 NMTOOLTIPSCREATED nmttc;
1195 nmttc.hdr.hwndFrom = hwndOwner;
1196 nmttc.hdr.idFrom = GetWindowLongA(hwndOwner, GWL_ID);
1197 nmttc.hdr.code = NM_TOOLTIPSCREATED;
1198 nmttc.hwndToolTips = hwndToolTip;
1200 SendMessageA(GetParent(hwndOwner), WM_NOTIFY,
1201 (WPARAM)GetWindowLongA(hwndOwner, GWL_ID),