2 * Common controls functions
4 * Copyright 1997 Dimitrie O. Paun
5 * Copyright 1998,2000 Eric Kohl
18 #include "debugtools.h"
20 DEFAULT_DEBUG_CHANNEL(commctrl);
22 extern void ANIMATE_Register(void);
23 extern void ANIMATE_Unregister(void);
24 extern void COMBOEX_Register(void);
25 extern void COMBOEX_Unregister(void);
26 extern void DATETIME_Register(void);
27 extern void DATETIME_Unregister(void);
28 extern void FLATSB_Register(void);
29 extern void FLATSB_Unregister(void);
30 extern void HEADER_Register(void);
31 extern void HEADER_Unregister(void);
32 extern void HOTKEY_Register(void);
33 extern void HOTKEY_Unregister(void);
34 extern void IPADDRESS_Register(void);
35 extern void IPADDRESS_Unregister(void);
36 extern void LISTVIEW_Register(void);
37 extern void LISTVIEW_Unregister(void);
38 extern void MONTHCAL_Register(void);
39 extern void MONTHCAL_Unregister(void);
40 extern void NATIVEFONT_Register(void);
41 extern void NATIVEFONT_Unregister(void);
42 extern void PAGER_Register(void);
43 extern void PAGER_Unregister(void);
44 extern void PROGRESS_Register(void);
45 extern void PROGRESS_Unregister(void);
46 extern void REBAR_Register(void);
47 extern void REBAR_Unregister(void);
48 extern void STATUS_Register(void);
49 extern void STATUS_Unregister(void);
50 extern void TAB_Register(void);
51 extern void TAB_Unregister(void);
52 extern void TOOLBAR_Register(void);
53 extern void TOOLBAR_Unregister(void);
54 extern void TOOLTIPS_Register(void);
55 extern void TOOLTIPS_Unregister(void);
56 extern void TRACKBAR_Register(void);
57 extern void TRACKBAR_Unregister(void);
58 extern void TREEVIEW_Register(void);
59 extern void TREEVIEW_Unregister(void);
60 extern void UPDOWN_Register(void);
61 extern void UPDOWN_Unregister(void);
64 HANDLE COMCTL32_hHeap = (HANDLE)NULL;
65 LPSTR COMCTL32_aSubclass = (LPSTR)NULL;
66 HMODULE COMCTL32_hModule = 0;
67 LANGID COMCTL32_uiLang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
68 HBRUSH COMCTL32_hPattern55AABrush = (HANDLE)NULL;
70 static HBITMAP COMCTL32_hPattern55AABitmap = (HANDLE)NULL;
72 static const WORD wPattern55AA[] =
74 0x5555, 0xaaaa, 0x5555, 0xaaaa,
75 0x5555, 0xaaaa, 0x5555, 0xaaaa
79 /***********************************************************************
80 * COMCTL32_LibMain [Internal] Initializes the internal 'COMCTL32.DLL'.
83 * hinstDLL [I] handle to the 'dlls' instance
85 * lpvReserved [I] reserverd, must be NULL
93 COMCTL32_LibMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
95 TRACE("%x,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
98 case DLL_PROCESS_ATTACH:
99 COMCTL32_hModule = (HMODULE)hinstDLL;
101 /* create private heap */
102 COMCTL32_hHeap = HeapCreate (0, 0x10000, 0);
103 TRACE("Heap created: 0x%x\n", COMCTL32_hHeap);
105 /* add global subclassing atom (used by 'tooltip' and 'updown') */
106 COMCTL32_aSubclass = (LPSTR)(DWORD)GlobalAddAtomA ("CC32SubclassInfo");
107 TRACE("Subclassing atom added: %p\n", COMCTL32_aSubclass);
109 /* create local pattern brush */
110 COMCTL32_hPattern55AABitmap = CreateBitmap (8, 8, 1, 1, wPattern55AA);
111 COMCTL32_hPattern55AABrush = CreatePatternBrush (COMCTL32_hPattern55AABitmap);
113 /* register all Win95 common control classes */
118 LISTVIEW_Register ();
119 PROGRESS_Register ();
123 TOOLTIPS_Register ();
124 TRACKBAR_Register ();
125 TREEVIEW_Register ();
129 case DLL_PROCESS_DETACH:
130 /* unregister all common control classes */
131 ANIMATE_Unregister ();
132 COMBOEX_Unregister ();
133 DATETIME_Unregister ();
134 FLATSB_Unregister ();
135 HEADER_Unregister ();
136 HOTKEY_Unregister ();
137 IPADDRESS_Unregister ();
138 LISTVIEW_Unregister ();
139 MONTHCAL_Unregister ();
140 NATIVEFONT_Unregister ();
142 PROGRESS_Unregister ();
144 STATUS_Unregister ();
146 TOOLBAR_Unregister ();
147 TOOLTIPS_Unregister ();
148 TRACKBAR_Unregister ();
149 TREEVIEW_Unregister ();
150 UPDOWN_Unregister ();
152 /* delete local pattern brush */
153 DeleteObject (COMCTL32_hPattern55AABrush);
154 COMCTL32_hPattern55AABrush = (HANDLE)NULL;
155 DeleteObject (COMCTL32_hPattern55AABitmap);
156 COMCTL32_hPattern55AABitmap = (HANDLE)NULL;
158 /* delete global subclassing atom */
159 GlobalDeleteAtom (LOWORD(COMCTL32_aSubclass));
160 TRACE("Subclassing atom deleted: %p\n", COMCTL32_aSubclass);
161 COMCTL32_aSubclass = (LPSTR)NULL;
163 /* destroy private heap */
164 HeapDestroy (COMCTL32_hHeap);
165 TRACE("Heap destroyed: 0x%x\n", COMCTL32_hHeap);
166 COMCTL32_hHeap = (HANDLE)NULL;
174 /***********************************************************************
175 * MenuHelp [COMCTL32.2]
178 * uMsg [I] message (WM_MENUSELECT) (see NOTES)
179 * wParam [I] wParam of the message uMsg
180 * lParam [I] lParam of the message uMsg
181 * hMainMenu [I] handle to the application's main menu
182 * hInst [I] handle to the module that contains string resources
183 * hwndStatus [I] handle to the status bar window
184 * lpwIDs [I] pointer to an array of integers (see NOTES)
190 * The official documentation is incomplete!
191 * This is the correct documentation:
194 * MenuHelp() does NOT handle WM_COMMAND messages! It only handles
195 * WM_MENUSELECT messages.
198 * (will be written ...)
202 MenuHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu,
203 HINSTANCE hInst, HWND hwndStatus, LPUINT lpwIDs)
207 if (!IsWindow (hwndStatus))
212 TRACE("WM_MENUSELECT wParam=0x%X lParam=0x%lX\n",
215 if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {
216 /* menu was closed */
217 TRACE("menu was closed!\n");
218 SendMessageA (hwndStatus, SB_SIMPLE, FALSE, 0);
221 /* menu item was selected */
222 if (HIWORD(wParam) & MF_POPUP)
223 uMenuID = (UINT)*(lpwIDs+1);
225 uMenuID = (UINT)LOWORD(wParam);
226 TRACE("uMenuID = %u\n", uMenuID);
231 if (!LoadStringA (hInst, uMenuID, szText, 256))
234 SendMessageA (hwndStatus, SB_SETTEXTA,
235 255 | SBT_NOBORDERS, (LPARAM)szText);
236 SendMessageA (hwndStatus, SB_SIMPLE, TRUE, 0);
242 TRACE("WM_COMMAND wParam=0x%X lParam=0x%lX\n",
244 /* WM_COMMAND is not invalid since it is documented
245 * in the windows api reference. So don't output
246 * any FIXME for WM_COMMAND
248 WARN("We don't care about the WM_COMMAND\n");
252 FIXME("Invalid Message 0x%x!\n", uMsg);
258 /***********************************************************************
259 * ShowHideMenuCtl [COMCTL32.3]
261 * Shows or hides controls and updates the corresponding menu item.
264 * hwnd [I] handle to the client window.
265 * uFlags [I] menu command id.
266 * lpInfo [I] pointer to an array of integers. (See NOTES.)
273 * The official documentation is incomplete!
274 * This is the correct documentation:
277 * Handle to the window that contains the menu and controls.
280 * Identifier of the menu item to receive or loose a check mark.
283 * The array of integers contains pairs of values. BOTH values of
284 * the first pair must be the handles to the application's main menu.
285 * Each subsequent pair consists of a menu id and control id.
289 ShowHideMenuCtl (HWND hwnd, UINT uFlags, LPINT lpInfo)
293 TRACE("%x, %x, %p\n", hwnd, uFlags, lpInfo);
298 if (!(lpInfo[0]) || !(lpInfo[1]))
301 /* search for control */
302 lpMenuId = &lpInfo[2];
303 while (*lpMenuId != uFlags)
306 if (GetMenuState (lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) {
307 /* uncheck menu item */
308 CheckMenuItem (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_UNCHECKED);
312 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
316 /* check menu item */
317 CheckMenuItem (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_CHECKED);
321 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
329 /***********************************************************************
330 * GetEffectiveClientRect [COMCTL32.4]
333 * hwnd [I] handle to the client window.
334 * lpRect [O] pointer to the rectangle of the client window
335 * lpInfo [I] pointer to an array of integers (see NOTES)
341 * The official documentation is incomplete!
342 * This is the correct documentation:
345 * (will be written...)
349 GetEffectiveClientRect (HWND hwnd, LPRECT lpRect, LPINT lpInfo)
355 TRACE("(0x%08lx 0x%08lx 0x%08lx)\n",
356 (DWORD)hwnd, (DWORD)lpRect, (DWORD)lpInfo);
358 GetClientRect (hwnd, lpRect);
366 hwndCtrl = GetDlgItem (hwnd, *lpRun);
367 if (GetWindowLongA (hwndCtrl, GWL_STYLE) & WS_VISIBLE) {
368 TRACE("control id 0x%x\n", *lpRun);
369 GetWindowRect (hwndCtrl, &rcCtrl);
370 MapWindowPoints ((HWND)0, hwnd, (LPPOINT)&rcCtrl, 2);
371 SubtractRect (lpRect, lpRect, &rcCtrl);
378 /***********************************************************************
379 * DrawStatusText [COMCTL32.27]
380 * DrawStatusTextA [COMCTL32.5]
382 * Draws text with borders, like in a status bar.
385 * hdc [I] handle to the window's display context
386 * lprc [I] pointer to a rectangle
387 * text [I] pointer to the text
388 * style [I] drawing style
394 * The style variable can have one of the following values:
395 * (will be written ...)
399 DrawStatusTextA (HDC hdc, LPRECT lprc, LPCSTR text, UINT style)
402 UINT border = BDR_SUNKENOUTER;
404 if (style & SBT_POPOUT)
405 border = BDR_RAISEDOUTER;
406 else if (style & SBT_NOBORDERS)
409 DrawEdge (hdc, &r, border, BF_RECT|BF_ADJUST|BF_MIDDLE);
413 int oldbkmode = SetBkMode (hdc, TRANSPARENT);
415 DrawTextA (hdc, text, lstrlenA(text),
416 &r, DT_LEFT|DT_VCENTER|DT_SINGLELINE);
417 if (oldbkmode != TRANSPARENT)
418 SetBkMode(hdc, oldbkmode);
423 /***********************************************************************
424 * DrawStatusTextW [COMCTL32.28]
426 * Draws text with borders, like in a status bar.
429 * hdc [I] handle to the window's display context
430 * lprc [I] pointer to a rectangle
431 * text [I] pointer to the text
432 * style [I] drawing style
439 DrawStatusTextW (HDC hdc, LPRECT lprc, LPCWSTR text, UINT style)
441 LPSTR p = HEAP_strdupWtoA (GetProcessHeap (), 0, text);
442 DrawStatusTextA (hdc, lprc, p, style);
443 HeapFree (GetProcessHeap (), 0, p );
447 /***********************************************************************
448 * CreateStatusWindow [COMCTL32.21]
449 * CreateStatusWindowA [COMCTL32.6]
451 * Creates a status bar
454 * style [I] window style
455 * text [I] pointer to the window text
456 * parent [I] handle to the parent window
457 * wid [I] control id of the status bar
460 * Success: handle to the status window
465 CreateStatusWindowA (INT style, LPCSTR text, HWND parent, UINT wid)
467 return CreateWindowA(STATUSCLASSNAMEA, text, style,
468 CW_USEDEFAULT, CW_USEDEFAULT,
469 CW_USEDEFAULT, CW_USEDEFAULT,
474 /***********************************************************************
475 * CreateStatusWindowW [COMCTL32.22] Creates a status bar control
478 * style [I] window style
479 * text [I] pointer to the window text
480 * parent [I] handle to the parent window
481 * wid [I] control id of the status bar
484 * Success: handle to the status window
489 CreateStatusWindowW (INT style, LPCWSTR text, HWND parent, UINT wid)
491 return CreateWindowW(STATUSCLASSNAMEW, text, style,
492 CW_USEDEFAULT, CW_USEDEFAULT,
493 CW_USEDEFAULT, CW_USEDEFAULT,
498 /***********************************************************************
499 * CreateUpDownControl [COMCTL32.16] Creates an up-down control
502 * style [I] window styles
503 * x [I] horizontal position of the control
504 * y [I] vertical position of the control
505 * cx [I] with of the control
506 * cy [I] height of the control
507 * parent [I] handle to the parent window
508 * id [I] the control's identifier
509 * inst [I] handle to the application's module instance
510 * buddy [I] handle to the buddy window, can be NULL
511 * maxVal [I] upper limit of the control
512 * minVal [I] lower limit of the control
513 * curVal [I] current value of the control
516 * Success: handle to the updown control
521 CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
522 HWND parent, INT id, HINSTANCE inst,
523 HWND buddy, INT maxVal, INT minVal, INT curVal)
526 CreateWindowA (UPDOWN_CLASSA, 0, style, x, y, cx, cy,
527 parent, id, inst, 0);
529 SendMessageA (hUD, UDM_SETBUDDY, buddy, 0);
530 SendMessageA (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));
531 SendMessageA (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));
538 /***********************************************************************
539 * InitCommonControls [COMCTL32.17]
541 * Registers the common controls.
550 * This function is just a dummy.
551 * The Win95 controls are registered at the DLL's initialization.
552 * To register other controls InitCommonControlsEx() must be used.
556 InitCommonControls (void)
561 /***********************************************************************
562 * InitCommonControlsEx [COMCTL32.84]
564 * Registers the common controls.
567 * lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
574 * Only the additional common controls are registered by this function.
575 * The Win95 controls are registered at the DLL's initialization.
579 InitCommonControlsEx (LPINITCOMMONCONTROLSEX lpInitCtrls)
586 if (lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
589 TRACE("(0x%08lx)\n", lpInitCtrls->dwICC);
591 for (cCount = 0; cCount < 32; cCount++) {
592 dwMask = 1 << cCount;
593 if (!(lpInitCtrls->dwICC & dwMask))
596 switch (lpInitCtrls->dwICC & dwMask) {
597 /* dummy initialization */
598 case ICC_ANIMATE_CLASS:
599 case ICC_BAR_CLASSES:
600 case ICC_LISTVIEW_CLASSES:
601 case ICC_TREEVIEW_CLASSES:
602 case ICC_TAB_CLASSES:
603 case ICC_UPDOWN_CLASS:
604 case ICC_PROGRESS_CLASS:
605 case ICC_HOTKEY_CLASS:
608 /* advanced classes - not included in Win95 */
609 case ICC_DATE_CLASSES:
610 MONTHCAL_Register ();
611 DATETIME_Register ();
614 case ICC_USEREX_CLASSES:
618 case ICC_COOL_CLASSES:
622 case ICC_INTERNET_CLASSES:
623 IPADDRESS_Register ();
626 case ICC_PAGESCROLLER_CLASS:
630 case ICC_NATIVEFNTCTL_CLASS:
631 NATIVEFONT_Register ();
635 FIXME("Unknown class! dwICC=0x%lX\n", dwMask);
644 /***********************************************************************
645 * CreateToolbarEx [COMCTL32.23] Creates a tool bar window
663 * Success: handle to the tool bar control
668 CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
669 HINSTANCE hBMInst, UINT wBMID, LPCTBBUTTON lpButtons,
670 INT iNumButtons, INT dxButton, INT dyButton,
671 INT dxBitmap, INT dyBitmap, UINT uStructSize)
675 /* If not position is specified then put it at the top */
676 if ((style & CCS_BOTTOM) == 0) {
681 CreateWindowExA (0, TOOLBARCLASSNAMEA, "", style|WS_CHILD, 0, 0, 0, 0,
682 hwnd, (HMENU)wID, 0, NULL);
686 SendMessageA (hwndTB, TB_BUTTONSTRUCTSIZE,
687 (WPARAM)uStructSize, 0);
689 /* set bitmap and button size */
690 /*If CreateToolbarEx receives 0, windows sets default values*/
695 SendMessageA (hwndTB, TB_SETBITMAPSIZE, 0,
696 MAKELPARAM((WORD)dxBitmap, (WORD)dyBitmap));
702 SendMessageA (hwndTB, TB_SETBUTTONSIZE, 0,
703 MAKELPARAM((WORD)dxButton, (WORD)dyButton));
709 tbab.hInst = hBMInst;
712 SendMessageA (hwndTB, TB_ADDBITMAP,
713 (WPARAM)nBitmaps, (LPARAM)&tbab);
717 SendMessageA (hwndTB, TB_ADDBUTTONSA,
718 (WPARAM)iNumButtons, (LPARAM)lpButtons);
725 /***********************************************************************
726 * CreateMappedBitmap [COMCTL32.8]
736 * Success: handle to the new bitmap
741 CreateMappedBitmap (HINSTANCE hInstance, INT idBitmap, UINT wFlags,
742 LPCOLORMAP lpColorMap, INT iNumMaps)
746 LPBITMAPINFOHEADER lpBitmap, lpBitmapInfo;
747 UINT nSize, nColorTableSize;
748 RGBQUAD *pColorTable;
749 INT iColor, i, iMaps, nWidth, nHeight;
752 LPCOLORMAP sysColorMap;
754 COLORMAP internalColorMap[4] =
755 {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
757 /* initialize pointer to colortable and default color table */
760 sysColorMap = lpColorMap;
763 internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT);
764 internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW);
765 internalColorMap[2].to = GetSysColor (COLOR_BTNFACE);
766 internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT);
768 sysColorMap = (LPCOLORMAP)internalColorMap;
771 hRsrc = FindResourceA (hInstance, (LPSTR)idBitmap, RT_BITMAPA);
774 hglb = LoadResource (hInstance, hRsrc);
777 lpBitmap = (LPBITMAPINFOHEADER)LockResource (hglb);
778 if (lpBitmap == NULL)
781 nColorTableSize = (1 << lpBitmap->biBitCount);
782 nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
783 lpBitmapInfo = (LPBITMAPINFOHEADER)GlobalAlloc (GMEM_FIXED, nSize);
784 if (lpBitmapInfo == NULL)
786 RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);
788 pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo)+(UINT)lpBitmapInfo->biSize);
790 for (iColor = 0; iColor < nColorTableSize; iColor++) {
791 for (i = 0; i < iMaps; i++) {
792 cRef = RGB(pColorTable[iColor].rgbRed,
793 pColorTable[iColor].rgbGreen,
794 pColorTable[iColor].rgbBlue);
795 if ( cRef == sysColorMap[i].from) {
797 if (wFlags & CBS_MASKED) {
798 if (sysColorMap[i].to != COLOR_BTNTEXT)
799 pColorTable[iColor] = RGB(255, 255, 255);
803 pColorTable[iColor].rgbBlue = GetBValue(sysColorMap[i].to);
804 pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);
805 pColorTable[iColor].rgbRed = GetRValue(sysColorMap[i].to);
810 nWidth = (INT)lpBitmapInfo->biWidth;
811 nHeight = (INT)lpBitmapInfo->biHeight;
812 hdcScreen = GetDC ((HWND)0);
813 hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
815 HDC hdcDst = CreateCompatibleDC (hdcScreen);
816 HBITMAP hbmOld = SelectObject (hdcDst, hbm);
817 LPBYTE lpBits = (LPBYTE)(lpBitmap + 1);
818 lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
819 StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
820 lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
822 SelectObject (hdcDst, hbmOld);
825 ReleaseDC ((HWND)0, hdcScreen);
826 GlobalFree ((HGLOBAL)lpBitmapInfo);
833 /***********************************************************************
834 * CreateToolbar [COMCTL32.7] Creates a tool bar control
847 * Success: handle to the tool bar control
851 * Do not use this functions anymore. Use CreateToolbarEx instead.
855 CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
856 HINSTANCE hBMInst, UINT wBMID,
857 LPCOLDTBBUTTON lpButtons,INT iNumButtons)
859 return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
860 hBMInst, wBMID, (LPCTBBUTTON)lpButtons,
861 iNumButtons, 0, 0, 0, 0, sizeof (OLDTBBUTTON));
865 /***********************************************************************
866 * DllGetVersion [COMCTL32.25]
868 * Retrieves version information of the 'COMCTL32.DLL'
871 * pdvi [O] pointer to version information structure.
875 * Failure: E_INVALIDARG
878 * Returns version of a comctl32.dll from IE4.01 SP1.
882 COMCTL32_DllGetVersion (DLLVERSIONINFO *pdvi)
884 if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
885 WARN("wrong DLLVERSIONINFO size from app\n");
889 pdvi->dwMajorVersion = COMCTL32_VERSION;
890 pdvi->dwMinorVersion = COMCTL32_VERSION_MINOR;
891 pdvi->dwBuildNumber = 2919;
892 pdvi->dwPlatformID = 6304;
894 TRACE("%lu.%lu.%lu.%lu\n",
895 pdvi->dwMajorVersion, pdvi->dwMinorVersion,
896 pdvi->dwBuildNumber, pdvi->dwPlatformID);
901 /***********************************************************************
902 * DllInstall (COMCTL32.26)
904 HRESULT WINAPI COMCTL32_DllInstall(BOOL bInstall, LPCWSTR cmdline)
906 FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
907 debugstr_w(cmdline));
913 typedef struct __TRACKINGLIST {
915 POINT pos; /* center of hover rectangle */
916 INT iHoverTime; /* elapsed time the cursor has been inside of the hover rect */
919 static _TRACKINGLIST TrackingList[10];
920 static int iTrackMax = 0;
921 static UINT_PTR timer;
922 static const INT iTimerInterval = 50; /* msec for timer interval */
924 /* FIXME: need to implement WM_NCMOUSELEAVE and WM_NCMOUSEHOVER for */
925 /* TrackMouseEventProc and _TrackMouseEvent */
926 static void CALLBACK TrackMouseEventProc(HWND hwndUnused, UINT uMsg, UINT_PTR idEvent,
932 INT hoverwidth = 0, hoverheight = 0;
935 hwnd = WindowFromPoint(pos);
937 SystemParametersInfoA(SPI_GETMOUSEHOVERWIDTH, 0, &hoverwidth, 0);
938 SystemParametersInfoA(SPI_GETMOUSEHOVERHEIGHT, 0, &hoverheight, 0);
940 /* loop through tracking events we are processing */
941 while (i < iTrackMax) {
942 /* see if this tracking event is looking for TME_LEAVE and that the */
943 /* mouse has left the window */
944 if ((TrackingList[i].tme.dwFlags & TME_LEAVE) &&
945 (TrackingList[i].tme.hwndTrack != hwnd)) {
946 PostMessageA(TrackingList[i].tme.hwndTrack, WM_MOUSELEAVE, 0, 0);
948 /* remove the TME_LEAVE flag */
949 TrackingList[i].tme.dwFlags ^= TME_LEAVE;
952 /* see if we are tracking hovering for this hwnd */
953 if(TrackingList[i].tme.dwFlags & TME_HOVER) {
954 /* add the timer interval to the hovering time */
955 TrackingList[i].iHoverTime+=iTimerInterval;
957 /* has the cursor moved outside the rectangle centered around pos? */
958 if((abs(pos.x - TrackingList[i].pos.x) > (hoverwidth / 2.0))
959 || (abs(pos.y - TrackingList[i].pos.y) > (hoverheight / 2.0)))
961 /* record this new position as the current position and reset */
962 /* the iHoverTime variable to 0 */
963 TrackingList[i].pos = pos;
964 TrackingList[i].iHoverTime = 0;
967 /* has the mouse hovered long enough? */
968 if(TrackingList[i].iHoverTime <= TrackingList[i].tme.dwHoverTime)
970 PostMessageA(TrackingList[i].tme.hwndTrack, WM_MOUSEHOVER, 0, 0);
972 /* stop tracking mouse hover */
973 TrackingList[i].tme.dwFlags ^= TME_HOVER;
977 /* see if we are still tracking TME_HOVER or TME_LEAVE for this entry */
978 if((TrackingList[i].tme.dwFlags & TME_HOVER) ||
979 (TrackingList[i].tme.dwFlags & TME_LEAVE)) {
981 } else { /* remove this entry from the tracking list */
982 TrackingList[i] = TrackingList[--iTrackMax];
986 /* stop the timer if the tracking list is empty */
993 /***********************************************************************
994 * _TrackMouseEvent [COMCTL32.91]
996 * Requests notification of mouse events
998 * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
999 * to the hwnd specified in the ptme structure. After the event message
1000 * is posted to the hwnd, the entry in the queue is removed.
1002 * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
1003 * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
1004 * immediately and the TME_LEAVE flag being ignored.
1007 * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
1016 _TrackMouseEvent (TRACKMOUSEEVENT *ptme)
1020 BOOL cancel = 0, hover = 0, leave = 0, query = 0;
1027 TRACE("%lx, %lx, %x, %lx\n", ptme->cbSize, ptme->dwFlags, ptme->hwndTrack, ptme->dwHoverTime);
1029 if (ptme->cbSize != sizeof(TRACKMOUSEEVENT)) {
1030 WARN("wrong TRACKMOUSEEVENT size from app\n");
1031 SetLastError(ERROR_INVALID_PARAMETER); /* FIXME not sure if this is correct */
1035 flags = ptme->dwFlags;
1037 /* if HOVER_DEFAULT was specified replace this with the systems current value */
1038 if(ptme->dwHoverTime == HOVER_DEFAULT)
1039 SystemParametersInfoA(SPI_GETMOUSEHOVERTIME, 0, &(ptme->dwHoverTime), 0);
1042 hwnd = WindowFromPoint(pos);
1044 if ( flags & TME_CANCEL ) {
1045 flags &= ~ TME_CANCEL;
1049 if ( flags & TME_HOVER ) {
1050 flags &= ~ TME_HOVER;
1054 if ( flags & TME_LEAVE ) {
1055 flags &= ~ TME_LEAVE;
1059 /* fill the TRACKMOUSEEVENT struct with the current tracking for the given hwnd */
1060 if ( flags & TME_QUERY ) {
1061 flags &= ~ TME_QUERY;
1065 /* Find the tracking list entry with the matching hwnd */
1066 while((i < iTrackMax) && (TrackingList[i].tme.hwndTrack != ptme->hwndTrack)) {
1070 /* hwnd found, fill in the ptme struct */
1072 *ptme = TrackingList[i].tme;
1076 return TRUE; /* return here, TME_QUERY is retrieving information */
1080 FIXME("Unknown flag(s) %08lx\n", flags );
1083 /* find a matching hwnd if one exists */
1086 while((i < iTrackMax) && (TrackingList[i].tme.hwndTrack != ptme->hwndTrack)) {
1091 TrackingList[i].tme.dwFlags &= ~(ptme->dwFlags & ~TME_CANCEL);
1093 /* if we aren't tracking on hover or leave remove this entry */
1094 if(!((TrackingList[i].tme.dwFlags & TME_HOVER) ||
1095 (TrackingList[i].tme.dwFlags & TME_LEAVE)))
1097 TrackingList[i] = TrackingList[--iTrackMax];
1099 if(iTrackMax == 0) {
1100 KillTimer(0, timer);
1106 /* see if hwndTrack isn't the current window */
1107 if(ptme->hwndTrack != hwnd) {
1109 PostMessageA(ptme->hwndTrack, WM_MOUSELEAVE, 0, 0);
1112 /* See if this hwnd is already being tracked and update the tracking flags */
1113 for(i = 0; i < iTrackMax; i++) {
1114 if(TrackingList[i].tme.hwndTrack == ptme->hwndTrack) {
1116 TrackingList[i].tme.dwFlags |= TME_HOVER;
1117 TrackingList[i].tme.dwHoverTime = ptme->dwHoverTime;
1121 TrackingList[i].tme.dwFlags |= TME_LEAVE;
1123 /* reset iHoverTime as per winapi specs */
1124 TrackingList[i].iHoverTime = 0;
1130 /* if the tracking list is full return FALSE */
1131 if (iTrackMax == sizeof (TrackingList) / sizeof(*TrackingList)) {
1135 /* Adding new mouse event to the tracking list */
1136 TrackingList[iTrackMax].tme = *ptme;
1138 /* Initialize HoverInfo variables even if not hover tracking */
1139 TrackingList[iTrackMax].iHoverTime = 0;
1140 TrackingList[iTrackMax].pos = pos;
1145 timer = SetTimer(0, 0, iTimerInterval, TrackMouseEventProc);
1154 /*************************************************************************
1155 * GetMUILanguage [COMCTL32.39]
1157 * FIXME: What's this supposed to do? Apparently some i18n thing.
1160 LANGID WINAPI GetMUILanguage (VOID)
1162 return COMCTL32_uiLang;
1166 /*************************************************************************
1167 * InitMUILanguage [COMCTL32.85]
1169 * FIXME: What's this supposed to do? Apparently some i18n thing.
1173 VOID WINAPI InitMUILanguage (LANGID uiLang)
1175 COMCTL32_uiLang = uiLang;
1179 /***********************************************************************
1180 * COMCTL32_CreateToolTip [NOT AN API]
1182 * Creates a tooltip for the control specified in hwnd and does all
1183 * necessary setup and notifications.
1186 * hwndOwner [I] Handle to the window that will own the tool tip.
1189 * Success: Handle of tool tip window.
1193 COMCTL32_CreateToolTip(HWND hwndOwner)
1197 hwndToolTip = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
1198 CW_USEDEFAULT, CW_USEDEFAULT,
1199 CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner,
1202 /* Send NM_TOOLTIPSCREATED notification */
1205 NMTOOLTIPSCREATED nmttc;
1206 /* true owner can be different if hwndOwner is a child window */
1207 HWND hwndTrueOwner = GetWindow(hwndToolTip, GW_OWNER);
1208 nmttc.hdr.hwndFrom = hwndTrueOwner;
1209 nmttc.hdr.idFrom = GetWindowLongA(hwndTrueOwner, GWL_ID);
1210 nmttc.hdr.code = NM_TOOLTIPSCREATED;
1211 nmttc.hwndToolTips = hwndToolTip;
1213 SendMessageA(GetParent(hwndTrueOwner), WM_NOTIFY,
1214 (WPARAM)GetWindowLongA(hwndTrueOwner, GWL_ID),