2 * Common controls functions
4 * Copyright 1997 Dimitrie O. Paun
5 * Copyright 1998,2000 Eric Kohl
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * This code was audited for completeness against the documented features
24 * of Comctl32.dll version 6.0 on Oct. 21, 2002, by Christian Neumair.
26 * Unless otherwise noted, we believe this code to be complete, as per
27 * the specification mentioned above.
28 * If you discover missing features, or bugs, please note them below.
31 * -- implement GetMUILanguage + InitMUILanguage
32 * -- LibMain => DLLMain ("DLLMain takes over the functionality of both the
33 * LibMain and the WEP function.", MSDN)
34 * -- finish NOTES for MenuHelp, GetEffectiveClientRect and GetStatusTextW
35 * -- FIXMEs + BUGS (search for them)
38 * -- ICC_ANIMATE_CLASS
43 * -- ICC_INTERNET_CLASSES
45 * -- ICC_LISTVIEW_CLASSES
46 * -- ICC_NATIVEFNTCTL_CLASS
47 * -- ICC_PAGESCROLLER_CLASS
48 * -- ICC_PROGRESS_CLASS
49 * -- ICC_STANDARD_CLASSES (not yet implemented)
51 * -- ICC_TREEVIEW_CLASSES
53 * -- ICC_USEREX_CLASSES
54 * -- ICC_WIN95_CLASSES
69 #define NO_SHLWAPI_STREAM
72 #include "wine/debug.h"
74 WINE_DEFAULT_DEBUG_CHANNEL(commctrl);
76 LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
78 LPWSTR COMCTL32_wSubclass = NULL;
79 HMODULE COMCTL32_hModule = 0;
80 LANGID COMCTL32_uiLang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
81 HBRUSH COMCTL32_hPattern55AABrush = NULL;
82 COMCTL32_SysColor comctl32_color;
84 static HBITMAP COMCTL32_hPattern55AABitmap = NULL;
86 static const WORD wPattern55AA[] =
88 0x5555, 0xaaaa, 0x5555, 0xaaaa,
89 0x5555, 0xaaaa, 0x5555, 0xaaaa
92 static const WCHAR strCC32SubclassInfo[] = {
93 'C','C','3','2','S','u','b','c','l','a','s','s','I','n','f','o',0
96 /***********************************************************************
99 * Initializes the internal 'COMCTL32.DLL'.
102 * hinstDLL [I] handle to the 'dlls' instance
104 * lpvReserved [I] reserverd, must be NULL
111 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
113 TRACE("%p,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
116 case DLL_PROCESS_ATTACH:
117 DisableThreadLibraryCalls(hinstDLL);
119 COMCTL32_hModule = (HMODULE)hinstDLL;
121 /* add global subclassing atom (used by 'tooltip' and 'updown') */
122 COMCTL32_wSubclass = (LPWSTR)(DWORD)GlobalAddAtomW (strCC32SubclassInfo);
123 TRACE("Subclassing atom added: %p\n", COMCTL32_wSubclass);
125 /* create local pattern brush */
126 COMCTL32_hPattern55AABitmap = CreateBitmap (8, 8, 1, 1, wPattern55AA);
127 COMCTL32_hPattern55AABrush = CreatePatternBrush (COMCTL32_hPattern55AABitmap);
129 /* Get all the colors at DLL load */
130 COMCTL32_RefreshSysColors();
132 /* register all Win95 common control classes */
137 LISTVIEW_Register ();
138 PROGRESS_Register ();
143 TOOLTIPS_Register ();
144 TRACKBAR_Register ();
145 TREEVIEW_Register ();
149 case DLL_PROCESS_DETACH:
150 /* unregister all common control classes */
151 ANIMATE_Unregister ();
152 COMBOEX_Unregister ();
153 DATETIME_Unregister ();
154 FLATSB_Unregister ();
155 HEADER_Unregister ();
156 HOTKEY_Unregister ();
157 IPADDRESS_Unregister ();
158 LISTVIEW_Unregister ();
159 MONTHCAL_Unregister ();
160 NATIVEFONT_Unregister ();
162 PROGRESS_Unregister ();
164 STATUS_Unregister ();
165 SYSLINK_Unregister ();
167 TOOLBAR_Unregister ();
168 TOOLTIPS_Unregister ();
169 TRACKBAR_Unregister ();
170 TREEVIEW_Unregister ();
171 UPDOWN_Unregister ();
173 /* delete local pattern brush */
174 DeleteObject (COMCTL32_hPattern55AABrush);
175 COMCTL32_hPattern55AABrush = NULL;
176 DeleteObject (COMCTL32_hPattern55AABitmap);
177 COMCTL32_hPattern55AABitmap = NULL;
179 /* delete global subclassing atom */
180 GlobalDeleteAtom (LOWORD(COMCTL32_wSubclass));
181 TRACE("Subclassing atom deleted: %p\n", COMCTL32_wSubclass);
182 COMCTL32_wSubclass = NULL;
190 /***********************************************************************
191 * MenuHelp [COMCTL32.2]
193 * Handles the setting of status bar help messages when the user
194 * selects menu items.
197 * uMsg [I] message (WM_MENUSELECT) (see NOTES)
198 * wParam [I] wParam of the message uMsg
199 * lParam [I] lParam of the message uMsg
200 * hMainMenu [I] handle to the application's main menu
201 * hInst [I] handle to the module that contains string resources
202 * hwndStatus [I] handle to the status bar window
203 * lpwIDs [I] pointer to an array of integers (see NOTES)
209 * The official documentation is incomplete!
210 * This is the correct documentation:
213 * MenuHelp() does NOT handle WM_COMMAND messages! It only handles
214 * WM_MENUSELECT messages.
217 * (will be written ...)
221 MenuHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu,
222 HINSTANCE hInst, HWND hwndStatus, UINT* lpwIDs)
226 if (!IsWindow (hwndStatus))
231 TRACE("WM_MENUSELECT wParam=0x%X lParam=0x%lX\n",
234 if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {
235 /* menu was closed */
236 TRACE("menu was closed!\n");
237 SendMessageW (hwndStatus, SB_SIMPLE, FALSE, 0);
240 /* menu item was selected */
241 if (HIWORD(wParam) & MF_POPUP)
242 uMenuID = (UINT)*(lpwIDs+1);
244 uMenuID = (UINT)LOWORD(wParam);
245 TRACE("uMenuID = %u\n", uMenuID);
250 if (!LoadStringW (hInst, uMenuID, szText, sizeof(szText)/sizeof(szText[0])))
253 SendMessageW (hwndStatus, SB_SETTEXTW,
254 255 | SBT_NOBORDERS, (LPARAM)szText);
255 SendMessageW (hwndStatus, SB_SIMPLE, TRUE, 0);
261 TRACE("WM_COMMAND wParam=0x%X lParam=0x%lX\n",
263 /* WM_COMMAND is not invalid since it is documented
264 * in the windows api reference. So don't output
265 * any FIXME for WM_COMMAND
267 WARN("We don't care about the WM_COMMAND\n");
271 FIXME("Invalid Message 0x%x!\n", uMsg);
277 /***********************************************************************
278 * ShowHideMenuCtl [COMCTL32.3]
280 * Shows or hides controls and updates the corresponding menu item.
283 * hwnd [I] handle to the client window.
284 * uFlags [I] menu command id.
285 * lpInfo [I] pointer to an array of integers. (See NOTES.)
292 * The official documentation is incomplete!
293 * This is the correct documentation:
296 * Handle to the window that contains the menu and controls.
299 * Identifier of the menu item to receive or lose a check mark.
302 * The array of integers contains pairs of values. BOTH values of
303 * the first pair must be the handles to the application's main menu.
304 * Each subsequent pair consists of a menu id and control id.
308 ShowHideMenuCtl (HWND hwnd, UINT uFlags, LPINT lpInfo)
312 TRACE("%p, %x, %p\n", hwnd, uFlags, lpInfo);
317 if (!(lpInfo[0]) || !(lpInfo[1]))
320 /* search for control */
321 lpMenuId = &lpInfo[2];
322 while (*lpMenuId != uFlags)
325 if (GetMenuState ((HMENU)lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) {
326 /* uncheck menu item */
327 CheckMenuItem ((HMENU)lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_UNCHECKED);
331 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
335 /* check menu item */
336 CheckMenuItem ((HMENU)lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_CHECKED);
340 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
348 /***********************************************************************
349 * GetEffectiveClientRect [COMCTL32.4]
351 * Calculates the coordinates of a rectangle in the client area.
354 * hwnd [I] handle to the client window.
355 * lpRect [O] pointer to the rectangle of the client window
356 * lpInfo [I] pointer to an array of integers (see NOTES)
362 * The official documentation is incomplete!
363 * This is the correct documentation:
366 * (will be written ...)
370 GetEffectiveClientRect (HWND hwnd, LPRECT lpRect, LPINT lpInfo)
376 TRACE("(0x%08lx 0x%08lx 0x%08lx)\n",
377 (DWORD)hwnd, (DWORD)lpRect, (DWORD)lpInfo);
379 GetClientRect (hwnd, lpRect);
387 hwndCtrl = GetDlgItem (hwnd, *lpRun);
388 if (GetWindowLongW (hwndCtrl, GWL_STYLE) & WS_VISIBLE) {
389 TRACE("control id 0x%x\n", *lpRun);
390 GetWindowRect (hwndCtrl, &rcCtrl);
391 MapWindowPoints (NULL, hwnd, (LPPOINT)&rcCtrl, 2);
392 SubtractRect (lpRect, lpRect, &rcCtrl);
399 /***********************************************************************
400 * DrawStatusTextW [COMCTL32.@]
402 * Draws text with borders, like in a status bar.
405 * hdc [I] handle to the window's display context
406 * lprc [I] pointer to a rectangle
407 * text [I] pointer to the text
408 * style [I] drawing style
414 * The style variable can have one of the following values:
415 * (will be written ...)
418 void WINAPI DrawStatusTextW (HDC hdc, LPRECT lprc, LPCWSTR text, UINT style)
421 UINT border = BDR_SUNKENOUTER;
423 if (style & SBT_POPOUT)
424 border = BDR_RAISEDOUTER;
425 else if (style & SBT_NOBORDERS)
428 DrawEdge (hdc, &r, border, BF_RECT|BF_ADJUST);
432 int oldbkmode = SetBkMode (hdc, TRANSPARENT);
433 UINT align = DT_LEFT;
434 if (*text == L'\t') {
437 if (*text == L'\t') {
443 if (style & SBT_RTLREADING)
444 FIXME("Unsupported RTL style!\n");
445 DrawTextW (hdc, text, -1, &r, align|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX);
446 SetBkMode(hdc, oldbkmode);
451 /***********************************************************************
452 * DrawStatusText [COMCTL32.@]
453 * DrawStatusTextA [COMCTL32.5]
455 * Draws text with borders, like in a status bar.
458 * hdc [I] handle to the window's display context
459 * lprc [I] pointer to a rectangle
460 * text [I] pointer to the text
461 * style [I] drawing style
467 void WINAPI DrawStatusTextA (HDC hdc, LPRECT lprc, LPCSTR text, UINT style)
473 if ( (len = MultiByteToWideChar( CP_ACP, 0, text, -1, NULL, 0 )) ) {
474 if ( (textW = Alloc( len * sizeof(WCHAR) )) )
475 MultiByteToWideChar( CP_ACP, 0, text, -1, textW, len );
478 DrawStatusTextW( hdc, lprc, textW, style );
483 /***********************************************************************
484 * CreateStatusWindow [COMCTL32.@]
485 * CreateStatusWindowA [COMCTL32.6]
487 * Creates a status bar
490 * style [I] window style
491 * text [I] pointer to the window text
492 * parent [I] handle to the parent window
493 * wid [I] control id of the status bar
496 * Success: handle to the status window
501 CreateStatusWindowA (LONG style, LPCSTR text, HWND parent, UINT wid)
503 return CreateWindowA(STATUSCLASSNAMEA, text, style,
504 CW_USEDEFAULT, CW_USEDEFAULT,
505 CW_USEDEFAULT, CW_USEDEFAULT,
506 parent, (HMENU)wid, 0, 0);
510 /***********************************************************************
511 * CreateStatusWindowW [COMCTL32.@]
513 * Creates a status bar control
516 * style [I] window style
517 * text [I] pointer to the window text
518 * parent [I] handle to the parent window
519 * wid [I] control id of the status bar
522 * Success: handle to the status window
527 CreateStatusWindowW (LONG style, LPCWSTR text, HWND parent, UINT wid)
529 return CreateWindowW(STATUSCLASSNAMEW, text, style,
530 CW_USEDEFAULT, CW_USEDEFAULT,
531 CW_USEDEFAULT, CW_USEDEFAULT,
532 parent, (HMENU)wid, 0, 0);
536 /***********************************************************************
537 * CreateUpDownControl [COMCTL32.16]
539 * Creates an up-down control
542 * style [I] window styles
543 * x [I] horizontal position of the control
544 * y [I] vertical position of the control
545 * cx [I] with of the control
546 * cy [I] height of the control
547 * parent [I] handle to the parent window
548 * id [I] the control's identifier
549 * inst [I] handle to the application's module instance
550 * buddy [I] handle to the buddy window, can be NULL
551 * maxVal [I] upper limit of the control
552 * minVal [I] lower limit of the control
553 * curVal [I] current value of the control
556 * Success: handle to the updown control
561 CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
562 HWND parent, INT id, HINSTANCE inst,
563 HWND buddy, INT maxVal, INT minVal, INT curVal)
566 CreateWindowW (UPDOWN_CLASSW, 0, style, x, y, cx, cy,
567 parent, (HMENU)id, inst, 0);
569 SendMessageW (hUD, UDM_SETBUDDY, (WPARAM)buddy, 0);
570 SendMessageW (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));
571 SendMessageW (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));
578 /***********************************************************************
579 * InitCommonControls [COMCTL32.17]
581 * Registers the common controls.
590 * This function is just a dummy.
591 * The Win95 controls are registered at the DLL's initialization.
592 * To register other controls InitCommonControlsEx() must be used.
596 InitCommonControls (void)
601 /***********************************************************************
602 * InitCommonControlsEx [COMCTL32.@]
604 * Registers the common controls.
607 * lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
614 * Only the additional common controls are registered by this function.
615 * The Win95 controls are registered at the DLL's initialization.
618 * implement the following control classes:
620 * ICC_STANDARD_CLASSES
624 InitCommonControlsEx (LPINITCOMMONCONTROLSEX lpInitCtrls)
631 if (lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
634 TRACE("(0x%08lx)\n", lpInitCtrls->dwICC);
636 for (cCount = 0; cCount < 32; cCount++) {
637 dwMask = 1 << cCount;
638 if (!(lpInitCtrls->dwICC & dwMask))
641 switch (lpInitCtrls->dwICC & dwMask) {
642 /* dummy initialization */
643 case ICC_ANIMATE_CLASS:
644 case ICC_BAR_CLASSES:
645 case ICC_LISTVIEW_CLASSES:
646 case ICC_TREEVIEW_CLASSES:
647 case ICC_TAB_CLASSES:
648 case ICC_UPDOWN_CLASS:
649 case ICC_PROGRESS_CLASS:
650 case ICC_HOTKEY_CLASS:
653 /* advanced classes - not included in Win95 */
654 case ICC_DATE_CLASSES:
655 MONTHCAL_Register ();
656 DATETIME_Register ();
659 case ICC_USEREX_CLASSES:
663 case ICC_COOL_CLASSES:
667 case ICC_INTERNET_CLASSES:
668 IPADDRESS_Register ();
671 case ICC_PAGESCROLLER_CLASS:
675 case ICC_NATIVEFNTCTL_CLASS:
676 NATIVEFONT_Register ();
684 FIXME("Unknown class! dwICC=0x%lX\n", dwMask);
693 /***********************************************************************
694 * CreateToolbarEx [COMCTL32.@]
696 * Creates a toolbar window.
714 * Success: handle to the tool bar control
719 CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
720 HINSTANCE hBMInst, UINT wBMID, LPCTBBUTTON lpButtons,
721 INT iNumButtons, INT dxButton, INT dyButton,
722 INT dxBitmap, INT dyBitmap, UINT uStructSize)
727 CreateWindowExW(0, TOOLBARCLASSNAMEW, NULL, style|WS_CHILD, 0,0,100,30,
728 hwnd, (HMENU)wID, COMCTL32_hModule, NULL);
732 SendMessageW (hwndTB, TB_BUTTONSTRUCTSIZE, (WPARAM)uStructSize, 0);
734 /* set bitmap and button size */
735 /*If CreateToolbarEx receives 0, windows sets default values*/
740 SendMessageW (hwndTB, TB_SETBITMAPSIZE, 0,
741 MAKELPARAM((WORD)dxBitmap, (WORD)dyBitmap));
747 SendMessageW (hwndTB, TB_SETBUTTONSIZE, 0,
748 MAKELPARAM((WORD)dxButton, (WORD)dyButton));
754 tbab.hInst = hBMInst;
757 SendMessageW (hwndTB, TB_ADDBITMAP, (WPARAM)nBitmaps, (LPARAM)&tbab);
761 SendMessageW (hwndTB, TB_ADDBUTTONSW,
762 (WPARAM)iNumButtons, (LPARAM)lpButtons);
769 /***********************************************************************
770 * CreateMappedBitmap [COMCTL32.8]
772 * Loads a bitmap resource using a colour map.
775 * hInstance [I] Handle to the module containing the bitmap.
776 * idBitmap [I] The bitmap resource ID.
777 * wFlags [I] CMB_MASKED for using bitmap as a mask or 0 for normal.
778 * lpColorMap [I] Colour information needed for the bitmap or NULL (uses system colours).
779 * iNumMaps [I] Number of COLORMAP's pointed to by lpColorMap.
782 * Success: handle to the new bitmap
787 CreateMappedBitmap (HINSTANCE hInstance, INT idBitmap, UINT wFlags,
788 LPCOLORMAP lpColorMap, INT iNumMaps)
792 LPBITMAPINFOHEADER lpBitmap, lpBitmapInfo;
793 UINT nSize, nColorTableSize, iColor;
794 RGBQUAD *pColorTable;
795 INT i, iMaps, nWidth, nHeight;
798 LPCOLORMAP sysColorMap;
800 COLORMAP internalColorMap[4] =
801 {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
803 /* initialize pointer to colortable and default color table */
806 sysColorMap = lpColorMap;
809 internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT);
810 internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW);
811 internalColorMap[2].to = GetSysColor (COLOR_BTNFACE);
812 internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT);
814 sysColorMap = (LPCOLORMAP)internalColorMap;
817 hRsrc = FindResourceW (hInstance, (LPWSTR)idBitmap, (LPWSTR)RT_BITMAP);
820 hglb = LoadResource (hInstance, hRsrc);
823 lpBitmap = (LPBITMAPINFOHEADER)LockResource (hglb);
824 if (lpBitmap == NULL)
827 if (lpBitmap->biSize >= sizeof(BITMAPINFOHEADER) && lpBitmap->biClrUsed)
828 nColorTableSize = lpBitmap->biClrUsed;
829 else if (lpBitmap->biBitCount <= 8)
830 nColorTableSize = (1 << lpBitmap->biBitCount);
833 nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
834 lpBitmapInfo = (LPBITMAPINFOHEADER)GlobalAlloc (GMEM_FIXED, nSize);
835 if (lpBitmapInfo == NULL)
837 RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);
839 pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo)+(UINT)lpBitmapInfo->biSize);
841 for (iColor = 0; iColor < nColorTableSize; iColor++) {
842 for (i = 0; i < iMaps; i++) {
843 cRef = RGB(pColorTable[iColor].rgbRed,
844 pColorTable[iColor].rgbGreen,
845 pColorTable[iColor].rgbBlue);
846 if ( cRef == sysColorMap[i].from) {
848 if (wFlags & CBS_MASKED) {
849 if (sysColorMap[i].to != COLOR_BTNTEXT)
850 pColorTable[iColor] = RGB(255, 255, 255);
854 pColorTable[iColor].rgbBlue = GetBValue(sysColorMap[i].to);
855 pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);
856 pColorTable[iColor].rgbRed = GetRValue(sysColorMap[i].to);
861 nWidth = (INT)lpBitmapInfo->biWidth;
862 nHeight = (INT)lpBitmapInfo->biHeight;
863 hdcScreen = GetDC (NULL);
864 hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
866 HDC hdcDst = CreateCompatibleDC (hdcScreen);
867 HBITMAP hbmOld = SelectObject (hdcDst, hbm);
868 LPBYTE lpBits = (LPBYTE)(lpBitmap + 1);
869 lpBits += nColorTableSize * sizeof(RGBQUAD);
870 StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
871 lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
873 SelectObject (hdcDst, hbmOld);
876 ReleaseDC (NULL, hdcScreen);
877 GlobalFree ((HGLOBAL)lpBitmapInfo);
884 /***********************************************************************
885 * CreateToolbar [COMCTL32.7]
887 * Creates a toolbar control.
900 * Success: handle to the tool bar control
904 * Do not use this functions anymore. Use CreateToolbarEx instead.
908 CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
909 HINSTANCE hBMInst, UINT wBMID,
910 LPCTBBUTTON lpButtons,INT iNumButtons)
912 return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
913 hBMInst, wBMID, lpButtons,
914 iNumButtons, 0, 0, 0, 0, CCSIZEOF_STRUCT(TBBUTTON, dwData));
918 /***********************************************************************
919 * DllGetVersion [COMCTL32.@]
921 * Retrieves version information of the 'COMCTL32.DLL'
924 * pdvi [O] pointer to version information structure.
928 * Failure: E_INVALIDARG
931 * Returns version of a comctl32.dll from IE4.01 SP1.
935 COMCTL32_DllGetVersion (DLLVERSIONINFO *pdvi)
937 if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
938 WARN("wrong DLLVERSIONINFO size from app\n");
942 pdvi->dwMajorVersion = COMCTL32_VERSION;
943 pdvi->dwMinorVersion = COMCTL32_VERSION_MINOR;
944 pdvi->dwBuildNumber = 2919;
945 pdvi->dwPlatformID = 6304;
947 TRACE("%lu.%lu.%lu.%lu\n",
948 pdvi->dwMajorVersion, pdvi->dwMinorVersion,
949 pdvi->dwBuildNumber, pdvi->dwPlatformID);
954 /***********************************************************************
955 * DllInstall (COMCTL32.@)
957 * Installs the ComCtl32 DLL.
961 * Failure: A HRESULT error
963 HRESULT WINAPI COMCTL32_DllInstall(BOOL bInstall, LPCWSTR cmdline)
965 FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
966 debugstr_w(cmdline));
971 /***********************************************************************
972 * _TrackMouseEvent [COMCTL32.@]
974 * Requests notification of mouse events
976 * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
977 * to the hwnd specified in the ptme structure. After the event message
978 * is posted to the hwnd, the entry in the queue is removed.
980 * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
981 * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
982 * immediately and the TME_LEAVE flag being ignored.
985 * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
991 * IMPLEMENTATION moved to USER32.TrackMouseEvent
996 _TrackMouseEvent (TRACKMOUSEEVENT *ptme)
998 return TrackMouseEvent (ptme);
1001 /*************************************************************************
1002 * GetMUILanguage [COMCTL32.@]
1004 * Returns the user interface language in use by the current process.
1007 * Language ID in use by the current process.
1009 LANGID WINAPI GetMUILanguage (VOID)
1011 return COMCTL32_uiLang;
1015 /*************************************************************************
1016 * InitMUILanguage [COMCTL32.@]
1018 * Sets the user interface language to be used by the current process.
1023 VOID WINAPI InitMUILanguage (LANGID uiLang)
1025 COMCTL32_uiLang = uiLang;
1029 /***********************************************************************
1030 * SetWindowSubclass [COMCTL32.410]
1032 * Starts a window subclass
1035 * hWnd [in] handle to window subclass.
1036 * pfnSubclass [in] Pointer to new window procedure.
1037 * uIDSubclass [in] Unique identifier of sublass together with pfnSubclass.
1038 * dwRef [in] Reference data to pass to window procedure.
1045 * If an application manually subclasses a window after subclassing it with
1046 * this API and then with this API again, then none of the previous
1047 * subclasses get called or the origional window procedure.
1050 BOOL WINAPI SetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
1051 UINT_PTR uIDSubclass, DWORD_PTR dwRef)
1053 LPSUBCLASS_INFO stack;
1054 LPSUBCLASSPROCS proc;
1056 TRACE ("(%p, %p, %x, %lx)\n", hWnd, pfnSubclass, uIDSubclass, dwRef);
1058 /* Since the window procedure that we set here has two additional arguments,
1059 * we can't simply set it as the new window procedure of the window. So we
1060 * set our own window procedure and then calculate the other two arguments
1063 /* See if we have been called for this window */
1064 stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
1066 /* allocate stack */
1067 stack = Alloc (sizeof(SUBCLASS_INFO));
1069 ERR ("Failed to allocate our Subclassing stack\n");
1072 SetPropW (hWnd, COMCTL32_wSubclass, (HANDLE)stack);
1074 /* set window procedure to our own and save the current one */
1075 if (IsWindowUnicode (hWnd))
1076 stack->origproc = (WNDPROC)SetWindowLongPtrW (hWnd, GWLP_WNDPROC,
1077 (DWORD_PTR)COMCTL32_SubclassProc);
1079 stack->origproc = (WNDPROC)SetWindowLongPtrA (hWnd, GWLP_WNDPROC,
1080 (DWORD_PTR)COMCTL32_SubclassProc);
1083 /* Check to see if we have called this function with the same uIDSubClass
1084 * and pfnSubclass */
1085 proc = stack->SubclassProcs;
1087 if ((proc->id == uIDSubclass) &&
1088 (proc->subproc == pfnSubclass)) {
1096 proc = Alloc(sizeof(SUBCLASSPROCS));
1098 ERR ("Failed to allocate subclass entry in stack\n");
1099 if (IsWindowUnicode (hWnd))
1100 SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1102 SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1104 RemovePropW( hWnd, COMCTL32_wSubclass );
1108 proc->subproc = pfnSubclass;
1110 proc->id = uIDSubclass;
1111 proc->next = stack->SubclassProcs;
1112 stack->SubclassProcs = proc;
1118 /***********************************************************************
1119 * GetWindowSubclass [COMCTL32.411]
1121 * Gets the Reference data from a subclass.
1124 * hWnd [in] Handle to window which were subclassing
1125 * pfnSubclass [in] Pointer to the subclass procedure
1126 * uID [in] Unique indentifier of the subclassing procedure
1127 * pdwRef [out] Pointer to the reference data
1134 BOOL WINAPI GetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
1135 UINT_PTR uID, DWORD_PTR *pdwRef)
1137 LPSUBCLASS_INFO stack;
1138 LPSUBCLASSPROCS proc;
1140 TRACE ("(%p, %p, %x, %p)\n", hWnd, pfnSubclass, uID, pdwRef);
1142 /* See if we have been called for this window */
1143 stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
1147 proc = stack->SubclassProcs;
1149 if ((proc->id == uID) &&
1150 (proc->subproc == pfnSubclass)) {
1151 *pdwRef = proc->ref;
1161 /***********************************************************************
1162 * RemoveWindowSubclass [COMCTL32.412]
1164 * Removes a window subclass.
1167 * hWnd [in] Handle to the window were subclassing
1168 * pfnSubclass [in] Pointer to the subclass procedure
1169 * uID [in] Unique identifier of this subclass
1176 BOOL WINAPI RemoveWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR uID)
1178 LPSUBCLASS_INFO stack;
1179 LPSUBCLASSPROCS prevproc = NULL;
1180 LPSUBCLASSPROCS proc;
1183 TRACE ("(%p, %p, %x)\n", hWnd, pfnSubclass, uID);
1185 /* Find the Subclass to remove */
1186 stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
1190 proc = stack->SubclassProcs;
1192 if ((proc->id == uID) &&
1193 (proc->subproc == pfnSubclass)) {
1196 stack->SubclassProcs = proc->next;
1198 prevproc->next = proc->next;
1200 if (stack->stackpos == proc)
1201 stack->stackpos = stack->stackpos->next;
1211 if (!stack->SubclassProcs && !stack->running) {
1212 TRACE("Last Subclass removed, cleaning up\n");
1213 /* clean up our heap and reset the origional window procedure */
1214 if (IsWindowUnicode (hWnd))
1215 SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1217 SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1219 RemovePropW( hWnd, COMCTL32_wSubclass );
1225 /***********************************************************************
1226 * COMCTL32_SubclassProc (internal)
1228 * Window procedure for all subclassed windows.
1229 * Saves the current subclassing stack position to support nested messages
1231 LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1233 LPSUBCLASS_INFO stack;
1234 LPSUBCLASSPROCS proc;
1237 TRACE ("(%p, 0x%08x, 0x%08x, 0x%08lx)\n", hWnd, uMsg, wParam, lParam);
1239 stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
1241 ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
1245 /* Save our old stackpos to properly handle nested messages */
1246 proc = stack->stackpos;
1247 stack->stackpos = stack->SubclassProcs;
1249 ret = DefSubclassProc(hWnd, uMsg, wParam, lParam);
1251 stack->stackpos = proc;
1253 if (!stack->SubclassProcs && !stack->running) {
1254 TRACE("Last Subclass removed, cleaning up\n");
1255 /* clean up our heap and reset the origional window procedure */
1256 if (IsWindowUnicode (hWnd))
1257 SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1259 SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1261 RemovePropW( hWnd, COMCTL32_wSubclass );
1266 /***********************************************************************
1267 * DefSubclassProc [COMCTL32.413]
1269 * Calls the next window procedure (ie. the one before this subclass)
1272 * hWnd [in] The window that we're subclassing
1274 * wParam [in] WPARAM
1275 * lParam [in] LPARAM
1282 LRESULT WINAPI DefSubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1284 LPSUBCLASS_INFO stack;
1287 TRACE ("(%p, 0x%08x, 0x%08x, 0x%08lx)\n", hWnd, uMsg, wParam, lParam);
1289 /* retrieve our little stack from the Properties */
1290 stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
1292 ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
1296 /* If we are at the end of stack then we have to call the original
1297 * window procedure */
1298 if (!stack->stackpos) {
1299 if (IsWindowUnicode (hWnd))
1300 ret = CallWindowProcW (stack->origproc, hWnd, uMsg, wParam, lParam);
1302 ret = CallWindowProcA (stack->origproc, hWnd, uMsg, wParam, lParam);
1304 LPSUBCLASSPROCS proc = stack->stackpos;
1305 stack->stackpos = stack->stackpos->next;
1306 /* call the Subclass procedure from the stack */
1307 ret = proc->subproc (hWnd, uMsg, wParam, lParam,
1308 proc->id, proc->ref);
1315 /***********************************************************************
1316 * COMCTL32_CreateToolTip [NOT AN API]
1318 * Creates a tooltip for the control specified in hwnd and does all
1319 * necessary setup and notifications.
1322 * hwndOwner [I] Handle to the window that will own the tool tip.
1325 * Success: Handle of tool tip window.
1330 COMCTL32_CreateToolTip(HWND hwndOwner)
1334 hwndToolTip = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, 0,
1335 CW_USEDEFAULT, CW_USEDEFAULT,
1336 CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner,
1339 /* Send NM_TOOLTIPSCREATED notification */
1342 NMTOOLTIPSCREATED nmttc;
1343 /* true owner can be different if hwndOwner is a child window */
1344 HWND hwndTrueOwner = GetWindow(hwndToolTip, GW_OWNER);
1345 nmttc.hdr.hwndFrom = hwndTrueOwner;
1346 nmttc.hdr.idFrom = GetWindowLongPtrW(hwndTrueOwner, GWLP_ID);
1347 nmttc.hdr.code = NM_TOOLTIPSCREATED;
1348 nmttc.hwndToolTips = hwndToolTip;
1350 SendMessageW(GetParent(hwndTrueOwner), WM_NOTIFY,
1351 (WPARAM)GetWindowLongPtrW(hwndTrueOwner, GWLP_ID),
1359 /***********************************************************************
1360 * COMCTL32_RefreshSysColors [NOT AN API]
1362 * Invoked on any control recognizing a WM_SYSCOLORCHANGE message to
1363 * refresh the color values in the color structure
1373 COMCTL32_RefreshSysColors(void)
1375 comctl32_color.clrBtnHighlight = GetSysColor (COLOR_BTNHIGHLIGHT);
1376 comctl32_color.clrBtnShadow = GetSysColor (COLOR_BTNSHADOW);
1377 comctl32_color.clrBtnText = GetSysColor (COLOR_BTNTEXT);
1378 comctl32_color.clrBtnFace = GetSysColor (COLOR_BTNFACE);
1379 comctl32_color.clrHighlight = GetSysColor (COLOR_HIGHLIGHT);
1380 comctl32_color.clrHighlightText = GetSysColor (COLOR_HIGHLIGHTTEXT);
1381 comctl32_color.clr3dHilight = GetSysColor (COLOR_3DHILIGHT);
1382 comctl32_color.clr3dShadow = GetSysColor (COLOR_3DSHADOW);
1383 comctl32_color.clr3dDkShadow = GetSysColor (COLOR_3DDKSHADOW);
1384 comctl32_color.clr3dFace = GetSysColor (COLOR_3DFACE);
1385 comctl32_color.clrWindow = GetSysColor (COLOR_WINDOW);
1386 comctl32_color.clrWindowText = GetSysColor (COLOR_WINDOWTEXT);
1387 comctl32_color.clrGrayText = GetSysColor (COLOR_GRAYTEXT);
1388 comctl32_color.clrActiveCaption = GetSysColor (COLOR_ACTIVECAPTION);
1389 comctl32_color.clrInfoBk = GetSysColor (COLOR_INFOBK);
1390 comctl32_color.clrInfoText = GetSysColor (COLOR_INFOTEXT);
1393 /***********************************************************************
1394 * COMCTL32_DrawInsertMark [NOT AN API]
1396 * Draws an insertion mark (which looks similar to an 'I').
1399 * hDC [I] Device context to draw onto.
1400 * lpRect [I] Co-ordinates of insertion mark.
1401 * clrInsertMark [I] Colour of the insertion mark.
1402 * bHorizontal [I] True if insert mark should be drawn horizontally,
1403 * vertical otherwise.
1409 * Draws up to but not including the bottom co-ordinate when drawing
1410 * vertically or the right co-ordinate when horizontal.
1412 void COMCTL32_DrawInsertMark(HDC hDC, const RECT *lpRect, COLORREF clrInsertMark, BOOL bHorizontal)
1414 HPEN hPen = CreatePen(PS_SOLID, 1, clrInsertMark);
1416 static const DWORD adwPolyPoints[] = {4,4,4};
1417 LONG lCentre = (bHorizontal ?
1418 lpRect->top + (lpRect->bottom - lpRect->top)/2 :
1419 lpRect->left + (lpRect->right - lpRect->left)/2);
1420 LONG l1 = (bHorizontal ? lpRect->left : lpRect->top);
1421 LONG l2 = (bHorizontal ? lpRect->right : lpRect->bottom);
1422 const POINT aptInsertMark[] =
1424 /* top (V) or left (H) arrow */
1428 {lCentre + 1, l1 + 2},
1432 {lCentre + 1, l1 - 1},
1433 {lCentre + 1, l2 - 2},
1434 /* bottom (V) or right (H) arrow */
1436 {lCentre - 2, l2 - 1},
1437 {lCentre + 3, l2 - 1},
1438 {lCentre + 1, l2 - 3},
1440 hOldPen = SelectObject(hDC, hPen);
1441 PolyPolyline(hDC, aptInsertMark, adwPolyPoints, sizeof(adwPolyPoints)/sizeof(adwPolyPoints[0]));
1442 SelectObject(hDC, hOldPen);
1446 /***********************************************************************
1447 * MirrorIcon [COMCTL32.414]
1449 * Mirrors an icon so that it will appear correctly on a mirrored DC.
1452 * phicon1 [I/O] Icon.
1453 * phicon2 [I/O] Icon.
1459 BOOL WINAPI MirrorIcon(HICON *phicon1, HICON *phicon2)
1461 FIXME("(%p, %p): stub\n", phicon1, phicon2);
1465 static inline int IsDelimiter(WCHAR c)
1478 static int CALLBACK PathWordBreakProc(LPWSTR lpch, int ichCurrent, int cch, int code)
1480 if (code == WB_ISDELIMITER)
1481 return IsDelimiter(lpch[ichCurrent]);
1484 int dir = (code == WB_LEFT) ? -1 : 1;
1485 for(; 0 <= ichCurrent && ichCurrent < cch; ichCurrent += dir)
1486 if (IsDelimiter(lpch[ichCurrent])) return ichCurrent;
1491 /***********************************************************************
1492 * SetPathWordBreakProc [COMCTL32.384]
1494 * Sets the word break procedure for an edit control to one that understands
1495 * paths so that the user can jump over directories.
1498 * hwnd [I] Handle to edit control.
1499 * bSet [I] If this is TRUE then the word break proc is set, otherwise it is removed.
1502 * Result from EM_SETWORDBREAKPROC message.
1504 LRESULT WINAPI SetPathWordBreakProc(HWND hwnd, BOOL bSet)
1506 return SendMessageW(hwnd, EM_SETWORDBREAKPROC, 0,
1507 (LPARAM)(bSet ? PathWordBreakProc : NULL));