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;
800 if (nSize == sizeof(BITMAPINFOHEADER) && lpBitmap->biCompression == BI_BITFIELDS)
801 nSize += 3 * sizeof(DWORD);
802 nSize += nColorTableSize * sizeof(RGBQUAD);
803 lpBitmapInfo = GlobalAlloc (GMEM_FIXED, nSize);
804 if (lpBitmapInfo == NULL)
806 RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);
808 pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo) + lpBitmapInfo->biSize);
810 for (iColor = 0; iColor < nColorTableSize; iColor++) {
811 for (i = 0; i < iMaps; i++) {
812 cRef = RGB(pColorTable[iColor].rgbRed,
813 pColorTable[iColor].rgbGreen,
814 pColorTable[iColor].rgbBlue);
815 if ( cRef == sysColorMap[i].from) {
817 if (wFlags & CBS_MASKED) {
818 if (sysColorMap[i].to != COLOR_BTNTEXT)
819 pColorTable[iColor] = RGB(255, 255, 255);
823 pColorTable[iColor].rgbBlue = GetBValue(sysColorMap[i].to);
824 pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);
825 pColorTable[iColor].rgbRed = GetRValue(sysColorMap[i].to);
830 nWidth = lpBitmapInfo->biWidth;
831 nHeight = lpBitmapInfo->biHeight;
832 hdcScreen = GetDC (NULL);
833 hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
835 HDC hdcDst = CreateCompatibleDC (hdcScreen);
836 HBITMAP hbmOld = SelectObject (hdcDst, hbm);
837 const BYTE *lpBits = (const BYTE *)lpBitmap + nSize;
838 StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
839 lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
841 SelectObject (hdcDst, hbmOld);
844 ReleaseDC (NULL, hdcScreen);
845 GlobalFree (lpBitmapInfo);
852 /***********************************************************************
853 * CreateToolbar [COMCTL32.7]
855 * Creates a toolbar control.
868 * Success: handle to the tool bar control
872 * Do not use this functions anymore. Use CreateToolbarEx instead.
876 CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
877 HINSTANCE hBMInst, UINT wBMID,
878 LPCTBBUTTON lpButtons,INT iNumButtons)
880 return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
881 hBMInst, wBMID, lpButtons,
882 iNumButtons, 0, 0, 0, 0, CCSIZEOF_STRUCT(TBBUTTON, dwData));
886 /***********************************************************************
887 * DllGetVersion [COMCTL32.@]
889 * Retrieves version information of the 'COMCTL32.DLL'
892 * pdvi [O] pointer to version information structure.
896 * Failure: E_INVALIDARG
899 * Returns version of a comctl32.dll from IE4.01 SP1.
902 HRESULT WINAPI DllGetVersion (DLLVERSIONINFO *pdvi)
904 if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
905 WARN("wrong DLLVERSIONINFO size from app\n");
909 pdvi->dwMajorVersion = COMCTL32_VERSION;
910 pdvi->dwMinorVersion = COMCTL32_VERSION_MINOR;
911 pdvi->dwBuildNumber = 2919;
912 pdvi->dwPlatformID = 6304;
914 TRACE("%u.%u.%u.%u\n",
915 pdvi->dwMajorVersion, pdvi->dwMinorVersion,
916 pdvi->dwBuildNumber, pdvi->dwPlatformID);
921 /***********************************************************************
922 * DllInstall (COMCTL32.@)
924 * Installs the ComCtl32 DLL.
928 * Failure: A HRESULT error
930 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
932 TRACE("(%u, %s): stub\n", bInstall, debugstr_w(cmdline));
936 /***********************************************************************
937 * _TrackMouseEvent [COMCTL32.@]
939 * Requests notification of mouse events
941 * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
942 * to the hwnd specified in the ptme structure. After the event message
943 * is posted to the hwnd, the entry in the queue is removed.
945 * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
946 * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
947 * immediately and the TME_LEAVE flag being ignored.
950 * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
956 * IMPLEMENTATION moved to USER32.TrackMouseEvent
961 _TrackMouseEvent (TRACKMOUSEEVENT *ptme)
963 return TrackMouseEvent (ptme);
966 /*************************************************************************
967 * GetMUILanguage [COMCTL32.@]
969 * Returns the user interface language in use by the current process.
972 * Language ID in use by the current process.
974 LANGID WINAPI GetMUILanguage (VOID)
976 return COMCTL32_uiLang;
980 /*************************************************************************
981 * InitMUILanguage [COMCTL32.@]
983 * Sets the user interface language to be used by the current process.
988 VOID WINAPI InitMUILanguage (LANGID uiLang)
990 COMCTL32_uiLang = uiLang;
994 /***********************************************************************
995 * SetWindowSubclass [COMCTL32.410]
997 * Starts a window subclass
1000 * hWnd [in] handle to window subclass.
1001 * pfnSubclass [in] Pointer to new window procedure.
1002 * uIDSubclass [in] Unique identifier of subclass together with pfnSubclass.
1003 * dwRef [in] Reference data to pass to window procedure.
1010 * If an application manually subclasses a window after subclassing it with
1011 * this API and then with this API again, then none of the previous
1012 * subclasses get called or the original window procedure.
1015 BOOL WINAPI SetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
1016 UINT_PTR uIDSubclass, DWORD_PTR dwRef)
1018 LPSUBCLASS_INFO stack;
1019 LPSUBCLASSPROCS proc;
1021 TRACE ("(%p, %p, %lx, %lx)\n", hWnd, pfnSubclass, uIDSubclass, dwRef);
1023 /* Since the window procedure that we set here has two additional arguments,
1024 * we can't simply set it as the new window procedure of the window. So we
1025 * set our own window procedure and then calculate the other two arguments
1028 /* See if we have been called for this window */
1029 stack = GetPropW (hWnd, COMCTL32_wSubclass);
1031 /* allocate stack */
1032 stack = Alloc (sizeof(SUBCLASS_INFO));
1034 ERR ("Failed to allocate our Subclassing stack\n");
1037 SetPropW (hWnd, COMCTL32_wSubclass, stack);
1039 /* set window procedure to our own and save the current one */
1040 if (IsWindowUnicode (hWnd))
1041 stack->origproc = (WNDPROC)SetWindowLongPtrW (hWnd, GWLP_WNDPROC,
1042 (DWORD_PTR)COMCTL32_SubclassProc);
1044 stack->origproc = (WNDPROC)SetWindowLongPtrA (hWnd, GWLP_WNDPROC,
1045 (DWORD_PTR)COMCTL32_SubclassProc);
1048 /* Check to see if we have called this function with the same uIDSubClass
1049 * and pfnSubclass */
1050 proc = stack->SubclassProcs;
1052 if ((proc->id == uIDSubclass) &&
1053 (proc->subproc == pfnSubclass)) {
1061 proc = Alloc(sizeof(SUBCLASSPROCS));
1063 ERR ("Failed to allocate subclass entry in stack\n");
1064 if (IsWindowUnicode (hWnd))
1065 SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1067 SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1069 RemovePropW( hWnd, COMCTL32_wSubclass );
1073 proc->subproc = pfnSubclass;
1075 proc->id = uIDSubclass;
1076 proc->next = stack->SubclassProcs;
1077 stack->SubclassProcs = proc;
1083 /***********************************************************************
1084 * GetWindowSubclass [COMCTL32.411]
1086 * Gets the Reference data from a subclass.
1089 * hWnd [in] Handle to window which were subclassing
1090 * pfnSubclass [in] Pointer to the subclass procedure
1091 * uID [in] Unique identifier of the subclassing procedure
1092 * pdwRef [out] Pointer to the reference data
1099 BOOL WINAPI GetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
1100 UINT_PTR uID, DWORD_PTR *pdwRef)
1102 const SUBCLASS_INFO *stack;
1103 const SUBCLASSPROCS *proc;
1105 TRACE ("(%p, %p, %lx, %p)\n", hWnd, pfnSubclass, uID, pdwRef);
1107 /* See if we have been called for this window */
1108 stack = GetPropW (hWnd, COMCTL32_wSubclass);
1112 proc = stack->SubclassProcs;
1114 if ((proc->id == uID) &&
1115 (proc->subproc == pfnSubclass)) {
1116 *pdwRef = proc->ref;
1126 /***********************************************************************
1127 * RemoveWindowSubclass [COMCTL32.412]
1129 * Removes a window subclass.
1132 * hWnd [in] Handle to the window were subclassing
1133 * pfnSubclass [in] Pointer to the subclass procedure
1134 * uID [in] Unique identifier of this subclass
1141 BOOL WINAPI RemoveWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR uID)
1143 LPSUBCLASS_INFO stack;
1144 LPSUBCLASSPROCS prevproc = NULL;
1145 LPSUBCLASSPROCS proc;
1148 TRACE ("(%p, %p, %lx)\n", hWnd, pfnSubclass, uID);
1150 /* Find the Subclass to remove */
1151 stack = GetPropW (hWnd, COMCTL32_wSubclass);
1155 proc = stack->SubclassProcs;
1157 if ((proc->id == uID) &&
1158 (proc->subproc == pfnSubclass)) {
1161 stack->SubclassProcs = proc->next;
1163 prevproc->next = proc->next;
1165 if (stack->stackpos == proc)
1166 stack->stackpos = stack->stackpos->next;
1176 if (!stack->SubclassProcs && !stack->running) {
1177 TRACE("Last Subclass removed, cleaning up\n");
1178 /* clean up our heap and reset the original window procedure */
1179 if (IsWindowUnicode (hWnd))
1180 SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1182 SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1184 RemovePropW( hWnd, COMCTL32_wSubclass );
1190 /***********************************************************************
1191 * COMCTL32_SubclassProc (internal)
1193 * Window procedure for all subclassed windows.
1194 * Saves the current subclassing stack position to support nested messages
1196 static LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1198 LPSUBCLASS_INFO stack;
1199 LPSUBCLASSPROCS proc;
1202 TRACE ("(%p, 0x%08x, 0x%08lx, 0x%08lx)\n", hWnd, uMsg, wParam, lParam);
1204 stack = GetPropW (hWnd, COMCTL32_wSubclass);
1206 ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
1210 /* Save our old stackpos to properly handle nested messages */
1211 proc = stack->stackpos;
1212 stack->stackpos = stack->SubclassProcs;
1214 ret = DefSubclassProc(hWnd, uMsg, wParam, lParam);
1216 stack->stackpos = proc;
1218 if (!stack->SubclassProcs && !stack->running) {
1219 TRACE("Last Subclass removed, cleaning up\n");
1220 /* clean up our heap and reset the original window procedure */
1221 if (IsWindowUnicode (hWnd))
1222 SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1224 SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1226 RemovePropW( hWnd, COMCTL32_wSubclass );
1231 /***********************************************************************
1232 * DefSubclassProc [COMCTL32.413]
1234 * Calls the next window procedure (i.e. the one before this subclass)
1237 * hWnd [in] The window that we're subclassing
1239 * wParam [in] WPARAM
1240 * lParam [in] LPARAM
1247 LRESULT WINAPI DefSubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1249 LPSUBCLASS_INFO stack;
1252 TRACE ("(%p, 0x%08x, 0x%08lx, 0x%08lx)\n", hWnd, uMsg, wParam, lParam);
1254 /* retrieve our little stack from the Properties */
1255 stack = GetPropW (hWnd, COMCTL32_wSubclass);
1257 ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
1261 /* If we are at the end of stack then we have to call the original
1262 * window procedure */
1263 if (!stack->stackpos) {
1264 if (IsWindowUnicode (hWnd))
1265 ret = CallWindowProcW (stack->origproc, hWnd, uMsg, wParam, lParam);
1267 ret = CallWindowProcA (stack->origproc, hWnd, uMsg, wParam, lParam);
1269 const SUBCLASSPROCS *proc = stack->stackpos;
1270 stack->stackpos = stack->stackpos->next;
1271 /* call the Subclass procedure from the stack */
1272 ret = proc->subproc (hWnd, uMsg, wParam, lParam,
1273 proc->id, proc->ref);
1280 /***********************************************************************
1281 * COMCTL32_CreateToolTip [NOT AN API]
1283 * Creates a tooltip for the control specified in hwnd and does all
1284 * necessary setup and notifications.
1287 * hwndOwner [I] Handle to the window that will own the tool tip.
1290 * Success: Handle of tool tip window.
1295 COMCTL32_CreateToolTip(HWND hwndOwner)
1299 hwndToolTip = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, WS_POPUP,
1300 CW_USEDEFAULT, CW_USEDEFAULT,
1301 CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner,
1304 /* Send NM_TOOLTIPSCREATED notification */
1307 NMTOOLTIPSCREATED nmttc;
1308 /* true owner can be different if hwndOwner is a child window */
1309 HWND hwndTrueOwner = GetWindow(hwndToolTip, GW_OWNER);
1310 nmttc.hdr.hwndFrom = hwndTrueOwner;
1311 nmttc.hdr.idFrom = GetWindowLongPtrW(hwndTrueOwner, GWLP_ID);
1312 nmttc.hdr.code = NM_TOOLTIPSCREATED;
1313 nmttc.hwndToolTips = hwndToolTip;
1315 SendMessageW(GetParent(hwndTrueOwner), WM_NOTIFY,
1316 GetWindowLongPtrW(hwndTrueOwner, GWLP_ID), (LPARAM)&nmttc);
1323 /***********************************************************************
1324 * COMCTL32_RefreshSysColors [NOT AN API]
1326 * Invoked on any control recognizing a WM_SYSCOLORCHANGE message to
1327 * refresh the color values in the color structure
1337 COMCTL32_RefreshSysColors(void)
1339 comctl32_color.clrBtnHighlight = GetSysColor (COLOR_BTNHIGHLIGHT);
1340 comctl32_color.clrBtnShadow = GetSysColor (COLOR_BTNSHADOW);
1341 comctl32_color.clrBtnText = GetSysColor (COLOR_BTNTEXT);
1342 comctl32_color.clrBtnFace = GetSysColor (COLOR_BTNFACE);
1343 comctl32_color.clrHighlight = GetSysColor (COLOR_HIGHLIGHT);
1344 comctl32_color.clrHighlightText = GetSysColor (COLOR_HIGHLIGHTTEXT);
1345 comctl32_color.clrHotTrackingColor = GetSysColor (COLOR_HOTLIGHT);
1346 comctl32_color.clr3dHilight = GetSysColor (COLOR_3DHILIGHT);
1347 comctl32_color.clr3dShadow = GetSysColor (COLOR_3DSHADOW);
1348 comctl32_color.clr3dDkShadow = GetSysColor (COLOR_3DDKSHADOW);
1349 comctl32_color.clr3dFace = GetSysColor (COLOR_3DFACE);
1350 comctl32_color.clrWindow = GetSysColor (COLOR_WINDOW);
1351 comctl32_color.clrWindowText = GetSysColor (COLOR_WINDOWTEXT);
1352 comctl32_color.clrGrayText = GetSysColor (COLOR_GRAYTEXT);
1353 comctl32_color.clrActiveCaption = GetSysColor (COLOR_ACTIVECAPTION);
1354 comctl32_color.clrInfoBk = GetSysColor (COLOR_INFOBK);
1355 comctl32_color.clrInfoText = GetSysColor (COLOR_INFOTEXT);
1358 /***********************************************************************
1359 * COMCTL32_DrawInsertMark [NOT AN API]
1361 * Draws an insertion mark (which looks similar to an 'I').
1364 * hDC [I] Device context to draw onto.
1365 * lpRect [I] Co-ordinates of insertion mark.
1366 * clrInsertMark [I] Colour of the insertion mark.
1367 * bHorizontal [I] True if insert mark should be drawn horizontally,
1368 * vertical otherwise.
1374 * Draws up to but not including the bottom co-ordinate when drawing
1375 * vertically or the right co-ordinate when horizontal.
1377 void COMCTL32_DrawInsertMark(HDC hDC, const RECT *lpRect, COLORREF clrInsertMark, BOOL bHorizontal)
1379 HPEN hPen = CreatePen(PS_SOLID, 1, clrInsertMark);
1381 static const DWORD adwPolyPoints[] = {4,4,4};
1382 LONG lCentre = (bHorizontal ?
1383 lpRect->top + (lpRect->bottom - lpRect->top)/2 :
1384 lpRect->left + (lpRect->right - lpRect->left)/2);
1385 LONG l1 = (bHorizontal ? lpRect->left : lpRect->top);
1386 LONG l2 = (bHorizontal ? lpRect->right : lpRect->bottom);
1387 const POINT aptInsertMark[] =
1389 /* top (V) or left (H) arrow */
1393 {lCentre + 1, l1 + 2},
1397 {lCentre + 1, l1 - 1},
1398 {lCentre + 1, l2 - 2},
1399 /* bottom (V) or right (H) arrow */
1401 {lCentre - 2, l2 - 1},
1402 {lCentre + 3, l2 - 1},
1403 {lCentre + 1, l2 - 3},
1405 hOldPen = SelectObject(hDC, hPen);
1406 PolyPolyline(hDC, aptInsertMark, adwPolyPoints, sizeof(adwPolyPoints)/sizeof(adwPolyPoints[0]));
1407 SelectObject(hDC, hOldPen);
1411 /***********************************************************************
1412 * COMCTL32_EnsureBitmapSize [internal]
1414 * If needed, enlarge the bitmap so that the width is at least cxMinWidth and
1415 * the height is at least cyMinHeight. If the bitmap already has these
1416 * dimensions nothing changes.
1419 * hBitmap [I/O] Bitmap to modify. The handle may change
1420 * cxMinWidth [I] If the width of the bitmap is smaller, then it will
1421 * be enlarged to this value
1422 * cyMinHeight [I] If the height of the bitmap is smaller, then it will
1423 * be enlarged to this value
1424 * cyBackground [I] The color with which the new area will be filled
1429 void COMCTL32_EnsureBitmapSize(HBITMAP *pBitmap, int cxMinWidth, int cyMinHeight, COLORREF crBackground)
1434 HBITMAP hNewDCBitmap, hOldDCBitmap;
1438 if (!GetObjectW(*pBitmap, sizeof(BITMAP), &bmp))
1440 cxNew = (cxMinWidth > bmp.bmWidth ? cxMinWidth : bmp.bmWidth);
1441 cyNew = (cyMinHeight > bmp.bmHeight ? cyMinHeight : bmp.bmHeight);
1442 if (cxNew == bmp.bmWidth && cyNew == bmp.bmHeight)
1445 hdcNew = CreateCompatibleDC(NULL);
1446 hNewBitmap = CreateBitmap(cxNew, cyNew, bmp.bmPlanes, bmp.bmBitsPixel, NULL);
1447 hNewDCBitmap = SelectObject(hdcNew, hNewBitmap);
1448 hNewDCBrush = SelectObject(hdcNew, CreateSolidBrush(crBackground));
1450 hdcOld = CreateCompatibleDC(NULL);
1451 hOldDCBitmap = SelectObject(hdcOld, *pBitmap);
1453 BitBlt(hdcNew, 0, 0, bmp.bmWidth, bmp.bmHeight, hdcOld, 0, 0, SRCCOPY);
1454 if (bmp.bmWidth < cxMinWidth)
1455 PatBlt(hdcNew, bmp.bmWidth, 0, cxNew, bmp.bmHeight, PATCOPY);
1456 if (bmp.bmHeight < cyMinHeight)
1457 PatBlt(hdcNew, 0, bmp.bmHeight, bmp.bmWidth, cyNew, PATCOPY);
1458 if (bmp.bmWidth < cxMinWidth && bmp.bmHeight < cyMinHeight)
1459 PatBlt(hdcNew, bmp.bmWidth, bmp.bmHeight, cxNew, cyNew, PATCOPY);
1461 SelectObject(hdcNew, hNewDCBitmap);
1462 DeleteObject(SelectObject(hdcNew, hNewDCBrush));
1464 SelectObject(hdcOld, hOldDCBitmap);
1467 DeleteObject(*pBitmap);
1468 *pBitmap = hNewBitmap;
1472 void COMCTL32_GetFontMetrics(HFONT hFont, TEXTMETRICW *ptm)
1474 HDC hdc = GetDC(NULL);
1477 hOldFont = SelectObject(hdc, hFont);
1478 GetTextMetricsW(hdc, ptm);
1479 SelectObject(hdc, hOldFont);
1480 ReleaseDC(NULL, hdc);
1483 #ifndef OCM__BASE /* avoid including olectl.h */
1484 #define OCM__BASE (WM_USER+0x1c00)
1487 /***********************************************************************
1488 * COMCTL32_IsReflectedMessage [internal]
1490 * Some parents reflect notify messages - for some messages sent by the child,
1491 * they send it back with the message code increased by OCM__BASE (0x2000).
1492 * This allows better subclassing of controls. We don't need to handle such
1493 * messages but we don't want to print ERRs for them, so this helper function
1496 * Some of the codes are in the CCM_FIRST..CCM_LAST range, but there is no
1497 * colision with defined CCM_ codes.
1499 BOOL COMCTL32_IsReflectedMessage(UINT uMsg)
1503 case OCM__BASE + WM_COMMAND:
1504 case OCM__BASE + WM_CTLCOLORBTN:
1505 case OCM__BASE + WM_CTLCOLOREDIT:
1506 case OCM__BASE + WM_CTLCOLORDLG:
1507 case OCM__BASE + WM_CTLCOLORLISTBOX:
1508 case OCM__BASE + WM_CTLCOLORMSGBOX:
1509 case OCM__BASE + WM_CTLCOLORSCROLLBAR:
1510 case OCM__BASE + WM_CTLCOLORSTATIC:
1511 case OCM__BASE + WM_DRAWITEM:
1512 case OCM__BASE + WM_MEASUREITEM:
1513 case OCM__BASE + WM_DELETEITEM:
1514 case OCM__BASE + WM_VKEYTOITEM:
1515 case OCM__BASE + WM_CHARTOITEM:
1516 case OCM__BASE + WM_COMPAREITEM:
1517 case OCM__BASE + WM_HSCROLL:
1518 case OCM__BASE + WM_VSCROLL:
1519 case OCM__BASE + WM_PARENTNOTIFY:
1520 case OCM__BASE + WM_NOTIFY:
1527 /***********************************************************************
1528 * MirrorIcon [COMCTL32.414]
1530 * Mirrors an icon so that it will appear correctly on a mirrored DC.
1533 * phicon1 [I/O] Icon.
1534 * phicon2 [I/O] Icon.
1540 BOOL WINAPI MirrorIcon(HICON *phicon1, HICON *phicon2)
1542 FIXME("(%p, %p): stub\n", phicon1, phicon2);
1546 static inline int IsDelimiter(WCHAR c)
1559 static int CALLBACK PathWordBreakProc(LPCWSTR lpch, int ichCurrent, int cch, int code)
1561 if (code == WB_ISDELIMITER)
1562 return IsDelimiter(lpch[ichCurrent]);
1565 int dir = (code == WB_LEFT) ? -1 : 1;
1566 for(; 0 <= ichCurrent && ichCurrent < cch; ichCurrent += dir)
1567 if (IsDelimiter(lpch[ichCurrent])) return ichCurrent;
1572 /***********************************************************************
1573 * SetPathWordBreakProc [COMCTL32.384]
1575 * Sets the word break procedure for an edit control to one that understands
1576 * paths so that the user can jump over directories.
1579 * hwnd [I] Handle to edit control.
1580 * bSet [I] If this is TRUE then the word break proc is set, otherwise it is removed.
1583 * Result from EM_SETWORDBREAKPROC message.
1585 LRESULT WINAPI SetPathWordBreakProc(HWND hwnd, BOOL bSet)
1587 return SendMessageW(hwnd, EM_SETWORDBREAKPROC, 0,
1588 (LPARAM)(bSet ? PathWordBreakProc : NULL));
1591 /***********************************************************************
1592 * DrawShadowText [COMCTL32.@]
1594 * Draw text with shadow.
1596 int WINAPI DrawShadowText(HDC hdc, LPCWSTR pszText, UINT cch, RECT *rect, DWORD dwFlags,
1597 COLORREF crText, COLORREF crShadow, int ixOffset, int iyOffset)
1599 FIXME("(%p, %s, %d, %p, %d, 0x%08x, 0x%08x, %d, %d): stub\n", hdc, debugstr_w(pszText), cch, rect, dwFlags,
1600 crText, crShadow, ixOffset, iyOffset);
1601 return DrawTextW(hdc, pszText, cch, rect, DT_LEFT);
1604 /***********************************************************************
1605 * TaskDialogIndirect [COMCTL32.@]
1607 HRESULT WINAPI TaskDialogIndirect(const TASKDIALOGCONFIG *pTaskConfig, int *pnButton,
1608 int *pnRadioButton, BOOL *pfVerificationFlagChecked)
1612 FIXME("%p, %p, %p, %p\n", pTaskConfig, pnButton, pnRadioButton, pfVerificationFlagChecked);
1614 if (pTaskConfig->dwCommonButtons & TDCBF_YES_BUTTON &&
1615 pTaskConfig->dwCommonButtons & TDCBF_NO_BUTTON &&
1616 pTaskConfig->dwCommonButtons & TDCBF_CANCEL_BUTTON)
1617 uType |= MB_YESNOCANCEL;
1619 if (pTaskConfig->dwCommonButtons & TDCBF_YES_BUTTON &&
1620 pTaskConfig->dwCommonButtons & TDCBF_NO_BUTTON)
1623 if (pTaskConfig->dwCommonButtons & TDCBF_RETRY_BUTTON &&
1624 pTaskConfig->dwCommonButtons & TDCBF_CANCEL_BUTTON)
1625 uType |= MB_RETRYCANCEL;
1627 if (pTaskConfig->dwCommonButtons & TDCBF_OK_BUTTON &&
1628 pTaskConfig->dwCommonButtons & TDCBF_CANCEL_BUTTON)
1629 uType |= MB_OKCANCEL;
1631 if (pTaskConfig->dwCommonButtons & TDCBF_OK_BUTTON)
1633 ret = MessageBoxW(pTaskConfig->hwndParent, pTaskConfig->pszMainInstruction,
1634 pTaskConfig->pszWindowTitle, uType);
1635 FIXME("dwCommonButtons=%x uType=%x ret=%x\n", pTaskConfig->dwCommonButtons, uType, ret);
1637 if (pnButton) *pnButton = ret;
1638 if (pnRadioButton) *pnRadioButton = pTaskConfig->nDefaultButton;
1639 if (pfVerificationFlagChecked) *pfVerificationFlagChecked = TRUE;