2 * Common controls functions
4 * Copyright 1997 Dimitrie O. Paun
5 * Copyright 1998,2000 Eric Kohl
20 #include "ipaddress.h"
23 #include "nativefont.h"
34 #include "debugtools.h"
37 DEFAULT_DEBUG_CHANNEL(commctrl
)
40 HANDLE COMCTL32_hHeap
= (HANDLE
)NULL
;
41 DWORD COMCTL32_dwProcessesAttached
= 0;
42 LPSTR COMCTL32_aSubclass
= (LPSTR
)NULL
;
43 HMODULE COMCTL32_hModule
= 0;
44 LANGID COMCTL32_uiLang
= MAKELANGID(LANG_NEUTRAL
, SUBLANG_NEUTRAL
);
47 /***********************************************************************
48 * COMCTL32_LibMain [Internal] Initializes the internal 'COMCTL32.DLL'.
51 * hinstDLL [I] handle to the 'dlls' instance
53 * lpvReserved [I] reserverd, must be NULL
61 COMCTL32_LibMain (HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
63 TRACE("%x,%lx,%p\n", hinstDLL
, fdwReason
, lpvReserved
);
66 case DLL_PROCESS_ATTACH
:
67 if (COMCTL32_dwProcessesAttached
== 0) {
69 /* This will be wrong for any other process attching in this address-space! */
70 COMCTL32_hModule
= (HMODULE
)hinstDLL
;
72 /* create private heap */
73 COMCTL32_hHeap
= HeapCreate (0, 0x10000, 0);
74 TRACE("Heap created: 0x%x\n", COMCTL32_hHeap
);
76 /* add global subclassing atom (used by 'tooltip' and 'updown') */
77 COMCTL32_aSubclass
= (LPSTR
)(DWORD
)GlobalAddAtomA ("CC32SubclassInfo");
78 TRACE("Subclassing atom added: %p\n",
81 /* register all Win95 common control classes */
96 COMCTL32_dwProcessesAttached
++;
99 case DLL_PROCESS_DETACH
:
100 COMCTL32_dwProcessesAttached
--;
101 if (COMCTL32_dwProcessesAttached
== 0) {
102 /* unregister all common control classes */
103 ANIMATE_Unregister ();
104 COMBOEX_Unregister ();
105 DATETIME_Unregister ();
106 FLATSB_Unregister ();
107 HEADER_Unregister ();
108 HOTKEY_Unregister ();
109 IPADDRESS_Unregister ();
110 LISTVIEW_Unregister ();
111 MONTHCAL_Unregister ();
112 NATIVEFONT_Unregister ();
114 PROGRESS_Unregister ();
116 STATUS_Unregister ();
118 TOOLBAR_Unregister ();
119 TOOLTIPS_Unregister ();
120 TRACKBAR_Unregister ();
121 TREEVIEW_Unregister ();
122 UPDOWN_Unregister ();
124 /* delete global subclassing atom */
125 GlobalDeleteAtom (LOWORD(COMCTL32_aSubclass
));
126 TRACE("Subclassing atom deleted: %p\n",
128 COMCTL32_aSubclass
= (LPSTR
)NULL
;
130 /* destroy private heap */
131 HeapDestroy (COMCTL32_hHeap
);
132 TRACE("Heap destroyed: 0x%x\n", COMCTL32_hHeap
);
133 COMCTL32_hHeap
= (HANDLE
)NULL
;
142 /***********************************************************************
143 * MenuHelp [COMCTL32.2]
146 * uMsg [I] message (WM_MENUSELECT) (see NOTES)
147 * wParam [I] wParam of the message uMsg
148 * lParam [I] lParam of the message uMsg
149 * hMainMenu [I] handle to the application's main menu
150 * hInst [I] handle to the module that contains string resources
151 * hwndStatus [I] handle to the status bar window
152 * lpwIDs [I] pointer to an array of intergers (see NOTES)
158 * The official documentation is incomplete!
159 * This is the correct documentation:
162 * MenuHelp() does NOT handle WM_COMMAND messages! It only handes
163 * WM_MENUSELECT messages.
166 * (will be written ...)
170 MenuHelp (UINT uMsg
, WPARAM wParam
, LPARAM lParam
, HMENU hMainMenu
,
171 HINSTANCE hInst
, HWND hwndStatus
, LPUINT lpwIDs
)
175 if (!IsWindow (hwndStatus
))
180 TRACE("WM_MENUSELECT wParam=0x%X lParam=0x%lX\n",
183 if ((HIWORD(wParam
) == 0xFFFF) && (lParam
== 0)) {
184 /* menu was closed */
185 TRACE("menu was closed!\n");
186 SendMessageA (hwndStatus
, SB_SIMPLE
, FALSE
, 0);
189 /* menu item was selected */
190 if (HIWORD(wParam
) & MF_POPUP
)
191 uMenuID
= (UINT
)*(lpwIDs
+1);
193 uMenuID
= (UINT
)LOWORD(wParam
);
194 TRACE("uMenuID = %u\n", uMenuID
);
199 if (!LoadStringA (hInst
, uMenuID
, szText
, 256))
202 SendMessageA (hwndStatus
, SB_SETTEXTA
,
203 255 | SBT_NOBORDERS
, (LPARAM
)szText
);
204 SendMessageA (hwndStatus
, SB_SIMPLE
, TRUE
, 0);
210 TRACE("WM_COMMAND wParam=0x%X lParam=0x%lX\n",
212 /* WM_COMMAND is not invalid since it is documented
213 * in the windows api reference. So don't output
214 * any FIXME for WM_COMMAND
216 WARN("We don't care about the WM_COMMAND\n");
220 FIXME("Invalid Message 0x%x!\n", uMsg
);
226 /***********************************************************************
227 * ShowHideMenuCtl [COMCTL32.3]
229 * Shows or hides controls and updates the corresponding menu item.
232 * hwnd [I] handle to the client window.
233 * uFlags [I] menu command id.
234 * lpInfo [I] pointer to an array of integers. (See NOTES.)
241 * The official documentation is incomplete!
242 * This is the correct documentation:
245 * Handle to the window that contains the menu and controls.
248 * Identifier of the menu item to receive or loose a check mark.
251 * The array of integers contains pairs of values. BOTH values of
252 * the first pair must be the handles to the application's main menu.
253 * Each subsequent pair consists of a menu id and control id.
257 ShowHideMenuCtl (HWND hwnd
, UINT uFlags
, LPINT lpInfo
)
261 TRACE("%x, %x, %p\n", hwnd
, uFlags
, lpInfo
);
266 if (!(lpInfo
[0]) || !(lpInfo
[1]))
269 /* search for control */
270 lpMenuId
= &lpInfo
[2];
271 while (*lpMenuId
!= uFlags
)
274 if (GetMenuState (lpInfo
[1], uFlags
, MF_BYCOMMAND
) & MFS_CHECKED
) {
275 /* uncheck menu item */
276 CheckMenuItem (lpInfo
[0], *lpMenuId
, MF_BYCOMMAND
| MF_UNCHECKED
);
280 SetWindowPos (GetDlgItem (hwnd
, *lpMenuId
), 0, 0, 0, 0, 0,
284 /* check menu item */
285 CheckMenuItem (lpInfo
[0], *lpMenuId
, MF_BYCOMMAND
| MF_CHECKED
);
289 SetWindowPos (GetDlgItem (hwnd
, *lpMenuId
), 0, 0, 0, 0, 0,
297 /***********************************************************************
298 * GetEffectiveClientRect [COMCTL32.4]
301 * hwnd [I] handle to the client window.
302 * lpRect [O] pointer to the rectangle of the client window
303 * lpInfo [I] pointer to an array of integers (see NOTES)
309 * The official documentation is incomplete!
310 * This is the correct documentation:
313 * (will be written...)
317 GetEffectiveClientRect (HWND hwnd
, LPRECT lpRect
, LPINT lpInfo
)
323 TRACE("(0x%08lx 0x%08lx 0x%08lx)\n",
324 (DWORD
)hwnd
, (DWORD
)lpRect
, (DWORD
)lpInfo
);
326 GetClientRect (hwnd
, lpRect
);
334 hwndCtrl
= GetDlgItem (hwnd
, *lpRun
);
335 if (GetWindowLongA (hwndCtrl
, GWL_STYLE
) & WS_VISIBLE
) {
336 TRACE("control id 0x%x\n", *lpRun
);
337 GetWindowRect (hwndCtrl
, &rcCtrl
);
338 MapWindowPoints ((HWND
)0, hwnd
, (LPPOINT
)&rcCtrl
, 2);
339 SubtractRect (lpRect
, lpRect
, &rcCtrl
);
346 /***********************************************************************
347 * DrawStatusTextA [COMCTL32.5][COMCTL32.27]
349 * Draws text with borders, like in a status bar.
352 * hdc [I] handle to the window's display context
353 * lprc [I] pointer to a rectangle
354 * text [I] pointer to the text
355 * style [I] drawing style
361 * The style variable can have one of the following values:
362 * (will be written ...)
366 DrawStatusTextA (HDC hdc
, LPRECT lprc
, LPCSTR text
, UINT style
)
369 UINT border
= BDR_SUNKENOUTER
;
371 if (style
& SBT_POPOUT
)
372 border
= BDR_RAISEDOUTER
;
373 else if (style
& SBT_NOBORDERS
)
376 DrawEdge (hdc
, &r
, border
, BF_RECT
|BF_ADJUST
|BF_MIDDLE
);
380 int oldbkmode
= SetBkMode (hdc
, TRANSPARENT
);
382 DrawTextA (hdc
, text
, lstrlenA(text
),
383 &r
, DT_LEFT
|DT_VCENTER
|DT_SINGLELINE
);
384 if (oldbkmode
!= TRANSPARENT
)
385 SetBkMode(hdc
, oldbkmode
);
390 /***********************************************************************
391 * DrawStatusTextW [COMCTL32.28]
393 * Draws text with borders, like in a status bar.
396 * hdc [I] handle to the window's display context
397 * lprc [I] pointer to a rectangle
398 * text [I] pointer to the text
399 * style [I] drawing style
406 DrawStatusTextW (HDC hdc
, LPRECT lprc
, LPCWSTR text
, UINT style
)
408 LPSTR p
= HEAP_strdupWtoA (GetProcessHeap (), 0, text
);
409 DrawStatusTextA (hdc
, lprc
, p
, style
);
410 HeapFree (GetProcessHeap (), 0, p
);
414 /***********************************************************************
415 * CreateStatusWindowA [COMCTL32.6][COMCTL32.21]
417 * Creates a status bar
420 * style [I] window style
421 * text [I] pointer to the window text
422 * parent [I] handle to the parent window
423 * wid [I] control id of the status bar
426 * Success: handle to the status window
431 CreateStatusWindowA (INT style
, LPCSTR text
, HWND parent
, UINT wid
)
433 return CreateWindowA(STATUSCLASSNAMEA
, text
, style
,
434 CW_USEDEFAULT
, CW_USEDEFAULT
,
435 CW_USEDEFAULT
, CW_USEDEFAULT
,
440 /***********************************************************************
441 * CreateStatusWindowW [COMCTL32.22] Creates a status bar control
444 * style [I] window style
445 * text [I] pointer to the window text
446 * parent [I] handle to the parent window
447 * wid [I] control id of the status bar
450 * Success: handle to the status window
455 CreateStatusWindowW (INT style
, LPCWSTR text
, HWND parent
, UINT wid
)
457 return CreateWindowW(STATUSCLASSNAMEW
, text
, style
,
458 CW_USEDEFAULT
, CW_USEDEFAULT
,
459 CW_USEDEFAULT
, CW_USEDEFAULT
,
464 /***********************************************************************
465 * CreateUpDownControl [COMCTL32.16] Creates an up-down control
468 * style [I] window styles
469 * x [I] horizontal position of the control
470 * y [I] vertical position of the control
471 * cx [I] with of the control
472 * cy [I] height of the control
473 * parent [I] handle to the parent window
474 * id [I] the control's identifier
475 * inst [I] handle to the application's module instance
476 * buddy [I] handle to the buddy window, can be NULL
477 * maxVal [I] upper limit of the control
478 * minVal [I] lower limit of the control
479 * curVal [I] current value of the control
482 * Success: handle to the updown control
487 CreateUpDownControl (DWORD style
, INT x
, INT y
, INT cx
, INT cy
,
488 HWND parent
, INT id
, HINSTANCE inst
,
489 HWND buddy
, INT maxVal
, INT minVal
, INT curVal
)
492 CreateWindowA (UPDOWN_CLASSA
, 0, style
, x
, y
, cx
, cy
,
493 parent
, id
, inst
, 0);
495 SendMessageA (hUD
, UDM_SETBUDDY
, buddy
, 0);
496 SendMessageA (hUD
, UDM_SETRANGE
, 0, MAKELONG(maxVal
, minVal
));
497 SendMessageA (hUD
, UDM_SETPOS
, 0, MAKELONG(curVal
, 0));
504 /***********************************************************************
505 * InitCommonControls [COMCTL32.17]
507 * Registers the common controls.
516 * This function is just a dummy.
517 * The Win95 controls are registered at the DLL's initialization.
518 * To register other controls InitCommonControlsEx() must be used.
522 InitCommonControls (void)
527 /***********************************************************************
528 * InitCommonControlsEx [COMCTL32.81]
530 * Registers the common controls.
533 * lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
540 * Only the additinal common controls are registered by this function.
541 * The Win95 controls are registered at the DLL's initialization.
545 InitCommonControlsEx (LPINITCOMMONCONTROLSEX lpInitCtrls
)
552 if (lpInitCtrls
->dwSize
!= sizeof(INITCOMMONCONTROLSEX
))
555 TRACE("(0x%08lx)\n", lpInitCtrls
->dwICC
);
557 for (cCount
= 0; cCount
< 32; cCount
++) {
558 dwMask
= 1 << cCount
;
559 if (!(lpInitCtrls
->dwICC
& dwMask
))
562 switch (lpInitCtrls
->dwICC
& dwMask
) {
563 /* dummy initialization */
564 case ICC_ANIMATE_CLASS
:
565 case ICC_BAR_CLASSES
:
566 case ICC_LISTVIEW_CLASSES
:
567 case ICC_TREEVIEW_CLASSES
:
568 case ICC_TAB_CLASSES
:
569 case ICC_UPDOWN_CLASS
:
570 case ICC_PROGRESS_CLASS
:
571 case ICC_HOTKEY_CLASS
:
574 /* advanced classes - not included in Win95 */
575 case ICC_DATE_CLASSES
:
576 MONTHCAL_Register ();
577 DATETIME_Register ();
580 case ICC_USEREX_CLASSES
:
584 case ICC_COOL_CLASSES
:
588 case ICC_INTERNET_CLASSES
:
589 IPADDRESS_Register ();
592 case ICC_PAGESCROLLER_CLASS
:
596 case ICC_NATIVEFNTCTL_CLASS
:
597 NATIVEFONT_Register ();
601 FIXME("Unknown class! dwICC=0x%lX\n", dwMask
);
610 /***********************************************************************
611 * CreateToolbarEx [COMCTL32.32] Creates a tool bar window
629 * Success: handle to the tool bar control
634 CreateToolbarEx (HWND hwnd
, DWORD style
, UINT wID
, INT nBitmaps
,
635 HINSTANCE hBMInst
, UINT wBMID
, LPCTBBUTTON lpButtons
,
636 INT iNumButtons
, INT dxButton
, INT dyButton
,
637 INT dxBitmap
, INT dyBitmap
, UINT uStructSize
)
640 CreateWindowExA (0, TOOLBARCLASSNAMEA
, "", style
, 0, 0, 0, 0,
641 hwnd
, (HMENU
)wID
, 0, NULL
);
645 SendMessageA (hwndTB
, TB_BUTTONSTRUCTSIZE
,
646 (WPARAM
)uStructSize
, 0);
648 /* set bitmap and button size */
649 /*If CreateToolbarEx receive 0, windows set default values*/
655 SendMessageA (hwndTB
, TB_SETBITMAPSIZE
, 0,
656 MAKELPARAM((WORD
)dxBitmap
, (WORD
)dyBitmap
));
657 SendMessageA (hwndTB
, TB_SETBUTTONSIZE
, 0,
658 MAKELPARAM((WORD
)dxButton
, (WORD
)dyButton
));
664 tbab
.hInst
= hBMInst
;
667 SendMessageA (hwndTB
, TB_ADDBITMAP
,
668 (WPARAM
)nBitmaps
, (LPARAM
)&tbab
);
672 SendMessageA (hwndTB
, TB_ADDBUTTONSA
,
673 (WPARAM
)iNumButtons
, (LPARAM
)lpButtons
);
680 /***********************************************************************
681 * CreateMappedBitmap [COMCTL32.8]
691 * Success: handle to the new bitmap
696 CreateMappedBitmap (HINSTANCE hInstance
, INT idBitmap
, UINT wFlags
,
697 LPCOLORMAP lpColorMap
, INT iNumMaps
)
701 LPBITMAPINFOHEADER lpBitmap
, lpBitmapInfo
;
702 UINT nSize
, nColorTableSize
;
703 RGBQUAD
*pColorTable
;
704 INT iColor
, i
, iMaps
, nWidth
, nHeight
;
707 LPCOLORMAP sysColorMap
;
709 COLORMAP internalColorMap
[4] =
710 {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
712 /* initialize pointer to colortable and default color table */
715 sysColorMap
= lpColorMap
;
718 internalColorMap
[0].to
= GetSysColor (COLOR_BTNTEXT
);
719 internalColorMap
[1].to
= GetSysColor (COLOR_BTNSHADOW
);
720 internalColorMap
[2].to
= GetSysColor (COLOR_BTNFACE
);
721 internalColorMap
[3].to
= GetSysColor (COLOR_BTNHIGHLIGHT
);
723 sysColorMap
= (LPCOLORMAP
)internalColorMap
;
726 hRsrc
= FindResourceA (hInstance
, (LPSTR
)idBitmap
, RT_BITMAPA
);
729 hglb
= LoadResource (hInstance
, hRsrc
);
732 lpBitmap
= (LPBITMAPINFOHEADER
)LockResource (hglb
);
733 if (lpBitmap
== NULL
)
736 nColorTableSize
= (1 << lpBitmap
->biBitCount
);
737 nSize
= lpBitmap
->biSize
+ nColorTableSize
* sizeof(RGBQUAD
);
738 lpBitmapInfo
= (LPBITMAPINFOHEADER
)GlobalAlloc (GMEM_FIXED
, nSize
);
739 if (lpBitmapInfo
== NULL
)
741 RtlMoveMemory (lpBitmapInfo
, lpBitmap
, nSize
);
743 pColorTable
= (RGBQUAD
*)(((LPBYTE
)lpBitmapInfo
)+(UINT
)lpBitmapInfo
->biSize
);
745 for (iColor
= 0; iColor
< nColorTableSize
; iColor
++) {
746 for (i
= 0; i
< iMaps
; i
++) {
747 cRef
= RGB(pColorTable
[iColor
].rgbRed
,
748 pColorTable
[iColor
].rgbGreen
,
749 pColorTable
[iColor
].rgbBlue
);
750 if ( cRef
== sysColorMap
[i
].from
) {
752 if (wFlags
& CBS_MASKED
) {
753 if (sysColorMap
[i
].to
!= COLOR_BTNTEXT
)
754 pColorTable
[iColor
] = RGB(255, 255, 255);
758 pColorTable
[iColor
].rgbBlue
= GetBValue(sysColorMap
[i
].to
);
759 pColorTable
[iColor
].rgbGreen
= GetGValue(sysColorMap
[i
].to
);
760 pColorTable
[iColor
].rgbRed
= GetRValue(sysColorMap
[i
].to
);
765 nWidth
= (INT
)lpBitmapInfo
->biWidth
;
766 nHeight
= (INT
)lpBitmapInfo
->biHeight
;
767 hdcScreen
= GetDC ((HWND
)0);
768 hbm
= CreateCompatibleBitmap (hdcScreen
, nWidth
, nHeight
);
770 HDC hdcDst
= CreateCompatibleDC (hdcScreen
);
771 HBITMAP hbmOld
= SelectObject (hdcDst
, hbm
);
772 LPBYTE lpBits
= (LPBYTE
)(lpBitmap
+ 1);
773 lpBits
+= (1 << (lpBitmapInfo
->biBitCount
)) * sizeof(RGBQUAD
);
774 StretchDIBits (hdcDst
, 0, 0, nWidth
, nHeight
, 0, 0, nWidth
, nHeight
,
775 lpBits
, (LPBITMAPINFO
)lpBitmapInfo
, DIB_RGB_COLORS
,
777 SelectObject (hdcDst
, hbmOld
);
780 ReleaseDC ((HWND
)0, hdcScreen
);
781 GlobalFree ((HGLOBAL
)lpBitmapInfo
);
788 /***********************************************************************
789 * CreateToolbar [COMCTL32.7] Creates a tool bar control
802 * Success: handle to the tool bar control
806 * Do not use this functions anymore. Use CreateToolbarEx instead.
810 CreateToolbar (HWND hwnd
, DWORD style
, UINT wID
, INT nBitmaps
,
811 HINSTANCE hBMInst
, UINT wBMID
,
812 LPCOLDTBBUTTON lpButtons
,INT iNumButtons
)
814 return CreateToolbarEx (hwnd
, style
| CCS_NODIVIDER
, wID
, nBitmaps
,
815 hBMInst
, wBMID
, (LPCTBBUTTON
)lpButtons
,
816 iNumButtons
, 0, 0, 0, 0, sizeof (OLDTBBUTTON
));
820 /***********************************************************************
821 * DllGetVersion [COMCTL32.25]
823 * Retrieves version information of the 'COMCTL32.DLL'
826 * pdvi [O] pointer to version information structure.
830 * Failure: E_INVALIDARG
833 * Returns version of a comctl32.dll from IE4.01 SP1.
837 COMCTL32_DllGetVersion (DLLVERSIONINFO
*pdvi
)
839 if (pdvi
->cbSize
!= sizeof(DLLVERSIONINFO
)) {
840 WARN("wrong DLLVERSIONINFO size from app");
844 pdvi
->dwMajorVersion
= 5;
845 pdvi
->dwMinorVersion
= 0;
846 pdvi
->dwBuildNumber
= 2919;
847 pdvi
->dwPlatformID
= 6304;
849 TRACE("%lu.%lu.%lu.%lu\n",
850 pdvi
->dwMajorVersion
, pdvi
->dwMinorVersion
,
851 pdvi
->dwBuildNumber
, pdvi
->dwPlatformID
);
856 /***********************************************************************
857 * DllInstall (COMCTL32.@)
859 HRESULT WINAPI
COMCTL32_DllInstall(BOOL bInstall
, LPCWSTR cmdline
)
861 FIXME("(%s, %s): stub\n", bInstall
?"TRUE":"FALSE",
862 debugstr_w(cmdline
));
868 typedef struct __TRACKINGLIST
{
870 POINT pos
; /* center of hover rectangle */
871 INT iHoverTime
; /* elapsed time the cursor has been inside of the hover rect */
874 static _TRACKINGLIST TrackingList
[10];
875 static int iTrackMax
= 0;
876 static UINT_PTR timer
;
877 static const INT iTimerInterval
= 50; /* msec for timer interval */
879 /* FIXME: need to implement WM_NCMOUSELEAVE and WM_NCMOUSEHOVER for */
880 /* TrackMouseEventProc and _TrackMouseEvent */
881 static void CALLBACK
TrackMouseEventProc(HWND hwndUnused
, UINT uMsg
, UINT_PTR idEvent
,
887 INT hoverwidth
= 0, hoverheight
= 0;
890 hwnd
= WindowFromPoint(pos
);
892 SystemParametersInfoA(SPI_GETMOUSEHOVERWIDTH
, 0, &hoverwidth
, 0);
893 SystemParametersInfoA(SPI_GETMOUSEHOVERHEIGHT
, 0, &hoverheight
, 0);
895 /* loop through tracking events we are processing */
896 while (i
< iTrackMax
) {
897 /* see if this tracking event is looking for TME_LEAVE and that the */
898 /* mouse has left the window */
899 if ((TrackingList
[i
].tme
.dwFlags
& TME_LEAVE
) &&
900 (TrackingList
[i
].tme
.hwndTrack
!= hwnd
)) {
901 PostMessageA(TrackingList
[i
].tme
.hwndTrack
, WM_MOUSELEAVE
, 0, 0);
903 /* remove the TME_LEAVE flag */
904 TrackingList
[i
].tme
.dwFlags
^= TME_LEAVE
;
907 /* see if we are tracking hovering for this hwnd */
908 if(TrackingList
[i
].tme
.dwFlags
& TME_HOVER
) {
909 /* add the timer interval to the hovering time */
910 TrackingList
[i
].iHoverTime
+=iTimerInterval
;
912 /* has the cursor moved outside the rectangle centered around pos? */
913 if((abs(pos
.x
- TrackingList
[i
].pos
.x
) > (hoverwidth
/ 2.0))
914 || (abs(pos
.y
- TrackingList
[i
].pos
.y
) > (hoverheight
/ 2.0)))
916 /* record this new position as the current position and reset */
917 /* the iHoverTime variable to 0 */
918 TrackingList
[i
].pos
= pos
;
919 TrackingList
[i
].iHoverTime
= 0;
922 /* has the mouse hovered long enough? */
923 if(TrackingList
[i
].iHoverTime
<= TrackingList
[i
].tme
.dwHoverTime
)
925 PostMessageA(TrackingList
[i
].tme
.hwndTrack
, WM_MOUSEHOVER
, 0, 0);
927 /* stop tracking mouse hover */
928 TrackingList
[i
].tme
.dwFlags
^= TME_HOVER
;
932 /* see if we are still tracking TME_HOVER or TME_LEAVE for this entry */
933 if((TrackingList
[i
].tme
.dwFlags
& TME_HOVER
) ||
934 (TrackingList
[i
].tme
.dwFlags
& TME_LEAVE
)) {
936 } else { /* remove this entry from the tracking list */
937 TrackingList
[i
] = TrackingList
[--iTrackMax
];
941 /* stop the timer if the tracking list is empty */
948 /***********************************************************************
949 * _TrackMouseEvent [COMCTL32.25]
951 * Requests notification of mouse events
953 * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
954 * to the hwnd specified in the ptme structure. After the event message
955 * is posted to the hwnd, the entry in the queue is removed.
957 * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
958 * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
959 * immediately and the TME_LEAVE flag being ignored.
962 * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
971 _TrackMouseEvent (TRACKMOUSEEVENT
*ptme
)
975 BOOL cancel
= 0, hover
= 0, leave
= 0, query
= 0;
982 TRACE("%lx, %lx, %x, %lx\n", ptme
->cbSize
, ptme
->dwFlags
, ptme
->hwndTrack
, ptme
->dwHoverTime
);
984 if (ptme
->cbSize
!= sizeof(TRACKMOUSEEVENT
)) {
985 WARN("wrong TRACKMOUSEEVENT size from app");
986 SetLastError(ERROR_INVALID_PARAMETER
); /* FIXME not sure if this is correct */
990 flags
= ptme
->dwFlags
;
992 /* if HOVER_DEFAULT was specified replace this with the systems current value */
993 if(ptme
->dwHoverTime
== HOVER_DEFAULT
)
994 SystemParametersInfoA(SPI_GETMOUSEHOVERTIME
, 0, &(ptme
->dwHoverTime
), 0);
997 hwnd
= WindowFromPoint(pos
);
999 if ( flags
& TME_CANCEL
) {
1000 flags
&= ~ TME_CANCEL
;
1004 if ( flags
& TME_HOVER
) {
1005 flags
&= ~ TME_HOVER
;
1009 if ( flags
& TME_LEAVE
) {
1010 flags
&= ~ TME_LEAVE
;
1014 /* fill the TRACKMOUSEEVENT struct with the current tracking for the given hwnd */
1015 if ( flags
& TME_QUERY
) {
1016 flags
&= ~ TME_QUERY
;
1020 /* Find the tracking list entry with the matching hwnd */
1021 while((i
< iTrackMax
) && (TrackingList
[i
].tme
.hwndTrack
!= ptme
->hwndTrack
)) {
1025 /* hwnd found, fill in the ptme struct */
1027 *ptme
= TrackingList
[i
].tme
;
1031 return TRUE
; /* return here, TME_QUERY is retrieving information */
1035 FIXME("Unknown flag(s) %08lx\n", flags
);
1038 /* find a matching hwnd if one exists */
1041 while((i
< iTrackMax
) && (TrackingList
[i
].tme
.hwndTrack
!= ptme
->hwndTrack
)) {
1046 TrackingList
[i
].tme
.dwFlags
&= ~(ptme
->dwFlags
& ~TME_CANCEL
);
1048 /* if we aren't tracking on hover or leave remove this entry */
1049 if(!((TrackingList
[i
].tme
.dwFlags
& TME_HOVER
) ||
1050 (TrackingList
[i
].tme
.dwFlags
& TME_LEAVE
)))
1052 TrackingList
[i
] = TrackingList
[--iTrackMax
];
1054 if(iTrackMax
== 0) {
1055 KillTimer(0, timer
);
1061 /* see if hwndTrack isn't the current window */
1062 if(ptme
->hwndTrack
!= hwnd
) {
1064 PostMessageA(ptme
->hwndTrack
, WM_MOUSELEAVE
, 0, 0);
1067 /* See if this hwnd is already being tracked and update the tracking flags */
1068 for(i
= 0; i
< iTrackMax
; i
++) {
1069 if(TrackingList
[i
].tme
.hwndTrack
== ptme
->hwndTrack
) {
1071 TrackingList
[i
].tme
.dwFlags
|= TME_HOVER
;
1072 TrackingList
[i
].tme
.dwHoverTime
= ptme
->dwHoverTime
;
1076 TrackingList
[i
].tme
.dwFlags
|= TME_LEAVE
;
1078 /* reset iHoverTime as per winapi specs */
1079 TrackingList
[i
].iHoverTime
= 0;
1085 /* if the tracking list is full return FALSE */
1086 if (iTrackMax
== sizeof (TrackingList
) / sizeof(*TrackingList
)) {
1090 /* Adding new mouse event to the tracking list */
1091 TrackingList
[iTrackMax
].tme
= *ptme
;
1093 /* Initialize HoverInfo variables even if not hover tracking */
1094 TrackingList
[iTrackMax
].iHoverTime
= 0;
1095 TrackingList
[iTrackMax
].pos
= pos
;
1100 timer
= SetTimer(0, 0, iTimerInterval
, TrackMouseEventProc
);
1109 /*************************************************************************
1110 * GetMUILanguage [COMCTL32.39]
1112 * FIXME: What's this supposed to do? Apparently some i18n thing.
1115 LANGID WINAPI
GetMUILanguage (VOID
)
1117 return COMCTL32_uiLang
;
1121 /*************************************************************************
1122 * InitMUILanguage [COMCTL32.85]
1124 * FIXME: What's this supposed to do? Apparently some i18n thing.
1128 VOID WINAPI
InitMUILanguage (LANGID uiLang
)
1130 COMCTL32_uiLang
= uiLang
;