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 * DrawStatusTextA [COMCTL32.5][COMCTL32.27]
380 * Draws text with borders, like in a status bar.
383 * hdc [I] handle to the window's display context
384 * lprc [I] pointer to a rectangle
385 * text [I] pointer to the text
386 * style [I] drawing style
392 * The style variable can have one of the following values:
393 * (will be written ...)
397 DrawStatusTextA (HDC hdc, LPRECT lprc, LPCSTR text, UINT style)
400 UINT border = BDR_SUNKENOUTER;
402 if (style & SBT_POPOUT)
403 border = BDR_RAISEDOUTER;
404 else if (style & SBT_NOBORDERS)
407 DrawEdge (hdc, &r, border, BF_RECT|BF_ADJUST|BF_MIDDLE);
411 int oldbkmode = SetBkMode (hdc, TRANSPARENT);
413 DrawTextA (hdc, text, lstrlenA(text),
414 &r, DT_LEFT|DT_VCENTER|DT_SINGLELINE);
415 if (oldbkmode != TRANSPARENT)
416 SetBkMode(hdc, oldbkmode);
421 /***********************************************************************
422 * DrawStatusTextW [COMCTL32.28]
424 * Draws text with borders, like in a status bar.
427 * hdc [I] handle to the window's display context
428 * lprc [I] pointer to a rectangle
429 * text [I] pointer to the text
430 * style [I] drawing style
437 DrawStatusTextW (HDC hdc, LPRECT lprc, LPCWSTR text, UINT style)
439 LPSTR p = HEAP_strdupWtoA (GetProcessHeap (), 0, text);
440 DrawStatusTextA (hdc, lprc, p, style);
441 HeapFree (GetProcessHeap (), 0, p );
445 /***********************************************************************
446 * CreateStatusWindowA [COMCTL32.6][COMCTL32.21]
448 * Creates a status bar
451 * style [I] window style
452 * text [I] pointer to the window text
453 * parent [I] handle to the parent window
454 * wid [I] control id of the status bar
457 * Success: handle to the status window
462 CreateStatusWindowA (INT style, LPCSTR text, HWND parent, UINT wid)
464 return CreateWindowA(STATUSCLASSNAMEA, text, style,
465 CW_USEDEFAULT, CW_USEDEFAULT,
466 CW_USEDEFAULT, CW_USEDEFAULT,
471 /***********************************************************************
472 * CreateStatusWindowW [COMCTL32.22] Creates a status bar control
475 * style [I] window style
476 * text [I] pointer to the window text
477 * parent [I] handle to the parent window
478 * wid [I] control id of the status bar
481 * Success: handle to the status window
486 CreateStatusWindowW (INT style, LPCWSTR text, HWND parent, UINT wid)
488 return CreateWindowW(STATUSCLASSNAMEW, text, style,
489 CW_USEDEFAULT, CW_USEDEFAULT,
490 CW_USEDEFAULT, CW_USEDEFAULT,
495 /***********************************************************************
496 * CreateUpDownControl [COMCTL32.16] Creates an up-down control
499 * style [I] window styles
500 * x [I] horizontal position of the control
501 * y [I] vertical position of the control
502 * cx [I] with of the control
503 * cy [I] height of the control
504 * parent [I] handle to the parent window
505 * id [I] the control's identifier
506 * inst [I] handle to the application's module instance
507 * buddy [I] handle to the buddy window, can be NULL
508 * maxVal [I] upper limit of the control
509 * minVal [I] lower limit of the control
510 * curVal [I] current value of the control
513 * Success: handle to the updown control
518 CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
519 HWND parent, INT id, HINSTANCE inst,
520 HWND buddy, INT maxVal, INT minVal, INT curVal)
523 CreateWindowA (UPDOWN_CLASSA, 0, style, x, y, cx, cy,
524 parent, id, inst, 0);
526 SendMessageA (hUD, UDM_SETBUDDY, buddy, 0);
527 SendMessageA (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));
528 SendMessageA (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));
535 /***********************************************************************
536 * InitCommonControls [COMCTL32.17]
538 * Registers the common controls.
547 * This function is just a dummy.
548 * The Win95 controls are registered at the DLL's initialization.
549 * To register other controls InitCommonControlsEx() must be used.
553 InitCommonControls (void)
558 /***********************************************************************
559 * InitCommonControlsEx [COMCTL32.81]
561 * Registers the common controls.
564 * lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
571 * Only the additional common controls are registered by this function.
572 * The Win95 controls are registered at the DLL's initialization.
576 InitCommonControlsEx (LPINITCOMMONCONTROLSEX lpInitCtrls)
583 if (lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
586 TRACE("(0x%08lx)\n", lpInitCtrls->dwICC);
588 for (cCount = 0; cCount < 32; cCount++) {
589 dwMask = 1 << cCount;
590 if (!(lpInitCtrls->dwICC & dwMask))
593 switch (lpInitCtrls->dwICC & dwMask) {
594 /* dummy initialization */
595 case ICC_ANIMATE_CLASS:
596 case ICC_BAR_CLASSES:
597 case ICC_LISTVIEW_CLASSES:
598 case ICC_TREEVIEW_CLASSES:
599 case ICC_TAB_CLASSES:
600 case ICC_UPDOWN_CLASS:
601 case ICC_PROGRESS_CLASS:
602 case ICC_HOTKEY_CLASS:
605 /* advanced classes - not included in Win95 */
606 case ICC_DATE_CLASSES:
607 MONTHCAL_Register ();
608 DATETIME_Register ();
611 case ICC_USEREX_CLASSES:
615 case ICC_COOL_CLASSES:
619 case ICC_INTERNET_CLASSES:
620 IPADDRESS_Register ();
623 case ICC_PAGESCROLLER_CLASS:
627 case ICC_NATIVEFNTCTL_CLASS:
628 NATIVEFONT_Register ();
632 FIXME("Unknown class! dwICC=0x%lX\n", dwMask);
641 /***********************************************************************
642 * CreateToolbarEx [COMCTL32.32] Creates a tool bar window
660 * Success: handle to the tool bar control
665 CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
666 HINSTANCE hBMInst, UINT wBMID, LPCTBBUTTON lpButtons,
667 INT iNumButtons, INT dxButton, INT dyButton,
668 INT dxBitmap, INT dyBitmap, UINT uStructSize)
672 /* If not position is specified then put it at the top */
673 if ((style & CCS_BOTTOM) == 0) {
678 CreateWindowExA (0, TOOLBARCLASSNAMEA, "", style|WS_CHILD, 0, 0, 0, 0,
679 hwnd, (HMENU)wID, 0, NULL);
683 SendMessageA (hwndTB, TB_BUTTONSTRUCTSIZE,
684 (WPARAM)uStructSize, 0);
686 /* set bitmap and button size */
687 /*If CreateToolbarEx receives 0, windows sets default values*/
692 SendMessageA (hwndTB, TB_SETBITMAPSIZE, 0,
693 MAKELPARAM((WORD)dxBitmap, (WORD)dyBitmap));
699 SendMessageA (hwndTB, TB_SETBUTTONSIZE, 0,
700 MAKELPARAM((WORD)dxButton, (WORD)dyButton));
706 tbab.hInst = hBMInst;
709 SendMessageA (hwndTB, TB_ADDBITMAP,
710 (WPARAM)nBitmaps, (LPARAM)&tbab);
714 SendMessageA (hwndTB, TB_ADDBUTTONSA,
715 (WPARAM)iNumButtons, (LPARAM)lpButtons);
722 /***********************************************************************
723 * CreateMappedBitmap [COMCTL32.8]
733 * Success: handle to the new bitmap
738 CreateMappedBitmap (HINSTANCE hInstance, INT idBitmap, UINT wFlags,
739 LPCOLORMAP lpColorMap, INT iNumMaps)
743 LPBITMAPINFOHEADER lpBitmap, lpBitmapInfo;
744 UINT nSize, nColorTableSize;
745 RGBQUAD *pColorTable;
746 INT iColor, i, iMaps, nWidth, nHeight;
749 LPCOLORMAP sysColorMap;
751 COLORMAP internalColorMap[4] =
752 {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
754 /* initialize pointer to colortable and default color table */
757 sysColorMap = lpColorMap;
760 internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT);
761 internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW);
762 internalColorMap[2].to = GetSysColor (COLOR_BTNFACE);
763 internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT);
765 sysColorMap = (LPCOLORMAP)internalColorMap;
768 hRsrc = FindResourceA (hInstance, (LPSTR)idBitmap, RT_BITMAPA);
771 hglb = LoadResource (hInstance, hRsrc);
774 lpBitmap = (LPBITMAPINFOHEADER)LockResource (hglb);
775 if (lpBitmap == NULL)
778 nColorTableSize = (1 << lpBitmap->biBitCount);
779 nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
780 lpBitmapInfo = (LPBITMAPINFOHEADER)GlobalAlloc (GMEM_FIXED, nSize);
781 if (lpBitmapInfo == NULL)
783 RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);
785 pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo)+(UINT)lpBitmapInfo->biSize);
787 for (iColor = 0; iColor < nColorTableSize; iColor++) {
788 for (i = 0; i < iMaps; i++) {
789 cRef = RGB(pColorTable[iColor].rgbRed,
790 pColorTable[iColor].rgbGreen,
791 pColorTable[iColor].rgbBlue);
792 if ( cRef == sysColorMap[i].from) {
794 if (wFlags & CBS_MASKED) {
795 if (sysColorMap[i].to != COLOR_BTNTEXT)
796 pColorTable[iColor] = RGB(255, 255, 255);
800 pColorTable[iColor].rgbBlue = GetBValue(sysColorMap[i].to);
801 pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);
802 pColorTable[iColor].rgbRed = GetRValue(sysColorMap[i].to);
807 nWidth = (INT)lpBitmapInfo->biWidth;
808 nHeight = (INT)lpBitmapInfo->biHeight;
809 hdcScreen = GetDC ((HWND)0);
810 hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
812 HDC hdcDst = CreateCompatibleDC (hdcScreen);
813 HBITMAP hbmOld = SelectObject (hdcDst, hbm);
814 LPBYTE lpBits = (LPBYTE)(lpBitmap + 1);
815 lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
816 StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
817 lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
819 SelectObject (hdcDst, hbmOld);
822 ReleaseDC ((HWND)0, hdcScreen);
823 GlobalFree ((HGLOBAL)lpBitmapInfo);
830 /***********************************************************************
831 * CreateToolbar [COMCTL32.7] Creates a tool bar control
844 * Success: handle to the tool bar control
848 * Do not use this functions anymore. Use CreateToolbarEx instead.
852 CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
853 HINSTANCE hBMInst, UINT wBMID,
854 LPCOLDTBBUTTON lpButtons,INT iNumButtons)
856 return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
857 hBMInst, wBMID, (LPCTBBUTTON)lpButtons,
858 iNumButtons, 0, 0, 0, 0, sizeof (OLDTBBUTTON));
862 /***********************************************************************
863 * DllGetVersion [COMCTL32.25]
865 * Retrieves version information of the 'COMCTL32.DLL'
868 * pdvi [O] pointer to version information structure.
872 * Failure: E_INVALIDARG
875 * Returns version of a comctl32.dll from IE4.01 SP1.
879 COMCTL32_DllGetVersion (DLLVERSIONINFO *pdvi)
881 if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
882 WARN("wrong DLLVERSIONINFO size from app\n");
886 pdvi->dwMajorVersion = COMCTL32_VERSION;
887 pdvi->dwMinorVersion = COMCTL32_VERSION_MINOR;
888 pdvi->dwBuildNumber = 2919;
889 pdvi->dwPlatformID = 6304;
891 TRACE("%lu.%lu.%lu.%lu\n",
892 pdvi->dwMajorVersion, pdvi->dwMinorVersion,
893 pdvi->dwBuildNumber, pdvi->dwPlatformID);
898 /***********************************************************************
899 * DllInstall (COMCTL32.@)
901 HRESULT WINAPI COMCTL32_DllInstall(BOOL bInstall, LPCWSTR cmdline)
903 FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
904 debugstr_w(cmdline));
910 typedef struct __TRACKINGLIST {
912 POINT pos; /* center of hover rectangle */
913 INT iHoverTime; /* elapsed time the cursor has been inside of the hover rect */
916 static _TRACKINGLIST TrackingList[10];
917 static int iTrackMax = 0;
918 static UINT_PTR timer;
919 static const INT iTimerInterval = 50; /* msec for timer interval */
921 /* FIXME: need to implement WM_NCMOUSELEAVE and WM_NCMOUSEHOVER for */
922 /* TrackMouseEventProc and _TrackMouseEvent */
923 static void CALLBACK TrackMouseEventProc(HWND hwndUnused, UINT uMsg, UINT_PTR idEvent,
929 INT hoverwidth = 0, hoverheight = 0;
932 hwnd = WindowFromPoint(pos);
934 SystemParametersInfoA(SPI_GETMOUSEHOVERWIDTH, 0, &hoverwidth, 0);
935 SystemParametersInfoA(SPI_GETMOUSEHOVERHEIGHT, 0, &hoverheight, 0);
937 /* loop through tracking events we are processing */
938 while (i < iTrackMax) {
939 /* see if this tracking event is looking for TME_LEAVE and that the */
940 /* mouse has left the window */
941 if ((TrackingList[i].tme.dwFlags & TME_LEAVE) &&
942 (TrackingList[i].tme.hwndTrack != hwnd)) {
943 PostMessageA(TrackingList[i].tme.hwndTrack, WM_MOUSELEAVE, 0, 0);
945 /* remove the TME_LEAVE flag */
946 TrackingList[i].tme.dwFlags ^= TME_LEAVE;
949 /* see if we are tracking hovering for this hwnd */
950 if(TrackingList[i].tme.dwFlags & TME_HOVER) {
951 /* add the timer interval to the hovering time */
952 TrackingList[i].iHoverTime+=iTimerInterval;
954 /* has the cursor moved outside the rectangle centered around pos? */
955 if((abs(pos.x - TrackingList[i].pos.x) > (hoverwidth / 2.0))
956 || (abs(pos.y - TrackingList[i].pos.y) > (hoverheight / 2.0)))
958 /* record this new position as the current position and reset */
959 /* the iHoverTime variable to 0 */
960 TrackingList[i].pos = pos;
961 TrackingList[i].iHoverTime = 0;
964 /* has the mouse hovered long enough? */
965 if(TrackingList[i].iHoverTime <= TrackingList[i].tme.dwHoverTime)
967 PostMessageA(TrackingList[i].tme.hwndTrack, WM_MOUSEHOVER, 0, 0);
969 /* stop tracking mouse hover */
970 TrackingList[i].tme.dwFlags ^= TME_HOVER;
974 /* see if we are still tracking TME_HOVER or TME_LEAVE for this entry */
975 if((TrackingList[i].tme.dwFlags & TME_HOVER) ||
976 (TrackingList[i].tme.dwFlags & TME_LEAVE)) {
978 } else { /* remove this entry from the tracking list */
979 TrackingList[i] = TrackingList[--iTrackMax];
983 /* stop the timer if the tracking list is empty */
990 /***********************************************************************
991 * _TrackMouseEvent [COMCTL32.25]
993 * Requests notification of mouse events
995 * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
996 * to the hwnd specified in the ptme structure. After the event message
997 * is posted to the hwnd, the entry in the queue is removed.
999 * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
1000 * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
1001 * immediately and the TME_LEAVE flag being ignored.
1004 * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
1013 _TrackMouseEvent (TRACKMOUSEEVENT *ptme)
1017 BOOL cancel = 0, hover = 0, leave = 0, query = 0;
1024 TRACE("%lx, %lx, %x, %lx\n", ptme->cbSize, ptme->dwFlags, ptme->hwndTrack, ptme->dwHoverTime);
1026 if (ptme->cbSize != sizeof(TRACKMOUSEEVENT)) {
1027 WARN("wrong TRACKMOUSEEVENT size from app\n");
1028 SetLastError(ERROR_INVALID_PARAMETER); /* FIXME not sure if this is correct */
1032 flags = ptme->dwFlags;
1034 /* if HOVER_DEFAULT was specified replace this with the systems current value */
1035 if(ptme->dwHoverTime == HOVER_DEFAULT)
1036 SystemParametersInfoA(SPI_GETMOUSEHOVERTIME, 0, &(ptme->dwHoverTime), 0);
1039 hwnd = WindowFromPoint(pos);
1041 if ( flags & TME_CANCEL ) {
1042 flags &= ~ TME_CANCEL;
1046 if ( flags & TME_HOVER ) {
1047 flags &= ~ TME_HOVER;
1051 if ( flags & TME_LEAVE ) {
1052 flags &= ~ TME_LEAVE;
1056 /* fill the TRACKMOUSEEVENT struct with the current tracking for the given hwnd */
1057 if ( flags & TME_QUERY ) {
1058 flags &= ~ TME_QUERY;
1062 /* Find the tracking list entry with the matching hwnd */
1063 while((i < iTrackMax) && (TrackingList[i].tme.hwndTrack != ptme->hwndTrack)) {
1067 /* hwnd found, fill in the ptme struct */
1069 *ptme = TrackingList[i].tme;
1073 return TRUE; /* return here, TME_QUERY is retrieving information */
1077 FIXME("Unknown flag(s) %08lx\n", flags );
1080 /* find a matching hwnd if one exists */
1083 while((i < iTrackMax) && (TrackingList[i].tme.hwndTrack != ptme->hwndTrack)) {
1088 TrackingList[i].tme.dwFlags &= ~(ptme->dwFlags & ~TME_CANCEL);
1090 /* if we aren't tracking on hover or leave remove this entry */
1091 if(!((TrackingList[i].tme.dwFlags & TME_HOVER) ||
1092 (TrackingList[i].tme.dwFlags & TME_LEAVE)))
1094 TrackingList[i] = TrackingList[--iTrackMax];
1096 if(iTrackMax == 0) {
1097 KillTimer(0, timer);
1103 /* see if hwndTrack isn't the current window */
1104 if(ptme->hwndTrack != hwnd) {
1106 PostMessageA(ptme->hwndTrack, WM_MOUSELEAVE, 0, 0);
1109 /* See if this hwnd is already being tracked and update the tracking flags */
1110 for(i = 0; i < iTrackMax; i++) {
1111 if(TrackingList[i].tme.hwndTrack == ptme->hwndTrack) {
1113 TrackingList[i].tme.dwFlags |= TME_HOVER;
1114 TrackingList[i].tme.dwHoverTime = ptme->dwHoverTime;
1118 TrackingList[i].tme.dwFlags |= TME_LEAVE;
1120 /* reset iHoverTime as per winapi specs */
1121 TrackingList[i].iHoverTime = 0;
1127 /* if the tracking list is full return FALSE */
1128 if (iTrackMax == sizeof (TrackingList) / sizeof(*TrackingList)) {
1132 /* Adding new mouse event to the tracking list */
1133 TrackingList[iTrackMax].tme = *ptme;
1135 /* Initialize HoverInfo variables even if not hover tracking */
1136 TrackingList[iTrackMax].iHoverTime = 0;
1137 TrackingList[iTrackMax].pos = pos;
1142 timer = SetTimer(0, 0, iTimerInterval, TrackMouseEventProc);
1151 /*************************************************************************
1152 * GetMUILanguage [COMCTL32.39]
1154 * FIXME: What's this supposed to do? Apparently some i18n thing.
1157 LANGID WINAPI GetMUILanguage (VOID)
1159 return COMCTL32_uiLang;
1163 /*************************************************************************
1164 * InitMUILanguage [COMCTL32.85]
1166 * FIXME: What's this supposed to do? Apparently some i18n thing.
1170 VOID WINAPI InitMUILanguage (LANGID uiLang)
1172 COMCTL32_uiLang = uiLang;
1176 /***********************************************************************
1177 * COMCTL32_CreateToolTip [NOT AN API]
1179 * Creates a tooltip for the control specified in hwnd and does all
1180 * necessary setup and notifications.
1183 * hwndOwner [I] Handle to the window that will own the tool tip.
1186 * Success: Handle of tool tip window.
1190 COMCTL32_CreateToolTip(HWND hwndOwner)
1194 hwndToolTip = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
1195 CW_USEDEFAULT, CW_USEDEFAULT,
1196 CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner,
1199 /* Send NM_TOOLTIPSCREATED notification */
1202 NMTOOLTIPSCREATED nmttc;
1203 /* true owner can be different if hwndOwner is a child window */
1204 HWND hwndTrueOwner = GetWindow(hwndToolTip, GW_OWNER);
1205 nmttc.hdr.hwndFrom = hwndTrueOwner;
1206 nmttc.hdr.idFrom = GetWindowLongA(hwndTrueOwner, GWL_ID);
1207 nmttc.hdr.code = NM_TOOLTIPSCREATED;
1208 nmttc.hwndToolTips = hwndToolTip;
1210 SendMessageA(GetParent(hwndTrueOwner), WM_NOTIFY,
1211 (WPARAM)GetWindowLongA(hwndTrueOwner, GWL_ID),