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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 * -- finish NOTES for MenuHelp, GetEffectiveClientRect and GetStatusTextW
33 * -- FIXMEs + BUGS (search for them)
36 * -- ICC_ANIMATE_CLASS
41 * -- ICC_INTERNET_CLASSES
43 * -- ICC_LISTVIEW_CLASSES
44 * -- ICC_NATIVEFNTCTL_CLASS
45 * -- ICC_PAGESCROLLER_CLASS
46 * -- ICC_PROGRESS_CLASS
47 * -- ICC_STANDARD_CLASSES (not yet implemented)
49 * -- ICC_TREEVIEW_CLASSES
51 * -- ICC_USEREX_CLASSES
52 * -- ICC_WIN95_CLASSES
67 #define NO_SHLWAPI_STREAM
70 #include "wine/debug.h"
72 WINE_DEFAULT_DEBUG_CHANNEL(commctrl);
75 static LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
77 static LPWSTR COMCTL32_wSubclass = NULL;
78 HMODULE COMCTL32_hModule = 0;
79 static LANGID COMCTL32_uiLang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
80 HBRUSH COMCTL32_hPattern55AABrush = NULL;
81 COMCTL32_SysColor comctl32_color;
83 static HBITMAP COMCTL32_hPattern55AABitmap = NULL;
85 static const WORD wPattern55AA[] =
87 0x5555, 0xaaaa, 0x5555, 0xaaaa,
88 0x5555, 0xaaaa, 0x5555, 0xaaaa
91 static const WCHAR strCC32SubclassInfo[] = {
92 '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] reserved, must be NULL
111 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
113 TRACE("%p,%x,%p\n", hinstDLL, fdwReason, lpvReserved);
116 case DLL_PROCESS_ATTACH:
117 DisableThreadLibraryCalls(hinstDLL);
119 COMCTL32_hModule = hinstDLL;
121 /* add global subclassing atom (used by 'tooltip' and 'updown') */
122 COMCTL32_wSubclass = (LPWSTR)(DWORD_PTR)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 /* like comctl32 5.82+ register all the common control classes */
135 DATETIME_Register ();
139 IPADDRESS_Register ();
140 LISTVIEW_Register ();
141 MONTHCAL_Register ();
142 NATIVEFONT_Register ();
144 PROGRESS_Register ();
150 TOOLTIPS_Register ();
151 TRACKBAR_Register ();
152 TREEVIEW_Register ();
155 /* subclass user32 controls */
156 THEMING_Initialize ();
159 case DLL_PROCESS_DETACH:
160 /* clean up subclassing */
161 THEMING_Uninitialize();
163 /* unregister all common control classes */
164 ANIMATE_Unregister ();
165 COMBOEX_Unregister ();
166 DATETIME_Unregister ();
167 FLATSB_Unregister ();
168 HEADER_Unregister ();
169 HOTKEY_Unregister ();
170 IPADDRESS_Unregister ();
171 LISTVIEW_Unregister ();
172 MONTHCAL_Unregister ();
173 NATIVEFONT_Unregister ();
175 PROGRESS_Unregister ();
177 STATUS_Unregister ();
178 SYSLINK_Unregister ();
180 TOOLBAR_Unregister ();
181 TOOLTIPS_Unregister ();
182 TRACKBAR_Unregister ();
183 TREEVIEW_Unregister ();
184 UPDOWN_Unregister ();
186 /* delete local pattern brush */
187 DeleteObject (COMCTL32_hPattern55AABrush);
188 COMCTL32_hPattern55AABrush = NULL;
189 DeleteObject (COMCTL32_hPattern55AABitmap);
190 COMCTL32_hPattern55AABitmap = NULL;
192 /* delete global subclassing atom */
193 GlobalDeleteAtom (LOWORD(COMCTL32_wSubclass));
194 TRACE("Subclassing atom deleted: %p\n", COMCTL32_wSubclass);
195 COMCTL32_wSubclass = NULL;
203 /***********************************************************************
204 * MenuHelp [COMCTL32.2]
206 * Handles the setting of status bar help messages when the user
207 * selects menu items.
210 * uMsg [I] message (WM_MENUSELECT) (see NOTES)
211 * wParam [I] wParam of the message uMsg
212 * lParam [I] lParam of the message uMsg
213 * hMainMenu [I] handle to the application's main menu
214 * hInst [I] handle to the module that contains string resources
215 * hwndStatus [I] handle to the status bar window
216 * lpwIDs [I] pointer to an array of integers (see NOTES)
222 * The official documentation is incomplete!
223 * This is the correct documentation:
226 * MenuHelp() does NOT handle WM_COMMAND messages! It only handles
227 * WM_MENUSELECT messages.
230 * (will be written ...)
234 MenuHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu,
235 HINSTANCE hInst, HWND hwndStatus, UINT* lpwIDs)
239 if (!IsWindow (hwndStatus))
244 TRACE("WM_MENUSELECT wParam=0x%lX lParam=0x%lX\n",
247 if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {
248 /* menu was closed */
249 TRACE("menu was closed!\n");
250 SendMessageW (hwndStatus, SB_SIMPLE, FALSE, 0);
253 /* menu item was selected */
254 if (HIWORD(wParam) & MF_POPUP)
255 uMenuID = *(lpwIDs+1);
257 uMenuID = (UINT)LOWORD(wParam);
258 TRACE("uMenuID = %u\n", uMenuID);
263 if (!LoadStringW (hInst, uMenuID, szText, sizeof(szText)/sizeof(szText[0])))
266 SendMessageW (hwndStatus, SB_SETTEXTW,
267 255 | SBT_NOBORDERS, (LPARAM)szText);
268 SendMessageW (hwndStatus, SB_SIMPLE, TRUE, 0);
274 TRACE("WM_COMMAND wParam=0x%lX lParam=0x%lX\n",
276 /* WM_COMMAND is not invalid since it is documented
277 * in the windows api reference. So don't output
278 * any FIXME for WM_COMMAND
280 WARN("We don't care about the WM_COMMAND\n");
284 FIXME("Invalid Message 0x%x!\n", uMsg);
290 /***********************************************************************
291 * ShowHideMenuCtl [COMCTL32.3]
293 * Shows or hides controls and updates the corresponding menu item.
296 * hwnd [I] handle to the client window.
297 * uFlags [I] menu command id.
298 * lpInfo [I] pointer to an array of integers. (See NOTES.)
305 * The official documentation is incomplete!
306 * This is the correct documentation:
309 * Handle to the window that contains the menu and controls.
312 * Identifier of the menu item to receive or lose a check mark.
315 * The array of integers contains pairs of values. BOTH values of
316 * the first pair must be the handles to the application's main menu.
317 * Each subsequent pair consists of a menu id and control id.
321 ShowHideMenuCtl (HWND hwnd, UINT_PTR uFlags, LPINT lpInfo)
325 TRACE("%p, %lx, %p\n", hwnd, uFlags, lpInfo);
330 if (!(lpInfo[0]) || !(lpInfo[1]))
333 /* search for control */
334 lpMenuId = &lpInfo[2];
335 while (*lpMenuId != uFlags)
338 if (GetMenuState ((HMENU)(DWORD_PTR)lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) {
339 /* uncheck menu item */
340 CheckMenuItem ((HMENU)(DWORD_PTR)lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_UNCHECKED);
344 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
348 /* check menu item */
349 CheckMenuItem ((HMENU)(DWORD_PTR)lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_CHECKED);
353 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
361 /***********************************************************************
362 * GetEffectiveClientRect [COMCTL32.4]
364 * Calculates the coordinates of a rectangle in the client area.
367 * hwnd [I] handle to the client window.
368 * lpRect [O] pointer to the rectangle of the client window
369 * lpInfo [I] pointer to an array of integers (see NOTES)
375 * The official documentation is incomplete!
376 * This is the correct documentation:
379 * (will be written ...)
383 GetEffectiveClientRect (HWND hwnd, LPRECT lpRect, const INT *lpInfo)
389 TRACE("(%p %p %p)\n",
390 hwnd, lpRect, lpInfo);
392 GetClientRect (hwnd, lpRect);
400 hwndCtrl = GetDlgItem (hwnd, *lpRun);
401 if (GetWindowLongW (hwndCtrl, GWL_STYLE) & WS_VISIBLE) {
402 TRACE("control id 0x%x\n", *lpRun);
403 GetWindowRect (hwndCtrl, &rcCtrl);
404 MapWindowPoints (NULL, hwnd, (LPPOINT)&rcCtrl, 2);
405 SubtractRect (lpRect, lpRect, &rcCtrl);
412 /***********************************************************************
413 * DrawStatusTextW [COMCTL32.@]
415 * Draws text with borders, like in a status bar.
418 * hdc [I] handle to the window's display context
419 * lprc [I] pointer to a rectangle
420 * text [I] pointer to the text
421 * style [I] drawing style
427 * The style variable can have one of the following values:
428 * (will be written ...)
431 void WINAPI DrawStatusTextW (HDC hdc, LPCRECT lprc, LPCWSTR text, UINT style)
434 UINT border = BDR_SUNKENOUTER;
436 if (style & SBT_POPOUT)
437 border = BDR_RAISEDOUTER;
438 else if (style & SBT_NOBORDERS)
441 DrawEdge (hdc, &r, border, BF_RECT|BF_ADJUST);
445 int oldbkmode = SetBkMode (hdc, TRANSPARENT);
446 UINT align = DT_LEFT;
449 if (style & SBT_RTLREADING)
450 FIXME("Unsupported RTL style!\n");
455 DrawTextW (hdc, text - strCnt, strCnt, &r, align|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX);
458 if (align==DT_RIGHT) {
461 align = (align==DT_LEFT ? DT_CENTER : DT_RIGHT);
467 if (strCnt) DrawTextW (hdc, text - strCnt, -1, &r, align|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX);
468 SetBkMode(hdc, oldbkmode);
473 /***********************************************************************
474 * DrawStatusText [COMCTL32.@]
475 * DrawStatusTextA [COMCTL32.5]
477 * Draws text with borders, like in a status bar.
480 * hdc [I] handle to the window's display context
481 * lprc [I] pointer to a rectangle
482 * text [I] pointer to the text
483 * style [I] drawing style
489 void WINAPI DrawStatusTextA (HDC hdc, LPCRECT lprc, LPCSTR text, UINT style)
495 if ( (len = MultiByteToWideChar( CP_ACP, 0, text, -1, NULL, 0 )) ) {
496 if ( (textW = Alloc( len * sizeof(WCHAR) )) )
497 MultiByteToWideChar( CP_ACP, 0, text, -1, textW, len );
500 DrawStatusTextW( hdc, lprc, textW, style );
505 /***********************************************************************
506 * CreateStatusWindow [COMCTL32.@]
507 * CreateStatusWindowA [COMCTL32.6]
509 * Creates a status bar
512 * style [I] window style
513 * text [I] pointer to the window text
514 * parent [I] handle to the parent window
515 * wid [I] control id of the status bar
518 * Success: handle to the status window
523 CreateStatusWindowA (LONG style, LPCSTR text, HWND parent, UINT wid)
525 return CreateWindowA(STATUSCLASSNAMEA, text, style,
526 CW_USEDEFAULT, CW_USEDEFAULT,
527 CW_USEDEFAULT, CW_USEDEFAULT,
528 parent, (HMENU)(DWORD_PTR)wid, 0, 0);
532 /***********************************************************************
533 * CreateStatusWindowW [COMCTL32.@]
535 * Creates a status bar control
538 * style [I] window style
539 * text [I] pointer to the window text
540 * parent [I] handle to the parent window
541 * wid [I] control id of the status bar
544 * Success: handle to the status window
549 CreateStatusWindowW (LONG style, LPCWSTR text, HWND parent, UINT wid)
551 return CreateWindowW(STATUSCLASSNAMEW, text, style,
552 CW_USEDEFAULT, CW_USEDEFAULT,
553 CW_USEDEFAULT, CW_USEDEFAULT,
554 parent, (HMENU)(DWORD_PTR)wid, 0, 0);
558 /***********************************************************************
559 * CreateUpDownControl [COMCTL32.16]
561 * Creates an up-down control
564 * style [I] window styles
565 * x [I] horizontal position of the control
566 * y [I] vertical position of the control
567 * cx [I] with of the control
568 * cy [I] height of the control
569 * parent [I] handle to the parent window
570 * id [I] the control's identifier
571 * inst [I] handle to the application's module instance
572 * buddy [I] handle to the buddy window, can be NULL
573 * maxVal [I] upper limit of the control
574 * minVal [I] lower limit of the control
575 * curVal [I] current value of the control
578 * Success: handle to the updown control
583 CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
584 HWND parent, INT id, HINSTANCE inst,
585 HWND buddy, INT maxVal, INT minVal, INT curVal)
588 CreateWindowW (UPDOWN_CLASSW, 0, style, x, y, cx, cy,
589 parent, (HMENU)(DWORD_PTR)id, inst, 0);
591 SendMessageW (hUD, UDM_SETBUDDY, (WPARAM)buddy, 0);
592 SendMessageW (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));
593 SendMessageW (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));
600 /***********************************************************************
601 * InitCommonControls [COMCTL32.17]
603 * Registers the common controls.
612 * This function is just a dummy - all the controls are registered at
613 * the DLL initialization time. See InitCommonContolsEx for details.
617 InitCommonControls (void)
622 /***********************************************************************
623 * InitCommonControlsEx [COMCTL32.@]
625 * Registers the common controls.
628 * lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
635 * Probably all versions of comctl32 initializes the Win95 controls in DllMain
636 * during DLL initialization. Starting from comctl32 v5.82 all the controls
637 * are initialized there. We follow this behaviour and this function is just
640 * Note: when writing programs under Windows, if you don't call any function
641 * from comctl32 the linker may not link this DLL. If InitCommonControlsEx
642 * was the only comctl32 function you were calling and you remove it you may
643 * have a false impression that InitCommonControlsEx actually did something.
647 InitCommonControlsEx (const INITCOMMONCONTROLSEX *lpInitCtrls)
649 if (!lpInitCtrls || lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
652 TRACE("(0x%08x)\n", lpInitCtrls->dwICC);
657 /***********************************************************************
658 * CreateToolbarEx [COMCTL32.@]
660 * Creates a toolbar window.
678 * Success: handle to the tool bar control
683 CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
684 HINSTANCE hBMInst, UINT_PTR wBMID, LPCTBBUTTON lpButtons,
685 INT iNumButtons, INT dxButton, INT dyButton,
686 INT dxBitmap, INT dyBitmap, UINT uStructSize)
691 CreateWindowExW(0, TOOLBARCLASSNAMEW, NULL, style|WS_CHILD, 0,0,100,30,
692 hwnd, (HMENU)(DWORD_PTR)wID, COMCTL32_hModule, NULL);
696 SendMessageW (hwndTB, TB_BUTTONSTRUCTSIZE, uStructSize, 0);
698 /* set bitmap and button size */
699 /*If CreateToolbarEx receives 0, windows sets default values*/
704 if (dxBitmap == 0 || dyBitmap == 0)
705 dxBitmap = dyBitmap = 16;
706 SendMessageW(hwndTB, TB_SETBITMAPSIZE, 0, MAKELPARAM(dxBitmap, dyBitmap));
712 /* TB_SETBUTTONSIZE -> TB_SETBITMAPSIZE bug introduced for Windows compatibility */
713 if (dxButton != 0 && dyButton != 0)
714 SendMessageW(hwndTB, TB_SETBITMAPSIZE, 0, MAKELPARAM(dxButton, dyButton));
718 if (nBitmaps > 0 || hBMInst == HINST_COMMCTRL)
720 tbab.hInst = hBMInst;
723 SendMessageW (hwndTB, TB_ADDBITMAP, nBitmaps, (LPARAM)&tbab);
727 SendMessageW (hwndTB, TB_ADDBUTTONSW, iNumButtons, (LPARAM)lpButtons);
734 /***********************************************************************
735 * CreateMappedBitmap [COMCTL32.8]
737 * Loads a bitmap resource using a colour map.
740 * hInstance [I] Handle to the module containing the bitmap.
741 * idBitmap [I] The bitmap resource ID.
742 * wFlags [I] CMB_MASKED for using bitmap as a mask or 0 for normal.
743 * lpColorMap [I] Colour information needed for the bitmap or NULL (uses system colours).
744 * iNumMaps [I] Number of COLORMAP's pointed to by lpColorMap.
747 * Success: handle to the new bitmap
752 CreateMappedBitmap (HINSTANCE hInstance, INT_PTR idBitmap, UINT wFlags,
753 LPCOLORMAP lpColorMap, INT iNumMaps)
757 const BITMAPINFOHEADER *lpBitmap;
758 LPBITMAPINFOHEADER lpBitmapInfo;
759 UINT nSize, nColorTableSize, iColor;
760 RGBQUAD *pColorTable;
761 INT i, iMaps, nWidth, nHeight;
764 LPCOLORMAP sysColorMap;
766 COLORMAP internalColorMap[4] =
767 {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
769 /* initialize pointer to colortable and default color table */
772 sysColorMap = lpColorMap;
775 internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT);
776 internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW);
777 internalColorMap[2].to = GetSysColor (COLOR_BTNFACE);
778 internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT);
780 sysColorMap = internalColorMap;
783 hRsrc = FindResourceW (hInstance, (LPWSTR)idBitmap, (LPWSTR)RT_BITMAP);
786 hglb = LoadResource (hInstance, hRsrc);
789 lpBitmap = LockResource (hglb);
790 if (lpBitmap == NULL)
793 if (lpBitmap->biSize >= sizeof(BITMAPINFOHEADER) && lpBitmap->biClrUsed)
794 nColorTableSize = lpBitmap->biClrUsed;
795 else if (lpBitmap->biBitCount <= 8)
796 nColorTableSize = (1 << lpBitmap->biBitCount);
799 nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
800 lpBitmapInfo = GlobalAlloc (GMEM_FIXED, nSize);
801 if (lpBitmapInfo == NULL)
803 RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);
805 pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo) + lpBitmapInfo->biSize);
807 for (iColor = 0; iColor < nColorTableSize; iColor++) {
808 for (i = 0; i < iMaps; i++) {
809 cRef = RGB(pColorTable[iColor].rgbRed,
810 pColorTable[iColor].rgbGreen,
811 pColorTable[iColor].rgbBlue);
812 if ( cRef == sysColorMap[i].from) {
814 if (wFlags & CBS_MASKED) {
815 if (sysColorMap[i].to != COLOR_BTNTEXT)
816 pColorTable[iColor] = RGB(255, 255, 255);
820 pColorTable[iColor].rgbBlue = GetBValue(sysColorMap[i].to);
821 pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);
822 pColorTable[iColor].rgbRed = GetRValue(sysColorMap[i].to);
827 nWidth = lpBitmapInfo->biWidth;
828 nHeight = lpBitmapInfo->biHeight;
829 hdcScreen = GetDC (NULL);
830 hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
832 HDC hdcDst = CreateCompatibleDC (hdcScreen);
833 HBITMAP hbmOld = SelectObject (hdcDst, hbm);
834 const BYTE *lpBits = (const BYTE *)lpBitmap + nSize;
835 StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
836 lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
838 SelectObject (hdcDst, hbmOld);
841 ReleaseDC (NULL, hdcScreen);
842 GlobalFree (lpBitmapInfo);
849 /***********************************************************************
850 * CreateToolbar [COMCTL32.7]
852 * Creates a toolbar control.
865 * Success: handle to the tool bar control
869 * Do not use this functions anymore. Use CreateToolbarEx instead.
873 CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
874 HINSTANCE hBMInst, UINT wBMID,
875 LPCTBBUTTON lpButtons,INT iNumButtons)
877 return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
878 hBMInst, wBMID, lpButtons,
879 iNumButtons, 0, 0, 0, 0, CCSIZEOF_STRUCT(TBBUTTON, dwData));
883 /***********************************************************************
884 * DllGetVersion [COMCTL32.@]
886 * Retrieves version information of the 'COMCTL32.DLL'
889 * pdvi [O] pointer to version information structure.
893 * Failure: E_INVALIDARG
896 * Returns version of a comctl32.dll from IE4.01 SP1.
899 HRESULT WINAPI DllGetVersion (DLLVERSIONINFO *pdvi)
901 if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
902 WARN("wrong DLLVERSIONINFO size from app\n");
906 pdvi->dwMajorVersion = COMCTL32_VERSION;
907 pdvi->dwMinorVersion = COMCTL32_VERSION_MINOR;
908 pdvi->dwBuildNumber = 2919;
909 pdvi->dwPlatformID = 6304;
911 TRACE("%u.%u.%u.%u\n",
912 pdvi->dwMajorVersion, pdvi->dwMinorVersion,
913 pdvi->dwBuildNumber, pdvi->dwPlatformID);
918 /***********************************************************************
919 * DllInstall (COMCTL32.@)
921 * Installs the ComCtl32 DLL.
925 * Failure: A HRESULT error
927 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
929 TRACE("(%u, %s): stub\n", bInstall, debugstr_w(cmdline));
933 /***********************************************************************
934 * _TrackMouseEvent [COMCTL32.@]
936 * Requests notification of mouse events
938 * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
939 * to the hwnd specified in the ptme structure. After the event message
940 * is posted to the hwnd, the entry in the queue is removed.
942 * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
943 * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
944 * immediately and the TME_LEAVE flag being ignored.
947 * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
953 * IMPLEMENTATION moved to USER32.TrackMouseEvent
958 _TrackMouseEvent (TRACKMOUSEEVENT *ptme)
960 return TrackMouseEvent (ptme);
963 /*************************************************************************
964 * GetMUILanguage [COMCTL32.@]
966 * Returns the user interface language in use by the current process.
969 * Language ID in use by the current process.
971 LANGID WINAPI GetMUILanguage (VOID)
973 return COMCTL32_uiLang;
977 /*************************************************************************
978 * InitMUILanguage [COMCTL32.@]
980 * Sets the user interface language to be used by the current process.
985 VOID WINAPI InitMUILanguage (LANGID uiLang)
987 COMCTL32_uiLang = uiLang;
991 /***********************************************************************
992 * SetWindowSubclass [COMCTL32.410]
994 * Starts a window subclass
997 * hWnd [in] handle to window subclass.
998 * pfnSubclass [in] Pointer to new window procedure.
999 * uIDSubclass [in] Unique identifier of subclass together with pfnSubclass.
1000 * dwRef [in] Reference data to pass to window procedure.
1007 * If an application manually subclasses a window after subclassing it with
1008 * this API and then with this API again, then none of the previous
1009 * subclasses get called or the original window procedure.
1012 BOOL WINAPI SetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
1013 UINT_PTR uIDSubclass, DWORD_PTR dwRef)
1015 LPSUBCLASS_INFO stack;
1016 LPSUBCLASSPROCS proc;
1018 TRACE ("(%p, %p, %lx, %lx)\n", hWnd, pfnSubclass, uIDSubclass, dwRef);
1020 /* Since the window procedure that we set here has two additional arguments,
1021 * we can't simply set it as the new window procedure of the window. So we
1022 * set our own window procedure and then calculate the other two arguments
1025 /* See if we have been called for this window */
1026 stack = GetPropW (hWnd, COMCTL32_wSubclass);
1028 /* allocate stack */
1029 stack = Alloc (sizeof(SUBCLASS_INFO));
1031 ERR ("Failed to allocate our Subclassing stack\n");
1034 SetPropW (hWnd, COMCTL32_wSubclass, stack);
1036 /* set window procedure to our own and save the current one */
1037 if (IsWindowUnicode (hWnd))
1038 stack->origproc = (WNDPROC)SetWindowLongPtrW (hWnd, GWLP_WNDPROC,
1039 (DWORD_PTR)COMCTL32_SubclassProc);
1041 stack->origproc = (WNDPROC)SetWindowLongPtrA (hWnd, GWLP_WNDPROC,
1042 (DWORD_PTR)COMCTL32_SubclassProc);
1045 /* Check to see if we have called this function with the same uIDSubClass
1046 * and pfnSubclass */
1047 proc = stack->SubclassProcs;
1049 if ((proc->id == uIDSubclass) &&
1050 (proc->subproc == pfnSubclass)) {
1058 proc = Alloc(sizeof(SUBCLASSPROCS));
1060 ERR ("Failed to allocate subclass entry in stack\n");
1061 if (IsWindowUnicode (hWnd))
1062 SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1064 SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1066 RemovePropW( hWnd, COMCTL32_wSubclass );
1070 proc->subproc = pfnSubclass;
1072 proc->id = uIDSubclass;
1073 proc->next = stack->SubclassProcs;
1074 stack->SubclassProcs = proc;
1080 /***********************************************************************
1081 * GetWindowSubclass [COMCTL32.411]
1083 * Gets the Reference data from a subclass.
1086 * hWnd [in] Handle to window which were subclassing
1087 * pfnSubclass [in] Pointer to the subclass procedure
1088 * uID [in] Unique identifier of the subclassing procedure
1089 * pdwRef [out] Pointer to the reference data
1096 BOOL WINAPI GetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
1097 UINT_PTR uID, DWORD_PTR *pdwRef)
1099 const SUBCLASS_INFO *stack;
1100 const SUBCLASSPROCS *proc;
1102 TRACE ("(%p, %p, %lx, %p)\n", hWnd, pfnSubclass, uID, pdwRef);
1104 /* See if we have been called for this window */
1105 stack = GetPropW (hWnd, COMCTL32_wSubclass);
1109 proc = stack->SubclassProcs;
1111 if ((proc->id == uID) &&
1112 (proc->subproc == pfnSubclass)) {
1113 *pdwRef = proc->ref;
1123 /***********************************************************************
1124 * RemoveWindowSubclass [COMCTL32.412]
1126 * Removes a window subclass.
1129 * hWnd [in] Handle to the window were subclassing
1130 * pfnSubclass [in] Pointer to the subclass procedure
1131 * uID [in] Unique identifier of this subclass
1138 BOOL WINAPI RemoveWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR uID)
1140 LPSUBCLASS_INFO stack;
1141 LPSUBCLASSPROCS prevproc = NULL;
1142 LPSUBCLASSPROCS proc;
1145 TRACE ("(%p, %p, %lx)\n", hWnd, pfnSubclass, uID);
1147 /* Find the Subclass to remove */
1148 stack = GetPropW (hWnd, COMCTL32_wSubclass);
1152 proc = stack->SubclassProcs;
1154 if ((proc->id == uID) &&
1155 (proc->subproc == pfnSubclass)) {
1158 stack->SubclassProcs = proc->next;
1160 prevproc->next = proc->next;
1162 if (stack->stackpos == proc)
1163 stack->stackpos = stack->stackpos->next;
1173 if (!stack->SubclassProcs && !stack->running) {
1174 TRACE("Last Subclass removed, cleaning up\n");
1175 /* clean up our heap and reset the original window procedure */
1176 if (IsWindowUnicode (hWnd))
1177 SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1179 SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1181 RemovePropW( hWnd, COMCTL32_wSubclass );
1187 /***********************************************************************
1188 * COMCTL32_SubclassProc (internal)
1190 * Window procedure for all subclassed windows.
1191 * Saves the current subclassing stack position to support nested messages
1193 static LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1195 LPSUBCLASS_INFO stack;
1196 LPSUBCLASSPROCS proc;
1199 TRACE ("(%p, 0x%08x, 0x%08lx, 0x%08lx)\n", hWnd, uMsg, wParam, lParam);
1201 stack = GetPropW (hWnd, COMCTL32_wSubclass);
1203 ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
1207 /* Save our old stackpos to properly handle nested messages */
1208 proc = stack->stackpos;
1209 stack->stackpos = stack->SubclassProcs;
1211 ret = DefSubclassProc(hWnd, uMsg, wParam, lParam);
1213 stack->stackpos = proc;
1215 if (!stack->SubclassProcs && !stack->running) {
1216 TRACE("Last Subclass removed, cleaning up\n");
1217 /* clean up our heap and reset the original window procedure */
1218 if (IsWindowUnicode (hWnd))
1219 SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1221 SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1223 RemovePropW( hWnd, COMCTL32_wSubclass );
1228 /***********************************************************************
1229 * DefSubclassProc [COMCTL32.413]
1231 * Calls the next window procedure (i.e. the one before this subclass)
1234 * hWnd [in] The window that we're subclassing
1236 * wParam [in] WPARAM
1237 * lParam [in] LPARAM
1244 LRESULT WINAPI DefSubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1246 LPSUBCLASS_INFO stack;
1249 TRACE ("(%p, 0x%08x, 0x%08lx, 0x%08lx)\n", hWnd, uMsg, wParam, lParam);
1251 /* retrieve our little stack from the Properties */
1252 stack = GetPropW (hWnd, COMCTL32_wSubclass);
1254 ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
1258 /* If we are at the end of stack then we have to call the original
1259 * window procedure */
1260 if (!stack->stackpos) {
1261 if (IsWindowUnicode (hWnd))
1262 ret = CallWindowProcW (stack->origproc, hWnd, uMsg, wParam, lParam);
1264 ret = CallWindowProcA (stack->origproc, hWnd, uMsg, wParam, lParam);
1266 const SUBCLASSPROCS *proc = stack->stackpos;
1267 stack->stackpos = stack->stackpos->next;
1268 /* call the Subclass procedure from the stack */
1269 ret = proc->subproc (hWnd, uMsg, wParam, lParam,
1270 proc->id, proc->ref);
1277 /***********************************************************************
1278 * COMCTL32_CreateToolTip [NOT AN API]
1280 * Creates a tooltip for the control specified in hwnd and does all
1281 * necessary setup and notifications.
1284 * hwndOwner [I] Handle to the window that will own the tool tip.
1287 * Success: Handle of tool tip window.
1292 COMCTL32_CreateToolTip(HWND hwndOwner)
1296 hwndToolTip = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, WS_POPUP,
1297 CW_USEDEFAULT, CW_USEDEFAULT,
1298 CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner,
1301 /* Send NM_TOOLTIPSCREATED notification */
1304 NMTOOLTIPSCREATED nmttc;
1305 /* true owner can be different if hwndOwner is a child window */
1306 HWND hwndTrueOwner = GetWindow(hwndToolTip, GW_OWNER);
1307 nmttc.hdr.hwndFrom = hwndTrueOwner;
1308 nmttc.hdr.idFrom = GetWindowLongPtrW(hwndTrueOwner, GWLP_ID);
1309 nmttc.hdr.code = NM_TOOLTIPSCREATED;
1310 nmttc.hwndToolTips = hwndToolTip;
1312 SendMessageW(GetParent(hwndTrueOwner), WM_NOTIFY,
1313 GetWindowLongPtrW(hwndTrueOwner, GWLP_ID), (LPARAM)&nmttc);
1320 /***********************************************************************
1321 * COMCTL32_RefreshSysColors [NOT AN API]
1323 * Invoked on any control recognizing a WM_SYSCOLORCHANGE message to
1324 * refresh the color values in the color structure
1334 COMCTL32_RefreshSysColors(void)
1336 comctl32_color.clrBtnHighlight = GetSysColor (COLOR_BTNHIGHLIGHT);
1337 comctl32_color.clrBtnShadow = GetSysColor (COLOR_BTNSHADOW);
1338 comctl32_color.clrBtnText = GetSysColor (COLOR_BTNTEXT);
1339 comctl32_color.clrBtnFace = GetSysColor (COLOR_BTNFACE);
1340 comctl32_color.clrHighlight = GetSysColor (COLOR_HIGHLIGHT);
1341 comctl32_color.clrHighlightText = GetSysColor (COLOR_HIGHLIGHTTEXT);
1342 comctl32_color.clrHotTrackingColor = GetSysColor (COLOR_HOTLIGHT);
1343 comctl32_color.clr3dHilight = GetSysColor (COLOR_3DHILIGHT);
1344 comctl32_color.clr3dShadow = GetSysColor (COLOR_3DSHADOW);
1345 comctl32_color.clr3dDkShadow = GetSysColor (COLOR_3DDKSHADOW);
1346 comctl32_color.clr3dFace = GetSysColor (COLOR_3DFACE);
1347 comctl32_color.clrWindow = GetSysColor (COLOR_WINDOW);
1348 comctl32_color.clrWindowText = GetSysColor (COLOR_WINDOWTEXT);
1349 comctl32_color.clrGrayText = GetSysColor (COLOR_GRAYTEXT);
1350 comctl32_color.clrActiveCaption = GetSysColor (COLOR_ACTIVECAPTION);
1351 comctl32_color.clrInfoBk = GetSysColor (COLOR_INFOBK);
1352 comctl32_color.clrInfoText = GetSysColor (COLOR_INFOTEXT);
1355 /***********************************************************************
1356 * COMCTL32_DrawInsertMark [NOT AN API]
1358 * Draws an insertion mark (which looks similar to an 'I').
1361 * hDC [I] Device context to draw onto.
1362 * lpRect [I] Co-ordinates of insertion mark.
1363 * clrInsertMark [I] Colour of the insertion mark.
1364 * bHorizontal [I] True if insert mark should be drawn horizontally,
1365 * vertical otherwise.
1371 * Draws up to but not including the bottom co-ordinate when drawing
1372 * vertically or the right co-ordinate when horizontal.
1374 void COMCTL32_DrawInsertMark(HDC hDC, const RECT *lpRect, COLORREF clrInsertMark, BOOL bHorizontal)
1376 HPEN hPen = CreatePen(PS_SOLID, 1, clrInsertMark);
1378 static const DWORD adwPolyPoints[] = {4,4,4};
1379 LONG lCentre = (bHorizontal ?
1380 lpRect->top + (lpRect->bottom - lpRect->top)/2 :
1381 lpRect->left + (lpRect->right - lpRect->left)/2);
1382 LONG l1 = (bHorizontal ? lpRect->left : lpRect->top);
1383 LONG l2 = (bHorizontal ? lpRect->right : lpRect->bottom);
1384 const POINT aptInsertMark[] =
1386 /* top (V) or left (H) arrow */
1390 {lCentre + 1, l1 + 2},
1394 {lCentre + 1, l1 - 1},
1395 {lCentre + 1, l2 - 2},
1396 /* bottom (V) or right (H) arrow */
1398 {lCentre - 2, l2 - 1},
1399 {lCentre + 3, l2 - 1},
1400 {lCentre + 1, l2 - 3},
1402 hOldPen = SelectObject(hDC, hPen);
1403 PolyPolyline(hDC, aptInsertMark, adwPolyPoints, sizeof(adwPolyPoints)/sizeof(adwPolyPoints[0]));
1404 SelectObject(hDC, hOldPen);
1408 /***********************************************************************
1409 * COMCTL32_EnsureBitmapSize [internal]
1411 * If needed, enlarge the bitmap so that the width is at least cxMinWidth and
1412 * the height is at least cyMinHeight. If the bitmap already has these
1413 * dimensions nothing changes.
1416 * hBitmap [I/O] Bitmap to modify. The handle may change
1417 * cxMinWidth [I] If the width of the bitmap is smaller, then it will
1418 * be enlarged to this value
1419 * cyMinHeight [I] If the height of the bitmap is smaller, then it will
1420 * be enlarged to this value
1421 * cyBackground [I] The color with which the new area will be filled
1426 void COMCTL32_EnsureBitmapSize(HBITMAP *pBitmap, int cxMinWidth, int cyMinHeight, COLORREF crBackground)
1431 HBITMAP hNewDCBitmap, hOldDCBitmap;
1435 if (!GetObjectW(*pBitmap, sizeof(BITMAP), &bmp))
1437 cxNew = (cxMinWidth > bmp.bmWidth ? cxMinWidth : bmp.bmWidth);
1438 cyNew = (cyMinHeight > bmp.bmHeight ? cyMinHeight : bmp.bmHeight);
1439 if (cxNew == bmp.bmWidth && cyNew == bmp.bmHeight)
1442 hdcNew = CreateCompatibleDC(NULL);
1443 hNewBitmap = CreateBitmap(cxNew, cyNew, bmp.bmPlanes, bmp.bmBitsPixel, NULL);
1444 hNewDCBitmap = SelectObject(hdcNew, hNewBitmap);
1445 hNewDCBrush = SelectObject(hdcNew, CreateSolidBrush(crBackground));
1447 hdcOld = CreateCompatibleDC(NULL);
1448 hOldDCBitmap = SelectObject(hdcOld, *pBitmap);
1450 BitBlt(hdcNew, 0, 0, bmp.bmWidth, bmp.bmHeight, hdcOld, 0, 0, SRCCOPY);
1451 if (bmp.bmWidth < cxMinWidth)
1452 PatBlt(hdcNew, bmp.bmWidth, 0, cxNew, bmp.bmHeight, PATCOPY);
1453 if (bmp.bmHeight < cyMinHeight)
1454 PatBlt(hdcNew, 0, bmp.bmHeight, bmp.bmWidth, cyNew, PATCOPY);
1455 if (bmp.bmWidth < cxMinWidth && bmp.bmHeight < cyMinHeight)
1456 PatBlt(hdcNew, bmp.bmWidth, bmp.bmHeight, cxNew, cyNew, PATCOPY);
1458 SelectObject(hdcNew, hNewDCBitmap);
1459 DeleteObject(SelectObject(hdcNew, hNewDCBrush));
1461 SelectObject(hdcOld, hOldDCBitmap);
1464 DeleteObject(*pBitmap);
1465 *pBitmap = hNewBitmap;
1469 void COMCTL32_GetFontMetrics(HFONT hFont, TEXTMETRICW *ptm)
1471 HDC hdc = GetDC(NULL);
1474 hOldFont = SelectObject(hdc, hFont);
1475 GetTextMetricsW(hdc, ptm);
1476 SelectObject(hdc, hOldFont);
1477 ReleaseDC(NULL, hdc);
1480 #ifndef OCM__BASE /* avoid including olectl.h */
1481 #define OCM__BASE (WM_USER+0x1c00)
1484 /***********************************************************************
1485 * COMCTL32_IsReflectedMessage [internal]
1487 * Some parents reflect notify messages - for some messages sent by the child,
1488 * they send it back with the message code increased by OCM__BASE (0x2000).
1489 * This allows better subclassing of controls. We don't need to handle such
1490 * messages but we don't want to print ERRs for them, so this helper function
1493 * Some of the codes are in the CCM_FIRST..CCM_LAST range, but there is no
1494 * colision with defined CCM_ codes.
1496 BOOL COMCTL32_IsReflectedMessage(UINT uMsg)
1500 case OCM__BASE + WM_COMMAND:
1501 case OCM__BASE + WM_CTLCOLORBTN:
1502 case OCM__BASE + WM_CTLCOLOREDIT:
1503 case OCM__BASE + WM_CTLCOLORDLG:
1504 case OCM__BASE + WM_CTLCOLORLISTBOX:
1505 case OCM__BASE + WM_CTLCOLORMSGBOX:
1506 case OCM__BASE + WM_CTLCOLORSCROLLBAR:
1507 case OCM__BASE + WM_CTLCOLORSTATIC:
1508 case OCM__BASE + WM_DRAWITEM:
1509 case OCM__BASE + WM_MEASUREITEM:
1510 case OCM__BASE + WM_DELETEITEM:
1511 case OCM__BASE + WM_VKEYTOITEM:
1512 case OCM__BASE + WM_CHARTOITEM:
1513 case OCM__BASE + WM_COMPAREITEM:
1514 case OCM__BASE + WM_HSCROLL:
1515 case OCM__BASE + WM_VSCROLL:
1516 case OCM__BASE + WM_PARENTNOTIFY:
1517 case OCM__BASE + WM_NOTIFY:
1524 /***********************************************************************
1525 * MirrorIcon [COMCTL32.414]
1527 * Mirrors an icon so that it will appear correctly on a mirrored DC.
1530 * phicon1 [I/O] Icon.
1531 * phicon2 [I/O] Icon.
1537 BOOL WINAPI MirrorIcon(HICON *phicon1, HICON *phicon2)
1539 FIXME("(%p, %p): stub\n", phicon1, phicon2);
1543 static inline int IsDelimiter(WCHAR c)
1556 static int CALLBACK PathWordBreakProc(LPCWSTR lpch, int ichCurrent, int cch, int code)
1558 if (code == WB_ISDELIMITER)
1559 return IsDelimiter(lpch[ichCurrent]);
1562 int dir = (code == WB_LEFT) ? -1 : 1;
1563 for(; 0 <= ichCurrent && ichCurrent < cch; ichCurrent += dir)
1564 if (IsDelimiter(lpch[ichCurrent])) return ichCurrent;
1569 /***********************************************************************
1570 * SetPathWordBreakProc [COMCTL32.384]
1572 * Sets the word break procedure for an edit control to one that understands
1573 * paths so that the user can jump over directories.
1576 * hwnd [I] Handle to edit control.
1577 * bSet [I] If this is TRUE then the word break proc is set, otherwise it is removed.
1580 * Result from EM_SETWORDBREAKPROC message.
1582 LRESULT WINAPI SetPathWordBreakProc(HWND hwnd, BOOL bSet)
1584 return SendMessageW(hwnd, EM_SETWORDBREAKPROC, 0,
1585 (LPARAM)(bSet ? PathWordBreakProc : NULL));
1588 /***********************************************************************
1589 * DrawShadowText [COMCTL32.@]
1591 * Draw text with shadow.
1593 int WINAPI DrawShadowText(HDC hdc, LPCWSTR pszText, UINT cch, RECT *rect, DWORD dwFlags,
1594 COLORREF crText, COLORREF crShadow, int ixOffset, int iyOffset)
1596 FIXME("(%p, %s, %d, %p, %d, 0x%08x, 0x%08x, %d, %d): stub\n", hdc, debugstr_w(pszText), cch, rect, dwFlags,
1597 crText, crShadow, ixOffset, iyOffset);
1598 return DrawTextW(hdc, pszText, cch, rect, DT_LEFT);
1601 /***********************************************************************
1602 * TaskDialogIndirect [COMCTL32.@]
1604 HRESULT WINAPI TaskDialogIndirect(const TASKDIALOGCONFIG *pTaskConfig, int *pnButton,
1605 int *pnRadioButton, BOOL *pfVerificationFlagChecked)
1609 FIXME("%p, %p, %p, %p\n", pTaskConfig, pnButton, pnRadioButton, pfVerificationFlagChecked);
1611 if (pTaskConfig->dwCommonButtons & TDCBF_YES_BUTTON &&
1612 pTaskConfig->dwCommonButtons & TDCBF_NO_BUTTON &&
1613 pTaskConfig->dwCommonButtons & TDCBF_CANCEL_BUTTON)
1614 uType |= MB_YESNOCANCEL;
1616 if (pTaskConfig->dwCommonButtons & TDCBF_YES_BUTTON &&
1617 pTaskConfig->dwCommonButtons & TDCBF_NO_BUTTON)
1620 if (pTaskConfig->dwCommonButtons & TDCBF_RETRY_BUTTON &&
1621 pTaskConfig->dwCommonButtons & TDCBF_CANCEL_BUTTON)
1622 uType |= MB_RETRYCANCEL;
1624 if (pTaskConfig->dwCommonButtons & TDCBF_OK_BUTTON &&
1625 pTaskConfig->dwCommonButtons & TDCBF_CANCEL_BUTTON)
1626 uType |= MB_OKCANCEL;
1628 if (pTaskConfig->dwCommonButtons & TDCBF_OK_BUTTON)
1630 ret = MessageBoxW(pTaskConfig->hwndParent, pTaskConfig->pszMainInstruction,
1631 pTaskConfig->pszWindowTitle, uType);
1632 FIXME("dwCommonButtons=%x uType=%x ret=%x\n", pTaskConfig->dwCommonButtons, uType, ret);
1634 if (pnButton) *pnButton = ret;
1635 if (pnRadioButton) *pnRadioButton = pTaskConfig->nDefaultButton;
1636 if (pfVerificationFlagChecked) *pfVerificationFlagChecked = TRUE;