2 * Common controls functions
4 * Copyright 1997 Dimitrie O. Paun
5 * Copyright 1998,2000 Eric Kohl
14 #include "debugtools.h"
19 DEFAULT_DEBUG_CHANNEL(commctrl);
21 extern void ANIMATE_Register(void);
22 extern void ANIMATE_Unregister(void);
23 extern void COMBOEX_Register(void);
24 extern void COMBOEX_Unregister(void);
25 extern void DATETIME_Register(void);
26 extern void DATETIME_Unregister(void);
27 extern void FLATSB_Register(void);
28 extern void FLATSB_Unregister(void);
29 extern void HEADER_Register(void);
30 extern void HEADER_Unregister(void);
31 extern void HOTKEY_Register(void);
32 extern void HOTKEY_Unregister(void);
33 extern void IPADDRESS_Register(void);
34 extern void IPADDRESS_Unregister(void);
35 extern void LISTVIEW_Register(void);
36 extern void LISTVIEW_Unregister(void);
37 extern void MONTHCAL_Register(void);
38 extern void MONTHCAL_Unregister(void);
39 extern void NATIVEFONT_Register(void);
40 extern void NATIVEFONT_Unregister(void);
41 extern void PAGER_Register(void);
42 extern void PAGER_Unregister(void);
43 extern void PROGRESS_Register(void);
44 extern void PROGRESS_Unregister(void);
45 extern void REBAR_Register(void);
46 extern void REBAR_Unregister(void);
47 extern void STATUS_Register(void);
48 extern void STATUS_Unregister(void);
49 extern void TAB_Register(void);
50 extern void TAB_Unregister(void);
51 extern void TOOLBAR_Register(void);
52 extern void TOOLBAR_Unregister(void);
53 extern void TOOLTIPS_Register(void);
54 extern void TOOLTIPS_Unregister(void);
55 extern void TRACKBAR_Register(void);
56 extern void TRACKBAR_Unregister(void);
57 extern void TREEVIEW_Register(void);
58 extern void TREEVIEW_Unregister(void);
59 extern void UPDOWN_Register(void);
60 extern void UPDOWN_Unregister(void);
63 HANDLE COMCTL32_hHeap = (HANDLE)NULL;
64 LPSTR COMCTL32_aSubclass = (LPSTR)NULL;
65 HMODULE COMCTL32_hModule = 0;
66 LANGID COMCTL32_uiLang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
67 HBRUSH COMCTL32_hPattern55AABrush = (HANDLE)NULL;
69 static HBITMAP COMCTL32_hPattern55AABitmap = (HANDLE)NULL;
71 static const WORD wPattern55AA[] =
73 0x5555, 0xaaaa, 0x5555, 0xaaaa,
74 0x5555, 0xaaaa, 0x5555, 0xaaaa
78 /***********************************************************************
79 * COMCTL32_LibMain [Internal] Initializes the internal 'COMCTL32.DLL'.
82 * hinstDLL [I] handle to the 'dlls' instance
84 * lpvReserved [I] reserverd, must be NULL
92 COMCTL32_LibMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
94 TRACE("%x,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
97 case DLL_PROCESS_ATTACH:
98 COMCTL32_hModule = (HMODULE)hinstDLL;
100 /* create private heap */
101 COMCTL32_hHeap = HeapCreate (0, 0x10000, 0);
102 TRACE("Heap created: 0x%x\n", COMCTL32_hHeap);
104 /* add global subclassing atom (used by 'tooltip' and 'updown') */
105 COMCTL32_aSubclass = (LPSTR)(DWORD)GlobalAddAtomA ("CC32SubclassInfo");
106 TRACE("Subclassing atom added: %p\n", COMCTL32_aSubclass);
108 /* create local pattern brush */
109 COMCTL32_hPattern55AABitmap = CreateBitmap (8, 8, 1, 1, wPattern55AA);
110 COMCTL32_hPattern55AABrush = CreatePatternBrush (COMCTL32_hPattern55AABitmap);
112 /* register all Win95 common control classes */
117 LISTVIEW_Register ();
118 PROGRESS_Register ();
122 TOOLTIPS_Register ();
123 TRACKBAR_Register ();
124 TREEVIEW_Register ();
128 case DLL_PROCESS_DETACH:
129 /* unregister all common control classes */
130 ANIMATE_Unregister ();
131 COMBOEX_Unregister ();
132 DATETIME_Unregister ();
133 FLATSB_Unregister ();
134 HEADER_Unregister ();
135 HOTKEY_Unregister ();
136 IPADDRESS_Unregister ();
137 LISTVIEW_Unregister ();
138 MONTHCAL_Unregister ();
139 NATIVEFONT_Unregister ();
141 PROGRESS_Unregister ();
143 STATUS_Unregister ();
145 TOOLBAR_Unregister ();
146 TOOLTIPS_Unregister ();
147 TRACKBAR_Unregister ();
148 TREEVIEW_Unregister ();
149 UPDOWN_Unregister ();
151 /* delete local pattern brush */
152 DeleteObject (COMCTL32_hPattern55AABrush);
153 COMCTL32_hPattern55AABrush = (HANDLE)NULL;
154 DeleteObject (COMCTL32_hPattern55AABitmap);
155 COMCTL32_hPattern55AABitmap = (HANDLE)NULL;
157 /* delete global subclassing atom */
158 GlobalDeleteAtom (LOWORD(COMCTL32_aSubclass));
159 TRACE("Subclassing atom deleted: %p\n", COMCTL32_aSubclass);
160 COMCTL32_aSubclass = (LPSTR)NULL;
162 /* destroy private heap */
163 HeapDestroy (COMCTL32_hHeap);
164 TRACE("Heap destroyed: 0x%x\n", COMCTL32_hHeap);
165 COMCTL32_hHeap = (HANDLE)NULL;
173 /***********************************************************************
174 * MenuHelp [COMCTL32.2]
177 * uMsg [I] message (WM_MENUSELECT) (see NOTES)
178 * wParam [I] wParam of the message uMsg
179 * lParam [I] lParam of the message uMsg
180 * hMainMenu [I] handle to the application's main menu
181 * hInst [I] handle to the module that contains string resources
182 * hwndStatus [I] handle to the status bar window
183 * lpwIDs [I] pointer to an array of integers (see NOTES)
189 * The official documentation is incomplete!
190 * This is the correct documentation:
193 * MenuHelp() does NOT handle WM_COMMAND messages! It only handles
194 * WM_MENUSELECT messages.
197 * (will be written ...)
201 MenuHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu,
202 HINSTANCE hInst, HWND hwndStatus, LPUINT lpwIDs)
206 if (!IsWindow (hwndStatus))
211 TRACE("WM_MENUSELECT wParam=0x%X lParam=0x%lX\n",
214 if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {
215 /* menu was closed */
216 TRACE("menu was closed!\n");
217 SendMessageA (hwndStatus, SB_SIMPLE, FALSE, 0);
220 /* menu item was selected */
221 if (HIWORD(wParam) & MF_POPUP)
222 uMenuID = (UINT)*(lpwIDs+1);
224 uMenuID = (UINT)LOWORD(wParam);
225 TRACE("uMenuID = %u\n", uMenuID);
230 if (!LoadStringA (hInst, uMenuID, szText, 256))
233 SendMessageA (hwndStatus, SB_SETTEXTA,
234 255 | SBT_NOBORDERS, (LPARAM)szText);
235 SendMessageA (hwndStatus, SB_SIMPLE, TRUE, 0);
241 TRACE("WM_COMMAND wParam=0x%X lParam=0x%lX\n",
243 /* WM_COMMAND is not invalid since it is documented
244 * in the windows api reference. So don't output
245 * any FIXME for WM_COMMAND
247 WARN("We don't care about the WM_COMMAND\n");
251 FIXME("Invalid Message 0x%x!\n", uMsg);
257 /***********************************************************************
258 * ShowHideMenuCtl [COMCTL32.3]
260 * Shows or hides controls and updates the corresponding menu item.
263 * hwnd [I] handle to the client window.
264 * uFlags [I] menu command id.
265 * lpInfo [I] pointer to an array of integers. (See NOTES.)
272 * The official documentation is incomplete!
273 * This is the correct documentation:
276 * Handle to the window that contains the menu and controls.
279 * Identifier of the menu item to receive or loose a check mark.
282 * The array of integers contains pairs of values. BOTH values of
283 * the first pair must be the handles to the application's main menu.
284 * Each subsequent pair consists of a menu id and control id.
288 ShowHideMenuCtl (HWND hwnd, UINT uFlags, LPINT lpInfo)
292 TRACE("%x, %x, %p\n", hwnd, uFlags, lpInfo);
297 if (!(lpInfo[0]) || !(lpInfo[1]))
300 /* search for control */
301 lpMenuId = &lpInfo[2];
302 while (*lpMenuId != uFlags)
305 if (GetMenuState (lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) {
306 /* uncheck menu item */
307 CheckMenuItem (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_UNCHECKED);
311 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
315 /* check menu item */
316 CheckMenuItem (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_CHECKED);
320 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
328 /***********************************************************************
329 * GetEffectiveClientRect [COMCTL32.4]
332 * hwnd [I] handle to the client window.
333 * lpRect [O] pointer to the rectangle of the client window
334 * lpInfo [I] pointer to an array of integers (see NOTES)
340 * The official documentation is incomplete!
341 * This is the correct documentation:
344 * (will be written...)
348 GetEffectiveClientRect (HWND hwnd, LPRECT lpRect, LPINT lpInfo)
354 TRACE("(0x%08lx 0x%08lx 0x%08lx)\n",
355 (DWORD)hwnd, (DWORD)lpRect, (DWORD)lpInfo);
357 GetClientRect (hwnd, lpRect);
365 hwndCtrl = GetDlgItem (hwnd, *lpRun);
366 if (GetWindowLongA (hwndCtrl, GWL_STYLE) & WS_VISIBLE) {
367 TRACE("control id 0x%x\n", *lpRun);
368 GetWindowRect (hwndCtrl, &rcCtrl);
369 MapWindowPoints ((HWND)0, hwnd, (LPPOINT)&rcCtrl, 2);
370 SubtractRect (lpRect, lpRect, &rcCtrl);
377 /***********************************************************************
378 * DrawStatusText [COMCTL32.27]
379 * DrawStatusTextA [COMCTL32.5]
381 * Draws text with borders, like in a status bar.
384 * hdc [I] handle to the window's display context
385 * lprc [I] pointer to a rectangle
386 * text [I] pointer to the text
387 * style [I] drawing style
393 * The style variable can have one of the following values:
394 * (will be written ...)
398 DrawStatusTextA (HDC hdc, LPRECT lprc, LPCSTR text, UINT style)
401 UINT border = BDR_SUNKENOUTER;
403 if (style & SBT_POPOUT)
404 border = BDR_RAISEDOUTER;
405 else if (style & SBT_NOBORDERS)
408 DrawEdge (hdc, &r, border, BF_RECT|BF_ADJUST|BF_MIDDLE);
412 int oldbkmode = SetBkMode (hdc, TRANSPARENT);
414 DrawTextA (hdc, text, lstrlenA(text),
415 &r, DT_LEFT|DT_VCENTER|DT_SINGLELINE);
416 if (oldbkmode != TRANSPARENT)
417 SetBkMode(hdc, oldbkmode);
422 /***********************************************************************
423 * DrawStatusTextW [COMCTL32.28]
425 * Draws text with borders, like in a status bar.
428 * hdc [I] handle to the window's display context
429 * lprc [I] pointer to a rectangle
430 * text [I] pointer to the text
431 * style [I] drawing style
438 DrawStatusTextW (HDC hdc, LPRECT lprc, LPCWSTR text, UINT style)
440 LPSTR p = HEAP_strdupWtoA (GetProcessHeap (), 0, text);
441 DrawStatusTextA (hdc, lprc, p, style);
442 HeapFree (GetProcessHeap (), 0, p );
446 /***********************************************************************
447 * CreateStatusWindow [COMCTL32.21]
448 * CreateStatusWindowA [COMCTL32.6]
450 * Creates a status bar
453 * style [I] window style
454 * text [I] pointer to the window text
455 * parent [I] handle to the parent window
456 * wid [I] control id of the status bar
459 * Success: handle to the status window
464 CreateStatusWindowA (INT style, LPCSTR text, HWND parent, UINT wid)
466 return CreateWindowA(STATUSCLASSNAMEA, text, style,
467 CW_USEDEFAULT, CW_USEDEFAULT,
468 CW_USEDEFAULT, CW_USEDEFAULT,
473 /***********************************************************************
474 * CreateStatusWindowW [COMCTL32.22] Creates a status bar control
477 * style [I] window style
478 * text [I] pointer to the window text
479 * parent [I] handle to the parent window
480 * wid [I] control id of the status bar
483 * Success: handle to the status window
488 CreateStatusWindowW (INT style, LPCWSTR text, HWND parent, UINT wid)
490 return CreateWindowW(STATUSCLASSNAMEW, text, style,
491 CW_USEDEFAULT, CW_USEDEFAULT,
492 CW_USEDEFAULT, CW_USEDEFAULT,
497 /***********************************************************************
498 * CreateUpDownControl [COMCTL32.16] Creates an up-down control
501 * style [I] window styles
502 * x [I] horizontal position of the control
503 * y [I] vertical position of the control
504 * cx [I] with of the control
505 * cy [I] height of the control
506 * parent [I] handle to the parent window
507 * id [I] the control's identifier
508 * inst [I] handle to the application's module instance
509 * buddy [I] handle to the buddy window, can be NULL
510 * maxVal [I] upper limit of the control
511 * minVal [I] lower limit of the control
512 * curVal [I] current value of the control
515 * Success: handle to the updown control
520 CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
521 HWND parent, INT id, HINSTANCE inst,
522 HWND buddy, INT maxVal, INT minVal, INT curVal)
525 CreateWindowA (UPDOWN_CLASSA, 0, style, x, y, cx, cy,
526 parent, id, inst, 0);
528 SendMessageA (hUD, UDM_SETBUDDY, buddy, 0);
529 SendMessageA (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));
530 SendMessageA (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));
537 /***********************************************************************
538 * InitCommonControls [COMCTL32.17]
540 * Registers the common controls.
549 * This function is just a dummy.
550 * The Win95 controls are registered at the DLL's initialization.
551 * To register other controls InitCommonControlsEx() must be used.
555 InitCommonControls (void)
560 /***********************************************************************
561 * InitCommonControlsEx [COMCTL32.84]
563 * Registers the common controls.
566 * lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
573 * Only the additional common controls are registered by this function.
574 * The Win95 controls are registered at the DLL's initialization.
578 InitCommonControlsEx (LPINITCOMMONCONTROLSEX lpInitCtrls)
585 if (lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
588 TRACE("(0x%08lx)\n", lpInitCtrls->dwICC);
590 for (cCount = 0; cCount < 32; cCount++) {
591 dwMask = 1 << cCount;
592 if (!(lpInitCtrls->dwICC & dwMask))
595 switch (lpInitCtrls->dwICC & dwMask) {
596 /* dummy initialization */
597 case ICC_ANIMATE_CLASS:
598 case ICC_BAR_CLASSES:
599 case ICC_LISTVIEW_CLASSES:
600 case ICC_TREEVIEW_CLASSES:
601 case ICC_TAB_CLASSES:
602 case ICC_UPDOWN_CLASS:
603 case ICC_PROGRESS_CLASS:
604 case ICC_HOTKEY_CLASS:
607 /* advanced classes - not included in Win95 */
608 case ICC_DATE_CLASSES:
609 MONTHCAL_Register ();
610 DATETIME_Register ();
613 case ICC_USEREX_CLASSES:
617 case ICC_COOL_CLASSES:
621 case ICC_INTERNET_CLASSES:
622 IPADDRESS_Register ();
625 case ICC_PAGESCROLLER_CLASS:
629 case ICC_NATIVEFNTCTL_CLASS:
630 NATIVEFONT_Register ();
634 FIXME("Unknown class! dwICC=0x%lX\n", dwMask);
643 /***********************************************************************
644 * CreateToolbarEx [COMCTL32.23] Creates a tool bar window
662 * Success: handle to the tool bar control
667 CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
668 HINSTANCE hBMInst, UINT wBMID, LPCTBBUTTON lpButtons,
669 INT iNumButtons, INT dxButton, INT dyButton,
670 INT dxBitmap, INT dyBitmap, UINT uStructSize)
674 /* If not position is specified then put it at the top */
675 if ((style & CCS_BOTTOM) == 0) {
680 CreateWindowExA (0, TOOLBARCLASSNAMEA, "", style|WS_CHILD, 0, 0, 0, 0,
681 hwnd, (HMENU)wID, 0, NULL);
685 SendMessageA (hwndTB, TB_BUTTONSTRUCTSIZE,
686 (WPARAM)uStructSize, 0);
688 /* set bitmap and button size */
689 /*If CreateToolbarEx receives 0, windows sets default values*/
694 SendMessageA (hwndTB, TB_SETBITMAPSIZE, 0,
695 MAKELPARAM((WORD)dxBitmap, (WORD)dyBitmap));
701 SendMessageA (hwndTB, TB_SETBUTTONSIZE, 0,
702 MAKELPARAM((WORD)dxButton, (WORD)dyButton));
708 tbab.hInst = hBMInst;
711 SendMessageA (hwndTB, TB_ADDBITMAP,
712 (WPARAM)nBitmaps, (LPARAM)&tbab);
716 SendMessageA (hwndTB, TB_ADDBUTTONSA,
717 (WPARAM)iNumButtons, (LPARAM)lpButtons);
724 /***********************************************************************
725 * CreateMappedBitmap [COMCTL32.8]
735 * Success: handle to the new bitmap
740 CreateMappedBitmap (HINSTANCE hInstance, INT idBitmap, UINT wFlags,
741 LPCOLORMAP lpColorMap, INT iNumMaps)
745 LPBITMAPINFOHEADER lpBitmap, lpBitmapInfo;
746 UINT nSize, nColorTableSize;
747 RGBQUAD *pColorTable;
748 INT iColor, i, iMaps, nWidth, nHeight;
751 LPCOLORMAP sysColorMap;
753 COLORMAP internalColorMap[4] =
754 {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
756 /* initialize pointer to colortable and default color table */
759 sysColorMap = lpColorMap;
762 internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT);
763 internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW);
764 internalColorMap[2].to = GetSysColor (COLOR_BTNFACE);
765 internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT);
767 sysColorMap = (LPCOLORMAP)internalColorMap;
770 hRsrc = FindResourceA (hInstance, (LPSTR)idBitmap, RT_BITMAPA);
773 hglb = LoadResource (hInstance, hRsrc);
776 lpBitmap = (LPBITMAPINFOHEADER)LockResource (hglb);
777 if (lpBitmap == NULL)
780 nColorTableSize = (1 << lpBitmap->biBitCount);
781 nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
782 lpBitmapInfo = (LPBITMAPINFOHEADER)GlobalAlloc (GMEM_FIXED, nSize);
783 if (lpBitmapInfo == NULL)
785 RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);
787 pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo)+(UINT)lpBitmapInfo->biSize);
789 for (iColor = 0; iColor < nColorTableSize; iColor++) {
790 for (i = 0; i < iMaps; i++) {
791 cRef = RGB(pColorTable[iColor].rgbRed,
792 pColorTable[iColor].rgbGreen,
793 pColorTable[iColor].rgbBlue);
794 if ( cRef == sysColorMap[i].from) {
796 if (wFlags & CBS_MASKED) {
797 if (sysColorMap[i].to != COLOR_BTNTEXT)
798 pColorTable[iColor] = RGB(255, 255, 255);
802 pColorTable[iColor].rgbBlue = GetBValue(sysColorMap[i].to);
803 pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);
804 pColorTable[iColor].rgbRed = GetRValue(sysColorMap[i].to);
809 nWidth = (INT)lpBitmapInfo->biWidth;
810 nHeight = (INT)lpBitmapInfo->biHeight;
811 hdcScreen = GetDC ((HWND)0);
812 hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
814 HDC hdcDst = CreateCompatibleDC (hdcScreen);
815 HBITMAP hbmOld = SelectObject (hdcDst, hbm);
816 LPBYTE lpBits = (LPBYTE)(lpBitmap + 1);
817 lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
818 StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
819 lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
821 SelectObject (hdcDst, hbmOld);
824 ReleaseDC ((HWND)0, hdcScreen);
825 GlobalFree ((HGLOBAL)lpBitmapInfo);
832 /***********************************************************************
833 * CreateToolbar [COMCTL32.7] Creates a tool bar control
846 * Success: handle to the tool bar control
850 * Do not use this functions anymore. Use CreateToolbarEx instead.
854 CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
855 HINSTANCE hBMInst, UINT wBMID,
856 LPCOLDTBBUTTON lpButtons,INT iNumButtons)
858 return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
859 hBMInst, wBMID, (LPCTBBUTTON)lpButtons,
860 iNumButtons, 0, 0, 0, 0, sizeof (OLDTBBUTTON));
864 /***********************************************************************
865 * DllGetVersion [COMCTL32.25]
867 * Retrieves version information of the 'COMCTL32.DLL'
870 * pdvi [O] pointer to version information structure.
874 * Failure: E_INVALIDARG
877 * Returns version of a comctl32.dll from IE4.01 SP1.
881 COMCTL32_DllGetVersion (DLLVERSIONINFO *pdvi)
883 if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
884 WARN("wrong DLLVERSIONINFO size from app\n");
888 pdvi->dwMajorVersion = COMCTL32_VERSION;
889 pdvi->dwMinorVersion = COMCTL32_VERSION_MINOR;
890 pdvi->dwBuildNumber = 2919;
891 pdvi->dwPlatformID = 6304;
893 TRACE("%lu.%lu.%lu.%lu\n",
894 pdvi->dwMajorVersion, pdvi->dwMinorVersion,
895 pdvi->dwBuildNumber, pdvi->dwPlatformID);
900 /***********************************************************************
901 * DllInstall (COMCTL32.26)
903 HRESULT WINAPI COMCTL32_DllInstall(BOOL bInstall, LPCWSTR cmdline)
905 FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
906 debugstr_w(cmdline));
912 typedef struct __TRACKINGLIST {
914 POINT pos; /* center of hover rectangle */
915 INT iHoverTime; /* elapsed time the cursor has been inside of the hover rect */
918 static _TRACKINGLIST TrackingList[10];
919 static int iTrackMax = 0;
920 static UINT_PTR timer;
921 static const INT iTimerInterval = 50; /* msec for timer interval */
923 /* FIXME: need to implement WM_NCMOUSELEAVE and WM_NCMOUSEHOVER for */
924 /* TrackMouseEventProc and _TrackMouseEvent */
925 static void CALLBACK TrackMouseEventProc(HWND hwndUnused, UINT uMsg, UINT_PTR idEvent,
931 INT hoverwidth = 0, hoverheight = 0;
934 hwnd = WindowFromPoint(pos);
936 SystemParametersInfoA(SPI_GETMOUSEHOVERWIDTH, 0, &hoverwidth, 0);
937 SystemParametersInfoA(SPI_GETMOUSEHOVERHEIGHT, 0, &hoverheight, 0);
939 /* loop through tracking events we are processing */
940 while (i < iTrackMax) {
941 /* see if this tracking event is looking for TME_LEAVE and that the */
942 /* mouse has left the window */
943 if ((TrackingList[i].tme.dwFlags & TME_LEAVE) &&
944 (TrackingList[i].tme.hwndTrack != hwnd)) {
945 PostMessageA(TrackingList[i].tme.hwndTrack, WM_MOUSELEAVE, 0, 0);
947 /* remove the TME_LEAVE flag */
948 TrackingList[i].tme.dwFlags ^= TME_LEAVE;
951 /* see if we are tracking hovering for this hwnd */
952 if(TrackingList[i].tme.dwFlags & TME_HOVER) {
953 /* add the timer interval to the hovering time */
954 TrackingList[i].iHoverTime+=iTimerInterval;
956 /* has the cursor moved outside the rectangle centered around pos? */
957 if((abs(pos.x - TrackingList[i].pos.x) > (hoverwidth / 2.0))
958 || (abs(pos.y - TrackingList[i].pos.y) > (hoverheight / 2.0)))
960 /* record this new position as the current position and reset */
961 /* the iHoverTime variable to 0 */
962 TrackingList[i].pos = pos;
963 TrackingList[i].iHoverTime = 0;
966 /* has the mouse hovered long enough? */
967 if(TrackingList[i].iHoverTime <= TrackingList[i].tme.dwHoverTime)
969 PostMessageA(TrackingList[i].tme.hwndTrack, WM_MOUSEHOVER, 0, 0);
971 /* stop tracking mouse hover */
972 TrackingList[i].tme.dwFlags ^= TME_HOVER;
976 /* see if we are still tracking TME_HOVER or TME_LEAVE for this entry */
977 if((TrackingList[i].tme.dwFlags & TME_HOVER) ||
978 (TrackingList[i].tme.dwFlags & TME_LEAVE)) {
980 } else { /* remove this entry from the tracking list */
981 TrackingList[i] = TrackingList[--iTrackMax];
985 /* stop the timer if the tracking list is empty */
992 /***********************************************************************
993 * _TrackMouseEvent [COMCTL32.91]
995 * Requests notification of mouse events
997 * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
998 * to the hwnd specified in the ptme structure. After the event message
999 * is posted to the hwnd, the entry in the queue is removed.
1001 * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
1002 * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
1003 * immediately and the TME_LEAVE flag being ignored.
1006 * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
1015 _TrackMouseEvent (TRACKMOUSEEVENT *ptme)
1019 BOOL cancel = 0, hover = 0, leave = 0, query = 0;
1026 TRACE("%lx, %lx, %x, %lx\n", ptme->cbSize, ptme->dwFlags, ptme->hwndTrack, ptme->dwHoverTime);
1028 if (ptme->cbSize != sizeof(TRACKMOUSEEVENT)) {
1029 WARN("wrong TRACKMOUSEEVENT size from app\n");
1030 SetLastError(ERROR_INVALID_PARAMETER); /* FIXME not sure if this is correct */
1034 flags = ptme->dwFlags;
1036 /* if HOVER_DEFAULT was specified replace this with the systems current value */
1037 if(ptme->dwHoverTime == HOVER_DEFAULT)
1038 SystemParametersInfoA(SPI_GETMOUSEHOVERTIME, 0, &(ptme->dwHoverTime), 0);
1041 hwnd = WindowFromPoint(pos);
1043 if ( flags & TME_CANCEL ) {
1044 flags &= ~ TME_CANCEL;
1048 if ( flags & TME_HOVER ) {
1049 flags &= ~ TME_HOVER;
1053 if ( flags & TME_LEAVE ) {
1054 flags &= ~ TME_LEAVE;
1058 /* fill the TRACKMOUSEEVENT struct with the current tracking for the given hwnd */
1059 if ( flags & TME_QUERY ) {
1060 flags &= ~ TME_QUERY;
1064 /* Find the tracking list entry with the matching hwnd */
1065 while((i < iTrackMax) && (TrackingList[i].tme.hwndTrack != ptme->hwndTrack)) {
1069 /* hwnd found, fill in the ptme struct */
1071 *ptme = TrackingList[i].tme;
1075 return TRUE; /* return here, TME_QUERY is retrieving information */
1079 FIXME("Unknown flag(s) %08lx\n", flags );
1082 /* find a matching hwnd if one exists */
1085 while((i < iTrackMax) && (TrackingList[i].tme.hwndTrack != ptme->hwndTrack)) {
1090 TrackingList[i].tme.dwFlags &= ~(ptme->dwFlags & ~TME_CANCEL);
1092 /* if we aren't tracking on hover or leave remove this entry */
1093 if(!((TrackingList[i].tme.dwFlags & TME_HOVER) ||
1094 (TrackingList[i].tme.dwFlags & TME_LEAVE)))
1096 TrackingList[i] = TrackingList[--iTrackMax];
1098 if(iTrackMax == 0) {
1099 KillTimer(0, timer);
1105 /* see if hwndTrack isn't the current window */
1106 if(ptme->hwndTrack != hwnd) {
1108 PostMessageA(ptme->hwndTrack, WM_MOUSELEAVE, 0, 0);
1111 /* See if this hwnd is already being tracked and update the tracking flags */
1112 for(i = 0; i < iTrackMax; i++) {
1113 if(TrackingList[i].tme.hwndTrack == ptme->hwndTrack) {
1115 TrackingList[i].tme.dwFlags |= TME_HOVER;
1116 TrackingList[i].tme.dwHoverTime = ptme->dwHoverTime;
1120 TrackingList[i].tme.dwFlags |= TME_LEAVE;
1122 /* reset iHoverTime as per winapi specs */
1123 TrackingList[i].iHoverTime = 0;
1129 /* if the tracking list is full return FALSE */
1130 if (iTrackMax == sizeof (TrackingList) / sizeof(*TrackingList)) {
1134 /* Adding new mouse event to the tracking list */
1135 TrackingList[iTrackMax].tme = *ptme;
1137 /* Initialize HoverInfo variables even if not hover tracking */
1138 TrackingList[iTrackMax].iHoverTime = 0;
1139 TrackingList[iTrackMax].pos = pos;
1144 timer = SetTimer(0, 0, iTimerInterval, TrackMouseEventProc);
1153 /*************************************************************************
1154 * GetMUILanguage [COMCTL32.39]
1156 * FIXME: What's this supposed to do? Apparently some i18n thing.
1159 LANGID WINAPI GetMUILanguage (VOID)
1161 return COMCTL32_uiLang;
1165 /*************************************************************************
1166 * InitMUILanguage [COMCTL32.85]
1168 * FIXME: What's this supposed to do? Apparently some i18n thing.
1172 VOID WINAPI InitMUILanguage (LANGID uiLang)
1174 COMCTL32_uiLang = uiLang;
1178 /***********************************************************************
1179 * COMCTL32_CreateToolTip [NOT AN API]
1181 * Creates a tooltip for the control specified in hwnd and does all
1182 * necessary setup and notifications.
1185 * hwndOwner [I] Handle to the window that will own the tool tip.
1188 * Success: Handle of tool tip window.
1192 COMCTL32_CreateToolTip(HWND hwndOwner)
1196 hwndToolTip = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
1197 CW_USEDEFAULT, CW_USEDEFAULT,
1198 CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner,
1201 /* Send NM_TOOLTIPSCREATED notification */
1204 NMTOOLTIPSCREATED nmttc;
1205 /* true owner can be different if hwndOwner is a child window */
1206 HWND hwndTrueOwner = GetWindow(hwndToolTip, GW_OWNER);
1207 nmttc.hdr.hwndFrom = hwndTrueOwner;
1208 nmttc.hdr.idFrom = GetWindowLongA(hwndTrueOwner, GWL_ID);
1209 nmttc.hdr.code = NM_TOOLTIPSCREATED;
1210 nmttc.hwndToolTips = hwndToolTip;
1212 SendMessageA(GetParent(hwndTrueOwner), WM_NOTIFY,
1213 (WPARAM)GetWindowLongA(hwndTrueOwner, GWL_ID),