2 * Common controls functions
4 * Copyright 1997 Dimitrie O. Paun
5 * Copyright 1998,2000 Eric Kohl
14 #include "debugtools.h"
17 DEFAULT_DEBUG_CHANNEL(commctrl);
19 extern void ANIMATE_Register(void);
20 extern void ANIMATE_Unregister(void);
21 extern void COMBOEX_Register(void);
22 extern void COMBOEX_Unregister(void);
23 extern void DATETIME_Register(void);
24 extern void DATETIME_Unregister(void);
25 extern void FLATSB_Register(void);
26 extern void FLATSB_Unregister(void);
27 extern void HEADER_Register(void);
28 extern void HEADER_Unregister(void);
29 extern void HOTKEY_Register(void);
30 extern void HOTKEY_Unregister(void);
31 extern void IPADDRESS_Register(void);
32 extern void IPADDRESS_Unregister(void);
33 extern void LISTVIEW_Register(void);
34 extern void LISTVIEW_Unregister(void);
35 extern void MONTHCAL_Register(void);
36 extern void MONTHCAL_Unregister(void);
37 extern void NATIVEFONT_Register(void);
38 extern void NATIVEFONT_Unregister(void);
39 extern void PAGER_Register(void);
40 extern void PAGER_Unregister(void);
41 extern void PROGRESS_Register(void);
42 extern void PROGRESS_Unregister(void);
43 extern void REBAR_Register(void);
44 extern void REBAR_Unregister(void);
45 extern void STATUS_Register(void);
46 extern void STATUS_Unregister(void);
47 extern void TAB_Register(void);
48 extern void TAB_Unregister(void);
49 extern void TOOLBAR_Register(void);
50 extern void TOOLBAR_Unregister(void);
51 extern void TOOLTIPS_Register(void);
52 extern void TOOLTIPS_Unregister(void);
53 extern void TRACKBAR_Register(void);
54 extern void TRACKBAR_Unregister(void);
55 extern void TREEVIEW_Register(void);
56 extern void TREEVIEW_Unregister(void);
57 extern void UPDOWN_Register(void);
58 extern void UPDOWN_Unregister(void);
61 HANDLE COMCTL32_hHeap = (HANDLE)NULL;
62 DWORD COMCTL32_dwProcessesAttached = 0;
63 LPSTR COMCTL32_aSubclass = (LPSTR)NULL;
64 HMODULE COMCTL32_hModule = 0;
65 LANGID COMCTL32_uiLang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
68 /***********************************************************************
69 * COMCTL32_LibMain [Internal] Initializes the internal 'COMCTL32.DLL'.
72 * hinstDLL [I] handle to the 'dlls' instance
74 * lpvReserved [I] reserverd, must be NULL
82 COMCTL32_LibMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
84 TRACE("%x,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
87 case DLL_PROCESS_ATTACH:
88 if (COMCTL32_dwProcessesAttached == 0) {
90 /* This will be wrong for any other process attching in this address-space! */
91 COMCTL32_hModule = (HMODULE)hinstDLL;
93 /* create private heap */
94 COMCTL32_hHeap = HeapCreate (0, 0x10000, 0);
95 TRACE("Heap created: 0x%x\n", COMCTL32_hHeap);
97 /* add global subclassing atom (used by 'tooltip' and 'updown') */
98 COMCTL32_aSubclass = (LPSTR)(DWORD)GlobalAddAtomA ("CC32SubclassInfo");
99 TRACE("Subclassing atom added: %p\n",
102 /* register all Win95 common control classes */
107 LISTVIEW_Register ();
108 PROGRESS_Register ();
112 TOOLTIPS_Register ();
113 TRACKBAR_Register ();
114 TREEVIEW_Register ();
117 COMCTL32_dwProcessesAttached++;
120 case DLL_PROCESS_DETACH:
121 COMCTL32_dwProcessesAttached--;
122 if (COMCTL32_dwProcessesAttached == 0) {
123 /* unregister all common control classes */
124 ANIMATE_Unregister ();
125 COMBOEX_Unregister ();
126 DATETIME_Unregister ();
127 FLATSB_Unregister ();
128 HEADER_Unregister ();
129 HOTKEY_Unregister ();
130 IPADDRESS_Unregister ();
131 LISTVIEW_Unregister ();
132 MONTHCAL_Unregister ();
133 NATIVEFONT_Unregister ();
135 PROGRESS_Unregister ();
137 STATUS_Unregister ();
139 TOOLBAR_Unregister ();
140 TOOLTIPS_Unregister ();
141 TRACKBAR_Unregister ();
142 TREEVIEW_Unregister ();
143 UPDOWN_Unregister ();
145 /* delete global subclassing atom */
146 GlobalDeleteAtom (LOWORD(COMCTL32_aSubclass));
147 TRACE("Subclassing atom deleted: %p\n",
149 COMCTL32_aSubclass = (LPSTR)NULL;
151 /* destroy private heap */
152 HeapDestroy (COMCTL32_hHeap);
153 TRACE("Heap destroyed: 0x%x\n", COMCTL32_hHeap);
154 COMCTL32_hHeap = (HANDLE)NULL;
163 /***********************************************************************
164 * MenuHelp [COMCTL32.2]
167 * uMsg [I] message (WM_MENUSELECT) (see NOTES)
168 * wParam [I] wParam of the message uMsg
169 * lParam [I] lParam of the message uMsg
170 * hMainMenu [I] handle to the application's main menu
171 * hInst [I] handle to the module that contains string resources
172 * hwndStatus [I] handle to the status bar window
173 * lpwIDs [I] pointer to an array of intergers (see NOTES)
179 * The official documentation is incomplete!
180 * This is the correct documentation:
183 * MenuHelp() does NOT handle WM_COMMAND messages! It only handles
184 * WM_MENUSELECT messages.
187 * (will be written ...)
191 MenuHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu,
192 HINSTANCE hInst, HWND hwndStatus, LPUINT lpwIDs)
196 if (!IsWindow (hwndStatus))
201 TRACE("WM_MENUSELECT wParam=0x%X lParam=0x%lX\n",
204 if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {
205 /* menu was closed */
206 TRACE("menu was closed!\n");
207 SendMessageA (hwndStatus, SB_SIMPLE, FALSE, 0);
210 /* menu item was selected */
211 if (HIWORD(wParam) & MF_POPUP)
212 uMenuID = (UINT)*(lpwIDs+1);
214 uMenuID = (UINT)LOWORD(wParam);
215 TRACE("uMenuID = %u\n", uMenuID);
220 if (!LoadStringA (hInst, uMenuID, szText, 256))
223 SendMessageA (hwndStatus, SB_SETTEXTA,
224 255 | SBT_NOBORDERS, (LPARAM)szText);
225 SendMessageA (hwndStatus, SB_SIMPLE, TRUE, 0);
231 TRACE("WM_COMMAND wParam=0x%X lParam=0x%lX\n",
233 /* WM_COMMAND is not invalid since it is documented
234 * in the windows api reference. So don't output
235 * any FIXME for WM_COMMAND
237 WARN("We don't care about the WM_COMMAND\n");
241 FIXME("Invalid Message 0x%x!\n", uMsg);
247 /***********************************************************************
248 * ShowHideMenuCtl [COMCTL32.3]
250 * Shows or hides controls and updates the corresponding menu item.
253 * hwnd [I] handle to the client window.
254 * uFlags [I] menu command id.
255 * lpInfo [I] pointer to an array of integers. (See NOTES.)
262 * The official documentation is incomplete!
263 * This is the correct documentation:
266 * Handle to the window that contains the menu and controls.
269 * Identifier of the menu item to receive or loose a check mark.
272 * The array of integers contains pairs of values. BOTH values of
273 * the first pair must be the handles to the application's main menu.
274 * Each subsequent pair consists of a menu id and control id.
278 ShowHideMenuCtl (HWND hwnd, UINT uFlags, LPINT lpInfo)
282 TRACE("%x, %x, %p\n", hwnd, uFlags, lpInfo);
287 if (!(lpInfo[0]) || !(lpInfo[1]))
290 /* search for control */
291 lpMenuId = &lpInfo[2];
292 while (*lpMenuId != uFlags)
295 if (GetMenuState (lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) {
296 /* uncheck menu item */
297 CheckMenuItem (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_UNCHECKED);
301 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
305 /* check menu item */
306 CheckMenuItem (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_CHECKED);
310 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
318 /***********************************************************************
319 * GetEffectiveClientRect [COMCTL32.4]
322 * hwnd [I] handle to the client window.
323 * lpRect [O] pointer to the rectangle of the client window
324 * lpInfo [I] pointer to an array of integers (see NOTES)
330 * The official documentation is incomplete!
331 * This is the correct documentation:
334 * (will be written...)
338 GetEffectiveClientRect (HWND hwnd, LPRECT lpRect, LPINT lpInfo)
344 TRACE("(0x%08lx 0x%08lx 0x%08lx)\n",
345 (DWORD)hwnd, (DWORD)lpRect, (DWORD)lpInfo);
347 GetClientRect (hwnd, lpRect);
355 hwndCtrl = GetDlgItem (hwnd, *lpRun);
356 if (GetWindowLongA (hwndCtrl, GWL_STYLE) & WS_VISIBLE) {
357 TRACE("control id 0x%x\n", *lpRun);
358 GetWindowRect (hwndCtrl, &rcCtrl);
359 MapWindowPoints ((HWND)0, hwnd, (LPPOINT)&rcCtrl, 2);
360 SubtractRect (lpRect, lpRect, &rcCtrl);
367 /***********************************************************************
368 * DrawStatusTextA [COMCTL32.5][COMCTL32.27]
370 * Draws text with borders, like in a status bar.
373 * hdc [I] handle to the window's display context
374 * lprc [I] pointer to a rectangle
375 * text [I] pointer to the text
376 * style [I] drawing style
382 * The style variable can have one of the following values:
383 * (will be written ...)
387 DrawStatusTextA (HDC hdc, LPRECT lprc, LPCSTR text, UINT style)
390 UINT border = BDR_SUNKENOUTER;
392 if (style & SBT_POPOUT)
393 border = BDR_RAISEDOUTER;
394 else if (style & SBT_NOBORDERS)
397 DrawEdge (hdc, &r, border, BF_RECT|BF_ADJUST|BF_MIDDLE);
401 int oldbkmode = SetBkMode (hdc, TRANSPARENT);
403 DrawTextA (hdc, text, lstrlenA(text),
404 &r, DT_LEFT|DT_VCENTER|DT_SINGLELINE);
405 if (oldbkmode != TRANSPARENT)
406 SetBkMode(hdc, oldbkmode);
411 /***********************************************************************
412 * DrawStatusTextW [COMCTL32.28]
414 * Draws text with borders, like in a status bar.
417 * hdc [I] handle to the window's display context
418 * lprc [I] pointer to a rectangle
419 * text [I] pointer to the text
420 * style [I] drawing style
427 DrawStatusTextW (HDC hdc, LPRECT lprc, LPCWSTR text, UINT style)
429 LPSTR p = HEAP_strdupWtoA (GetProcessHeap (), 0, text);
430 DrawStatusTextA (hdc, lprc, p, style);
431 HeapFree (GetProcessHeap (), 0, p );
435 /***********************************************************************
436 * CreateStatusWindowA [COMCTL32.6][COMCTL32.21]
438 * Creates a status bar
441 * style [I] window style
442 * text [I] pointer to the window text
443 * parent [I] handle to the parent window
444 * wid [I] control id of the status bar
447 * Success: handle to the status window
452 CreateStatusWindowA (INT style, LPCSTR text, HWND parent, UINT wid)
454 return CreateWindowA(STATUSCLASSNAMEA, text, style,
455 CW_USEDEFAULT, CW_USEDEFAULT,
456 CW_USEDEFAULT, CW_USEDEFAULT,
461 /***********************************************************************
462 * CreateStatusWindowW [COMCTL32.22] Creates a status bar control
465 * style [I] window style
466 * text [I] pointer to the window text
467 * parent [I] handle to the parent window
468 * wid [I] control id of the status bar
471 * Success: handle to the status window
476 CreateStatusWindowW (INT style, LPCWSTR text, HWND parent, UINT wid)
478 return CreateWindowW(STATUSCLASSNAMEW, text, style,
479 CW_USEDEFAULT, CW_USEDEFAULT,
480 CW_USEDEFAULT, CW_USEDEFAULT,
485 /***********************************************************************
486 * CreateUpDownControl [COMCTL32.16] Creates an up-down control
489 * style [I] window styles
490 * x [I] horizontal position of the control
491 * y [I] vertical position of the control
492 * cx [I] with of the control
493 * cy [I] height of the control
494 * parent [I] handle to the parent window
495 * id [I] the control's identifier
496 * inst [I] handle to the application's module instance
497 * buddy [I] handle to the buddy window, can be NULL
498 * maxVal [I] upper limit of the control
499 * minVal [I] lower limit of the control
500 * curVal [I] current value of the control
503 * Success: handle to the updown control
508 CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
509 HWND parent, INT id, HINSTANCE inst,
510 HWND buddy, INT maxVal, INT minVal, INT curVal)
513 CreateWindowA (UPDOWN_CLASSA, 0, style, x, y, cx, cy,
514 parent, id, inst, 0);
516 SendMessageA (hUD, UDM_SETBUDDY, buddy, 0);
517 SendMessageA (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));
518 SendMessageA (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));
525 /***********************************************************************
526 * InitCommonControls [COMCTL32.17]
528 * Registers the common controls.
537 * This function is just a dummy.
538 * The Win95 controls are registered at the DLL's initialization.
539 * To register other controls InitCommonControlsEx() must be used.
543 InitCommonControls (void)
548 /***********************************************************************
549 * InitCommonControlsEx [COMCTL32.81]
551 * Registers the common controls.
554 * lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
561 * Only the additinal common controls are registered by this function.
562 * The Win95 controls are registered at the DLL's initialization.
566 InitCommonControlsEx (LPINITCOMMONCONTROLSEX lpInitCtrls)
573 if (lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
576 TRACE("(0x%08lx)\n", lpInitCtrls->dwICC);
578 for (cCount = 0; cCount < 32; cCount++) {
579 dwMask = 1 << cCount;
580 if (!(lpInitCtrls->dwICC & dwMask))
583 switch (lpInitCtrls->dwICC & dwMask) {
584 /* dummy initialization */
585 case ICC_ANIMATE_CLASS:
586 case ICC_BAR_CLASSES:
587 case ICC_LISTVIEW_CLASSES:
588 case ICC_TREEVIEW_CLASSES:
589 case ICC_TAB_CLASSES:
590 case ICC_UPDOWN_CLASS:
591 case ICC_PROGRESS_CLASS:
592 case ICC_HOTKEY_CLASS:
595 /* advanced classes - not included in Win95 */
596 case ICC_DATE_CLASSES:
597 MONTHCAL_Register ();
598 DATETIME_Register ();
601 case ICC_USEREX_CLASSES:
605 case ICC_COOL_CLASSES:
609 case ICC_INTERNET_CLASSES:
610 IPADDRESS_Register ();
613 case ICC_PAGESCROLLER_CLASS:
617 case ICC_NATIVEFNTCTL_CLASS:
618 NATIVEFONT_Register ();
622 FIXME("Unknown class! dwICC=0x%lX\n", dwMask);
631 /***********************************************************************
632 * CreateToolbarEx [COMCTL32.32] Creates a tool bar window
650 * Success: handle to the tool bar control
655 CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
656 HINSTANCE hBMInst, UINT wBMID, LPCTBBUTTON lpButtons,
657 INT iNumButtons, INT dxButton, INT dyButton,
658 INT dxBitmap, INT dyBitmap, UINT uStructSize)
662 /* If not position is specified then put it at the top */
663 if ((style & CCS_BOTTOM) == 0) {
668 CreateWindowExA (0, TOOLBARCLASSNAMEA, "", style|WS_CHILD, 0, 0, 0, 0,
669 hwnd, (HMENU)wID, 0, NULL);
673 SendMessageA (hwndTB, TB_BUTTONSTRUCTSIZE,
674 (WPARAM)uStructSize, 0);
676 /* set bitmap and button size */
677 /*If CreateToolbarEx receives 0, windows sets default values*/
682 SendMessageA (hwndTB, TB_SETBITMAPSIZE, 0,
683 MAKELPARAM((WORD)dxBitmap, (WORD)dyBitmap));
689 SendMessageA (hwndTB, TB_SETBUTTONSIZE, 0,
690 MAKELPARAM((WORD)dxButton, (WORD)dyButton));
696 tbab.hInst = hBMInst;
699 SendMessageA (hwndTB, TB_ADDBITMAP,
700 (WPARAM)nBitmaps, (LPARAM)&tbab);
704 SendMessageA (hwndTB, TB_ADDBUTTONSA,
705 (WPARAM)iNumButtons, (LPARAM)lpButtons);
712 /***********************************************************************
713 * CreateMappedBitmap [COMCTL32.8]
723 * Success: handle to the new bitmap
728 CreateMappedBitmap (HINSTANCE hInstance, INT idBitmap, UINT wFlags,
729 LPCOLORMAP lpColorMap, INT iNumMaps)
733 LPBITMAPINFOHEADER lpBitmap, lpBitmapInfo;
734 UINT nSize, nColorTableSize;
735 RGBQUAD *pColorTable;
736 INT iColor, i, iMaps, nWidth, nHeight;
739 LPCOLORMAP sysColorMap;
741 COLORMAP internalColorMap[4] =
742 {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
744 /* initialize pointer to colortable and default color table */
747 sysColorMap = lpColorMap;
750 internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT);
751 internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW);
752 internalColorMap[2].to = GetSysColor (COLOR_BTNFACE);
753 internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT);
755 sysColorMap = (LPCOLORMAP)internalColorMap;
758 hRsrc = FindResourceA (hInstance, (LPSTR)idBitmap, RT_BITMAPA);
761 hglb = LoadResource (hInstance, hRsrc);
764 lpBitmap = (LPBITMAPINFOHEADER)LockResource (hglb);
765 if (lpBitmap == NULL)
768 nColorTableSize = (1 << lpBitmap->biBitCount);
769 nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
770 lpBitmapInfo = (LPBITMAPINFOHEADER)GlobalAlloc (GMEM_FIXED, nSize);
771 if (lpBitmapInfo == NULL)
773 RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);
775 pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo)+(UINT)lpBitmapInfo->biSize);
777 for (iColor = 0; iColor < nColorTableSize; iColor++) {
778 for (i = 0; i < iMaps; i++) {
779 cRef = RGB(pColorTable[iColor].rgbRed,
780 pColorTable[iColor].rgbGreen,
781 pColorTable[iColor].rgbBlue);
782 if ( cRef == sysColorMap[i].from) {
784 if (wFlags & CBS_MASKED) {
785 if (sysColorMap[i].to != COLOR_BTNTEXT)
786 pColorTable[iColor] = RGB(255, 255, 255);
790 pColorTable[iColor].rgbBlue = GetBValue(sysColorMap[i].to);
791 pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);
792 pColorTable[iColor].rgbRed = GetRValue(sysColorMap[i].to);
797 nWidth = (INT)lpBitmapInfo->biWidth;
798 nHeight = (INT)lpBitmapInfo->biHeight;
799 hdcScreen = GetDC ((HWND)0);
800 hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
802 HDC hdcDst = CreateCompatibleDC (hdcScreen);
803 HBITMAP hbmOld = SelectObject (hdcDst, hbm);
804 LPBYTE lpBits = (LPBYTE)(lpBitmap + 1);
805 lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
806 StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
807 lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
809 SelectObject (hdcDst, hbmOld);
812 ReleaseDC ((HWND)0, hdcScreen);
813 GlobalFree ((HGLOBAL)lpBitmapInfo);
820 /***********************************************************************
821 * CreateToolbar [COMCTL32.7] Creates a tool bar control
834 * Success: handle to the tool bar control
838 * Do not use this functions anymore. Use CreateToolbarEx instead.
842 CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
843 HINSTANCE hBMInst, UINT wBMID,
844 LPCOLDTBBUTTON lpButtons,INT iNumButtons)
846 return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
847 hBMInst, wBMID, (LPCTBBUTTON)lpButtons,
848 iNumButtons, 0, 0, 0, 0, sizeof (OLDTBBUTTON));
852 /***********************************************************************
853 * DllGetVersion [COMCTL32.25]
855 * Retrieves version information of the 'COMCTL32.DLL'
858 * pdvi [O] pointer to version information structure.
862 * Failure: E_INVALIDARG
865 * Returns version of a comctl32.dll from IE4.01 SP1.
869 COMCTL32_DllGetVersion (DLLVERSIONINFO *pdvi)
871 if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
872 WARN("wrong DLLVERSIONINFO size from app");
876 pdvi->dwMajorVersion = 5;
877 pdvi->dwMinorVersion = 0;
878 pdvi->dwBuildNumber = 2919;
879 pdvi->dwPlatformID = 6304;
881 TRACE("%lu.%lu.%lu.%lu\n",
882 pdvi->dwMajorVersion, pdvi->dwMinorVersion,
883 pdvi->dwBuildNumber, pdvi->dwPlatformID);
888 /***********************************************************************
889 * DllInstall (COMCTL32.@)
891 HRESULT WINAPI COMCTL32_DllInstall(BOOL bInstall, LPCWSTR cmdline)
893 FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
894 debugstr_w(cmdline));
900 typedef struct __TRACKINGLIST {
902 POINT pos; /* center of hover rectangle */
903 INT iHoverTime; /* elapsed time the cursor has been inside of the hover rect */
906 static _TRACKINGLIST TrackingList[10];
907 static int iTrackMax = 0;
908 static UINT_PTR timer;
909 static const INT iTimerInterval = 50; /* msec for timer interval */
911 /* FIXME: need to implement WM_NCMOUSELEAVE and WM_NCMOUSEHOVER for */
912 /* TrackMouseEventProc and _TrackMouseEvent */
913 static void CALLBACK TrackMouseEventProc(HWND hwndUnused, UINT uMsg, UINT_PTR idEvent,
919 INT hoverwidth = 0, hoverheight = 0;
922 hwnd = WindowFromPoint(pos);
924 SystemParametersInfoA(SPI_GETMOUSEHOVERWIDTH, 0, &hoverwidth, 0);
925 SystemParametersInfoA(SPI_GETMOUSEHOVERHEIGHT, 0, &hoverheight, 0);
927 /* loop through tracking events we are processing */
928 while (i < iTrackMax) {
929 /* see if this tracking event is looking for TME_LEAVE and that the */
930 /* mouse has left the window */
931 if ((TrackingList[i].tme.dwFlags & TME_LEAVE) &&
932 (TrackingList[i].tme.hwndTrack != hwnd)) {
933 PostMessageA(TrackingList[i].tme.hwndTrack, WM_MOUSELEAVE, 0, 0);
935 /* remove the TME_LEAVE flag */
936 TrackingList[i].tme.dwFlags ^= TME_LEAVE;
939 /* see if we are tracking hovering for this hwnd */
940 if(TrackingList[i].tme.dwFlags & TME_HOVER) {
941 /* add the timer interval to the hovering time */
942 TrackingList[i].iHoverTime+=iTimerInterval;
944 /* has the cursor moved outside the rectangle centered around pos? */
945 if((abs(pos.x - TrackingList[i].pos.x) > (hoverwidth / 2.0))
946 || (abs(pos.y - TrackingList[i].pos.y) > (hoverheight / 2.0)))
948 /* record this new position as the current position and reset */
949 /* the iHoverTime variable to 0 */
950 TrackingList[i].pos = pos;
951 TrackingList[i].iHoverTime = 0;
954 /* has the mouse hovered long enough? */
955 if(TrackingList[i].iHoverTime <= TrackingList[i].tme.dwHoverTime)
957 PostMessageA(TrackingList[i].tme.hwndTrack, WM_MOUSEHOVER, 0, 0);
959 /* stop tracking mouse hover */
960 TrackingList[i].tme.dwFlags ^= TME_HOVER;
964 /* see if we are still tracking TME_HOVER or TME_LEAVE for this entry */
965 if((TrackingList[i].tme.dwFlags & TME_HOVER) ||
966 (TrackingList[i].tme.dwFlags & TME_LEAVE)) {
968 } else { /* remove this entry from the tracking list */
969 TrackingList[i] = TrackingList[--iTrackMax];
973 /* stop the timer if the tracking list is empty */
980 /***********************************************************************
981 * _TrackMouseEvent [COMCTL32.25]
983 * Requests notification of mouse events
985 * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
986 * to the hwnd specified in the ptme structure. After the event message
987 * is posted to the hwnd, the entry in the queue is removed.
989 * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
990 * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
991 * immediately and the TME_LEAVE flag being ignored.
994 * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
1003 _TrackMouseEvent (TRACKMOUSEEVENT *ptme)
1007 BOOL cancel = 0, hover = 0, leave = 0, query = 0;
1014 TRACE("%lx, %lx, %x, %lx\n", ptme->cbSize, ptme->dwFlags, ptme->hwndTrack, ptme->dwHoverTime);
1016 if (ptme->cbSize != sizeof(TRACKMOUSEEVENT)) {
1017 WARN("wrong TRACKMOUSEEVENT size from app");
1018 SetLastError(ERROR_INVALID_PARAMETER); /* FIXME not sure if this is correct */
1022 flags = ptme->dwFlags;
1024 /* if HOVER_DEFAULT was specified replace this with the systems current value */
1025 if(ptme->dwHoverTime == HOVER_DEFAULT)
1026 SystemParametersInfoA(SPI_GETMOUSEHOVERTIME, 0, &(ptme->dwHoverTime), 0);
1029 hwnd = WindowFromPoint(pos);
1031 if ( flags & TME_CANCEL ) {
1032 flags &= ~ TME_CANCEL;
1036 if ( flags & TME_HOVER ) {
1037 flags &= ~ TME_HOVER;
1041 if ( flags & TME_LEAVE ) {
1042 flags &= ~ TME_LEAVE;
1046 /* fill the TRACKMOUSEEVENT struct with the current tracking for the given hwnd */
1047 if ( flags & TME_QUERY ) {
1048 flags &= ~ TME_QUERY;
1052 /* Find the tracking list entry with the matching hwnd */
1053 while((i < iTrackMax) && (TrackingList[i].tme.hwndTrack != ptme->hwndTrack)) {
1057 /* hwnd found, fill in the ptme struct */
1059 *ptme = TrackingList[i].tme;
1063 return TRUE; /* return here, TME_QUERY is retrieving information */
1067 FIXME("Unknown flag(s) %08lx\n", flags );
1070 /* find a matching hwnd if one exists */
1073 while((i < iTrackMax) && (TrackingList[i].tme.hwndTrack != ptme->hwndTrack)) {
1078 TrackingList[i].tme.dwFlags &= ~(ptme->dwFlags & ~TME_CANCEL);
1080 /* if we aren't tracking on hover or leave remove this entry */
1081 if(!((TrackingList[i].tme.dwFlags & TME_HOVER) ||
1082 (TrackingList[i].tme.dwFlags & TME_LEAVE)))
1084 TrackingList[i] = TrackingList[--iTrackMax];
1086 if(iTrackMax == 0) {
1087 KillTimer(0, timer);
1093 /* see if hwndTrack isn't the current window */
1094 if(ptme->hwndTrack != hwnd) {
1096 PostMessageA(ptme->hwndTrack, WM_MOUSELEAVE, 0, 0);
1099 /* See if this hwnd is already being tracked and update the tracking flags */
1100 for(i = 0; i < iTrackMax; i++) {
1101 if(TrackingList[i].tme.hwndTrack == ptme->hwndTrack) {
1103 TrackingList[i].tme.dwFlags |= TME_HOVER;
1104 TrackingList[i].tme.dwHoverTime = ptme->dwHoverTime;
1108 TrackingList[i].tme.dwFlags |= TME_LEAVE;
1110 /* reset iHoverTime as per winapi specs */
1111 TrackingList[i].iHoverTime = 0;
1117 /* if the tracking list is full return FALSE */
1118 if (iTrackMax == sizeof (TrackingList) / sizeof(*TrackingList)) {
1122 /* Adding new mouse event to the tracking list */
1123 TrackingList[iTrackMax].tme = *ptme;
1125 /* Initialize HoverInfo variables even if not hover tracking */
1126 TrackingList[iTrackMax].iHoverTime = 0;
1127 TrackingList[iTrackMax].pos = pos;
1132 timer = SetTimer(0, 0, iTimerInterval, TrackMouseEventProc);
1141 /*************************************************************************
1142 * GetMUILanguage [COMCTL32.39]
1144 * FIXME: What's this supposed to do? Apparently some i18n thing.
1147 LANGID WINAPI GetMUILanguage (VOID)
1149 return COMCTL32_uiLang;
1153 /*************************************************************************
1154 * InitMUILanguage [COMCTL32.85]
1156 * FIXME: What's this supposed to do? Apparently some i18n thing.
1160 VOID WINAPI InitMUILanguage (LANGID uiLang)
1162 COMCTL32_uiLang = uiLang;
1166 /***********************************************************************
1167 * COMCTL32_CreateToolTip [NOT AN API]
1169 * Creates a tooltip for the control specified in hwnd and does all
1170 * necessary setup and notifications.
1173 * hwndOwner [I] Handle to the window that will own the tool tip.
1176 * Success: Handle of tool tip window.
1180 COMCTL32_CreateToolTip(HWND hwndOwner)
1184 hwndToolTip = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
1185 CW_USEDEFAULT, CW_USEDEFAULT,
1186 CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner,
1189 /* Send NM_TOOLTIPSCREATED notification */
1192 NMTOOLTIPSCREATED nmttc;
1194 nmttc.hdr.hwndFrom = hwndOwner;
1195 nmttc.hdr.idFrom = GetWindowLongA(hwndOwner, GWL_ID);
1196 nmttc.hdr.code = NM_TOOLTIPSCREATED;
1197 nmttc.hwndToolTips = hwndToolTip;
1199 SendMessageA(GetParent(hwndOwner), WM_NOTIFY,
1200 (WPARAM)GetWindowLongA(hwndOwner, GWL_ID),