2 * Common controls functions
4 * Copyright 1997 Dimitrie O. Paun
5 * Copyright 1998 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;
46 /***********************************************************************
47 * COMCTL32_LibMain [Internal] Initializes the internal 'COMCTL32.DLL'.
50 * hinstDLL [I] handle to the 'dlls' instance
52 * lpvReserved [I] reserverd, must be NULL
60 COMCTL32_LibMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
62 TRACE("%x,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
65 case DLL_PROCESS_ATTACH:
66 if (COMCTL32_dwProcessesAttached == 0) {
68 /* This will be wrong for any other process attching in this address-space! */
69 COMCTL32_hModule = (HMODULE)hinstDLL;
71 /* create private heap */
72 COMCTL32_hHeap = HeapCreate (0, 0x10000, 0);
73 TRACE("Heap created: 0x%x\n", COMCTL32_hHeap);
75 /* add global subclassing atom (used by 'tooltip' and 'updown') */
76 COMCTL32_aSubclass = (LPSTR)(DWORD)GlobalAddAtomA ("CC32SubclassInfo");
77 TRACE("Subclassing atom added: %p\n",
80 /* register all Win95 common control classes */
95 COMCTL32_dwProcessesAttached++;
98 case DLL_PROCESS_DETACH:
99 COMCTL32_dwProcessesAttached--;
100 if (COMCTL32_dwProcessesAttached == 0) {
101 /* unregister all common control classes */
102 ANIMATE_Unregister ();
103 COMBOEX_Unregister ();
104 DATETIME_Unregister ();
105 FLATSB_Unregister ();
106 HEADER_Unregister ();
107 HOTKEY_Unregister ();
108 IPADDRESS_Unregister ();
109 LISTVIEW_Unregister ();
110 MONTHCAL_Unregister ();
111 NATIVEFONT_Unregister ();
113 PROGRESS_Unregister ();
115 STATUS_Unregister ();
117 TOOLBAR_Unregister ();
118 TOOLTIPS_Unregister ();
119 TRACKBAR_Unregister ();
120 TREEVIEW_Unregister ();
121 UPDOWN_Unregister ();
123 /* delete global subclassing atom */
124 GlobalDeleteAtom (LOWORD(COMCTL32_aSubclass));
125 TRACE("Subclassing atom deleted: %p\n",
127 COMCTL32_aSubclass = (LPSTR)NULL;
129 /* destroy private heap */
130 HeapDestroy (COMCTL32_hHeap);
131 TRACE("Heap destroyed: 0x%x\n", COMCTL32_hHeap);
132 COMCTL32_hHeap = (HANDLE)NULL;
141 /***********************************************************************
142 * MenuHelp [COMCTL32.2]
145 * uMsg [I] message (WM_MENUSELECT) (see NOTES)
146 * wParam [I] wParam of the message uMsg
147 * lParam [I] lParam of the message uMsg
148 * hMainMenu [I] handle to the application's main menu
149 * hInst [I] handle to the module that contains string resources
150 * hwndStatus [I] handle to the status bar window
151 * lpwIDs [I] pointer to an array of intergers (see NOTES)
157 * The official documentation is incomplete!
158 * This is the correct documentation:
161 * MenuHelp() does NOT handle WM_COMMAND messages! It only handes
162 * WM_MENUSELECT messages.
165 * (will be written ...)
169 MenuHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu,
170 HINSTANCE hInst, HWND hwndStatus, LPUINT lpwIDs)
174 if (!IsWindow (hwndStatus))
179 TRACE("WM_MENUSELECT wParam=0x%X lParam=0x%lX\n",
182 if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {
183 /* menu was closed */
184 TRACE("menu was closed!\n");
185 SendMessageA (hwndStatus, SB_SIMPLE, FALSE, 0);
188 /* menu item was selected */
189 if (HIWORD(wParam) & MF_POPUP)
190 uMenuID = (UINT)*(lpwIDs+1);
192 uMenuID = (UINT)LOWORD(wParam);
193 TRACE("uMenuID = %u\n", uMenuID);
198 if (!LoadStringA (hInst, uMenuID, szText, 256))
201 SendMessageA (hwndStatus, SB_SETTEXTA,
202 255 | SBT_NOBORDERS, (LPARAM)szText);
203 SendMessageA (hwndStatus, SB_SIMPLE, TRUE, 0);
209 TRACE("WM_COMMAND wParam=0x%X lParam=0x%lX\n",
211 /* WM_COMMAND is not invalid since it is documented
212 * in the windows api reference. So don't output
213 * any FIXME for WM_COMMAND
215 WARN("We don't care about the WM_COMMAND\n");
219 FIXME("Invalid Message 0x%x!\n", uMsg);
225 /***********************************************************************
226 * ShowHideMenuCtl [COMCTL32.3]
228 * Shows or hides controls and updates the corresponding menu item.
231 * hwnd [I] handle to the client window.
232 * uFlags [I] menu command id.
233 * lpInfo [I] pointer to an array of integers. (See NOTES.)
240 * The official documentation is incomplete!
241 * This is the correct documentation:
244 * Handle to the window that contains the menu and controls.
247 * Identifier of the menu item to receive or loose a check mark.
250 * The array of integers contains pairs of values. BOTH values of
251 * the first pair must be the handles to the application's main menu.
252 * Each subsequent pair consists of a menu id and control id.
256 ShowHideMenuCtl (HWND hwnd, UINT uFlags, LPINT lpInfo)
260 TRACE("%x, %x, %p\n", hwnd, uFlags, lpInfo);
265 if (!(lpInfo[0]) || !(lpInfo[1]))
268 /* search for control */
269 lpMenuId = &lpInfo[2];
270 while (*lpMenuId != uFlags)
273 if (GetMenuState (lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) {
274 /* uncheck menu item */
275 CheckMenuItem (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_UNCHECKED);
279 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
283 /* check menu item */
284 CheckMenuItem (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_CHECKED);
288 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
296 /***********************************************************************
297 * GetEffectiveClientRect [COMCTL32.4]
300 * hwnd [I] handle to the client window.
301 * lpRect [O] pointer to the rectangle of the client window
302 * lpInfo [I] pointer to an array of integers (see NOTES)
308 * The official documentation is incomplete!
309 * This is the correct documentation:
312 * (will be written...)
316 GetEffectiveClientRect (HWND hwnd, LPRECT lpRect, LPINT lpInfo)
322 TRACE("(0x%08lx 0x%08lx 0x%08lx)\n",
323 (DWORD)hwnd, (DWORD)lpRect, (DWORD)lpInfo);
325 GetClientRect (hwnd, lpRect);
333 hwndCtrl = GetDlgItem (hwnd, *lpRun);
334 if (GetWindowLongA (hwndCtrl, GWL_STYLE) & WS_VISIBLE) {
335 TRACE("control id 0x%x\n", *lpRun);
336 GetWindowRect (hwndCtrl, &rcCtrl);
337 MapWindowPoints ((HWND)0, hwnd, (LPPOINT)&rcCtrl, 2);
338 SubtractRect (lpRect, lpRect, &rcCtrl);
345 /***********************************************************************
346 * DrawStatusTextA [COMCTL32.5][COMCTL32.27]
348 * Draws text with borders, like in a status bar.
351 * hdc [I] handle to the window's display context
352 * lprc [I] pointer to a rectangle
353 * text [I] pointer to the text
354 * style [I] drawing style
360 * The style variable can have one of the following values:
361 * (will be written ...)
365 DrawStatusTextA (HDC hdc, LPRECT lprc, LPCSTR text, UINT style)
368 UINT border = BDR_SUNKENOUTER;
370 if (style & SBT_POPOUT)
371 border = BDR_RAISEDOUTER;
372 else if (style & SBT_NOBORDERS)
375 DrawEdge (hdc, &r, border, BF_RECT|BF_ADJUST|BF_MIDDLE);
379 int oldbkmode = SetBkMode (hdc, TRANSPARENT);
381 DrawTextA (hdc, text, lstrlenA(text),
382 &r, DT_LEFT|DT_VCENTER|DT_SINGLELINE);
383 if (oldbkmode != TRANSPARENT)
384 SetBkMode(hdc, oldbkmode);
389 /***********************************************************************
390 * DrawStatusTextW [COMCTL32.28]
392 * Draws text with borders, like in a status bar.
395 * hdc [I] handle to the window's display context
396 * lprc [I] pointer to a rectangle
397 * text [I] pointer to the text
398 * style [I] drawing style
405 DrawStatusTextW (HDC hdc, LPRECT lprc, LPCWSTR text, UINT style)
407 LPSTR p = HEAP_strdupWtoA (GetProcessHeap (), 0, text);
408 DrawStatusTextA (hdc, lprc, p, style);
409 HeapFree (GetProcessHeap (), 0, p );
413 /***********************************************************************
414 * CreateStatusWindowA [COMCTL32.6][COMCTL32.21]
416 * Creates a status bar
419 * style [I] window style
420 * text [I] pointer to the window text
421 * parent [I] handle to the parent window
422 * wid [I] control id of the status bar
425 * Success: handle to the status window
430 CreateStatusWindowA (INT style, LPCSTR text, HWND parent, UINT wid)
432 return CreateWindowA(STATUSCLASSNAMEA, text, style,
433 CW_USEDEFAULT, CW_USEDEFAULT,
434 CW_USEDEFAULT, CW_USEDEFAULT,
439 /***********************************************************************
440 * CreateStatusWindowW [COMCTL32.22] Creates a status bar control
443 * style [I] window style
444 * text [I] pointer to the window text
445 * parent [I] handle to the parent window
446 * wid [I] control id of the status bar
449 * Success: handle to the status window
454 CreateStatusWindowW (INT style, LPCWSTR text, HWND parent, UINT wid)
456 return CreateWindowW(STATUSCLASSNAMEW, text, style,
457 CW_USEDEFAULT, CW_USEDEFAULT,
458 CW_USEDEFAULT, CW_USEDEFAULT,
463 /***********************************************************************
464 * CreateUpDownControl [COMCTL32.16] Creates an up-down control
467 * style [I] window styles
468 * x [I] horizontal position of the control
469 * y [I] vertical position of the control
470 * cx [I] with of the control
471 * cy [I] height of the control
472 * parent [I] handle to the parent window
473 * id [I] the control's identifier
474 * inst [I] handle to the application's module instance
475 * buddy [I] handle to the buddy window, can be NULL
476 * maxVal [I] upper limit of the control
477 * minVal [I] lower limit of the control
478 * curVal [I] current value of the control
481 * Success: handle to the updown control
486 CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
487 HWND parent, INT id, HINSTANCE inst,
488 HWND buddy, INT maxVal, INT minVal, INT curVal)
491 CreateWindowA (UPDOWN_CLASSA, 0, style, x, y, cx, cy,
492 parent, id, inst, 0);
494 SendMessageA (hUD, UDM_SETBUDDY, buddy, 0);
495 SendMessageA (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));
496 SendMessageA (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));
503 /***********************************************************************
504 * InitCommonControls [COMCTL32.17]
506 * Registers the common controls.
515 * This function is just a dummy.
516 * The Win95 controls are registered at the DLL's initialization.
517 * To register other controls InitCommonControlsEx() must be used.
521 InitCommonControls (void)
526 /***********************************************************************
527 * InitCommonControlsEx [COMCTL32.81]
529 * Registers the common controls.
532 * lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
539 * Only the additinal common controls are registered by this function.
540 * The Win95 controls are registered at the DLL's initialization.
544 InitCommonControlsEx (LPINITCOMMONCONTROLSEX lpInitCtrls)
551 if (lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
554 TRACE("(0x%08lx)\n", lpInitCtrls->dwICC);
556 for (cCount = 0; cCount < 32; cCount++) {
557 dwMask = 1 << cCount;
558 if (!(lpInitCtrls->dwICC & dwMask))
561 switch (lpInitCtrls->dwICC & dwMask) {
562 /* dummy initialization */
563 case ICC_ANIMATE_CLASS:
564 case ICC_BAR_CLASSES:
565 case ICC_LISTVIEW_CLASSES:
566 case ICC_TREEVIEW_CLASSES:
567 case ICC_TAB_CLASSES:
568 case ICC_UPDOWN_CLASS:
569 case ICC_PROGRESS_CLASS:
570 case ICC_HOTKEY_CLASS:
573 /* advanced classes - not included in Win95 */
574 case ICC_DATE_CLASSES:
575 MONTHCAL_Register ();
576 DATETIME_Register ();
579 case ICC_USEREX_CLASSES:
583 case ICC_COOL_CLASSES:
587 case ICC_INTERNET_CLASSES:
588 IPADDRESS_Register ();
591 case ICC_PAGESCROLLER_CLASS:
595 case ICC_NATIVEFNTCTL_CLASS:
596 NATIVEFONT_Register ();
600 FIXME("Unknown class! dwICC=0x%lX\n", dwMask);
609 /***********************************************************************
610 * CreateToolbarEx [COMCTL32.32] Creates a tool bar window
628 * Success: handle to the tool bar control
633 CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
634 HINSTANCE hBMInst, UINT wBMID, LPCTBBUTTON lpButtons,
635 INT iNumButtons, INT dxButton, INT dyButton,
636 INT dxBitmap, INT dyBitmap, UINT uStructSize)
639 CreateWindowExA (0, TOOLBARCLASSNAMEA, "", style, 0, 0, 0, 0,
640 hwnd, (HMENU)wID, 0, NULL);
644 SendMessageA (hwndTB, TB_BUTTONSTRUCTSIZE,
645 (WPARAM)uStructSize, 0);
647 /* set bitmap and button size */
648 /*If CreateToolbarEx receive 0, windows set default values*/
654 SendMessageA (hwndTB, TB_SETBITMAPSIZE, 0,
655 MAKELPARAM((WORD)dyBitmap, (WORD)dxBitmap));
656 SendMessageA (hwndTB, TB_SETBUTTONSIZE, 0,
657 MAKELPARAM((WORD)dyButton, (WORD)dxButton));
663 tbab.hInst = hBMInst;
666 SendMessageA (hwndTB, TB_ADDBITMAP,
667 (WPARAM)nBitmaps, (LPARAM)&tbab);
671 SendMessageA (hwndTB, TB_ADDBUTTONSA,
672 (WPARAM)iNumButtons, (LPARAM)lpButtons);
679 /***********************************************************************
680 * CreateMappedBitmap [COMCTL32.8]
690 * Success: handle to the new bitmap
695 CreateMappedBitmap (HINSTANCE hInstance, INT idBitmap, UINT wFlags,
696 LPCOLORMAP lpColorMap, INT iNumMaps)
700 LPBITMAPINFOHEADER lpBitmap, lpBitmapInfo;
701 UINT nSize, nColorTableSize;
702 RGBQUAD *pColorTable;
703 INT iColor, i, iMaps, nWidth, nHeight;
706 LPCOLORMAP sysColorMap;
708 COLORMAP internalColorMap[4] =
709 {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
711 /* initialize pointer to colortable and default color table */
714 sysColorMap = lpColorMap;
717 internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT);
718 internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW);
719 internalColorMap[2].to = GetSysColor (COLOR_BTNFACE);
720 internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT);
722 sysColorMap = (LPCOLORMAP)internalColorMap;
725 hRsrc = FindResourceA (hInstance, (LPSTR)idBitmap, RT_BITMAPA);
728 hglb = LoadResource (hInstance, hRsrc);
731 lpBitmap = (LPBITMAPINFOHEADER)LockResource (hglb);
732 if (lpBitmap == NULL)
735 nColorTableSize = (1 << lpBitmap->biBitCount);
736 nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
737 lpBitmapInfo = (LPBITMAPINFOHEADER)GlobalAlloc (GMEM_FIXED, nSize);
738 if (lpBitmapInfo == NULL)
740 RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);
742 pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo)+(UINT)lpBitmapInfo->biSize);
744 for (iColor = 0; iColor < nColorTableSize; iColor++) {
745 for (i = 0; i < iMaps; i++) {
746 cRef = RGB(pColorTable[iColor].rgbRed,
747 pColorTable[iColor].rgbGreen,
748 pColorTable[iColor].rgbBlue);
749 if ( cRef == sysColorMap[i].from) {
751 if (wFlags & CBS_MASKED) {
752 if (sysColorMap[i].to != COLOR_BTNTEXT)
753 pColorTable[iColor] = RGB(255, 255, 255);
757 pColorTable[iColor].rgbBlue = GetBValue(sysColorMap[i].to);
758 pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);
759 pColorTable[iColor].rgbRed = GetRValue(sysColorMap[i].to);
764 nWidth = (INT)lpBitmapInfo->biWidth;
765 nHeight = (INT)lpBitmapInfo->biHeight;
766 hdcScreen = GetDC ((HWND)0);
767 hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
769 HDC hdcDst = CreateCompatibleDC (hdcScreen);
770 HBITMAP hbmOld = SelectObject (hdcDst, hbm);
771 LPBYTE lpBits = (LPBYTE)(lpBitmap + 1);
772 lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
773 StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
774 lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
776 SelectObject (hdcDst, hbmOld);
779 ReleaseDC ((HWND)0, hdcScreen);
780 GlobalFree ((HGLOBAL)lpBitmapInfo);
787 /***********************************************************************
788 * CreateToolbar [COMCTL32.7] Creates a tool bar control
801 * Success: handle to the tool bar control
805 * Do not use this functions anymore. Use CreateToolbarEx instead.
809 CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
810 HINSTANCE hBMInst, UINT wBMID,
811 LPCOLDTBBUTTON lpButtons,INT iNumButtons)
813 return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
814 hBMInst, wBMID, (LPCTBBUTTON)lpButtons,
815 iNumButtons, 0, 0, 0, 0, sizeof (OLDTBBUTTON));
819 /***********************************************************************
820 * DllGetVersion [COMCTL32.25]
822 * Retrieves version information of the 'COMCTL32.DLL'
825 * pdvi [O] pointer to version information structure.
829 * Failure: E_INVALIDARG
832 * Returns version of a comctl32.dll from IE4.01 SP1.
836 COMCTL32_DllGetVersion (DLLVERSIONINFO *pdvi)
838 if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
839 WARN("wrong DLLVERSIONINFO size from app");
843 pdvi->dwMajorVersion = 4;
844 pdvi->dwMinorVersion = 72;
845 pdvi->dwBuildNumber = 3110;
846 pdvi->dwPlatformID = 1;
848 TRACE("%lu.%lu.%lu.%lu\n",
849 pdvi->dwMajorVersion, pdvi->dwMinorVersion,
850 pdvi->dwBuildNumber, pdvi->dwPlatformID);
856 static int iTrackMax = 0;
857 static HWND TrackingList[10];
858 static UINT_PTR timer;
860 static void CALLBACK TrackMouseEventProc(HWND hwndUnused, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) {
864 BOOL keepTracking = FALSE;
866 hwnd = WindowFromPoint(pos);
867 /* Loop through the list of windows waiting on mouse exit */
868 while (i < iTrackMax) {
869 if (TrackingList[i] != hwnd)
870 PostMessageA(TrackingList[i], WM_MOUSELEAVE, 0, 0);
880 TrackingList[0] = hwnd;
886 /***********************************************************************
887 * _TrackMouseEvent [COMCTL32.25]
889 * Requests notification of mouse events
892 * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
901 _TrackMouseEvent (TRACKMOUSEEVENT *ptme)
905 BOOL cancel = 0, hover = 0, leave = 0, query = 0;
906 if (ptme->cbSize != sizeof(TRACKMOUSEEVENT)) {
907 WARN("wrong TRACKMOUSEEVENT size from app");
911 TRACE("%lx, %lx, %x, %lx\n", ptme->cbSize, ptme->dwFlags, ptme->hwndTrack, ptme->dwHoverTime);
913 flags = ptme->dwFlags;
914 if ( flags & TME_CANCEL ) {
916 flags &= ~ TME_CANCEL;
918 if ( flags & TME_HOVER ) {
920 flags &= ~ TME_HOVER;
921 FIXME("TME_HOVER unimplemented\n" );
923 if ( flags & TME_LEAVE ) {
925 flags &= ~ TME_LEAVE;
927 if ( flags & TME_QUERY ) {
929 flags &= ~ TME_QUERY;
930 FIXME("TME_QUERY unimplemented\n" );
934 FIXME("Unknown flag(s) %ld\n", flags & ~(TME_CANCEL | TME_HOVER | TME_LEAVE | TME_QUERY) );
938 for (i = 0; i < iTrackMax; i++)
939 if (TrackingList[i] == ptme->hwndTrack)
940 TrackingList[i] = TrackingList[--iTrackMax];
943 if (iTrackMax == sizeof (TrackingList) / sizeof *TrackingList)
946 /* Add hwndTrack to the track list */
947 TrackingList[iTrackMax++] = ptme->hwndTrack;
949 timer = SetTimer(0, 0, 50, TrackMouseEventProc);