2 * Common controls functions
4 * Copyright 1997 Dimitrie O. Paun
5 * Copyright 1998,2000 Eric Kohl
6 * Copyright 2014-2015 Michael Müller
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 * This code was audited for completeness against the documented features
25 * of Comctl32.dll version 6.0 on Oct. 21, 2002, by Christian Neumair.
27 * Unless otherwise noted, we believe this code to be complete, as per
28 * the specification mentioned above.
29 * If you discover missing features, or bugs, please note them below.
32 * -- implement GetMUILanguage + InitMUILanguage
33 * -- finish NOTES for MenuHelp, GetEffectiveClientRect and GetStatusTextW
34 * -- FIXMEs + BUGS (search for them)
37 * -- ICC_ANIMATE_CLASS
42 * -- ICC_INTERNET_CLASSES
44 * -- ICC_LISTVIEW_CLASSES
45 * -- ICC_NATIVEFNTCTL_CLASS
46 * -- ICC_PAGESCROLLER_CLASS
47 * -- ICC_PROGRESS_CLASS
48 * -- ICC_STANDARD_CLASSES (not yet implemented)
50 * -- ICC_TREEVIEW_CLASSES
52 * -- ICC_USEREX_CLASSES
53 * -- ICC_WIN95_CLASSES
68 #define NO_SHLWAPI_STREAM
71 #include "wine/debug.h"
73 WINE_DEFAULT_DEBUG_CHANNEL(commctrl
);
76 static LRESULT WINAPI
COMCTL32_SubclassProc (HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
78 static LPWSTR COMCTL32_wSubclass
= NULL
;
79 HMODULE COMCTL32_hModule
= 0;
80 static 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
97 /***********************************************************************
100 * Initializes the internal 'COMCTL32.DLL'.
103 * hinstDLL [I] handle to the 'dlls' instance
105 * lpvReserved [I] reserved, must be NULL
112 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
114 TRACE("%p,%x,%p\n", hinstDLL
, fdwReason
, lpvReserved
);
117 case DLL_PROCESS_ATTACH
:
118 DisableThreadLibraryCalls(hinstDLL
);
120 COMCTL32_hModule
= hinstDLL
;
122 /* add global subclassing atom (used by 'tooltip' and 'updown') */
123 COMCTL32_wSubclass
= (LPWSTR
)(DWORD_PTR
)GlobalAddAtomW (strCC32SubclassInfo
);
124 TRACE("Subclassing atom added: %p\n", COMCTL32_wSubclass
);
126 /* create local pattern brush */
127 COMCTL32_hPattern55AABitmap
= CreateBitmap (8, 8, 1, 1, wPattern55AA
);
128 COMCTL32_hPattern55AABrush
= CreatePatternBrush (COMCTL32_hPattern55AABitmap
);
130 /* Get all the colors at DLL load */
131 COMCTL32_RefreshSysColors();
133 /* like comctl32 5.82+ register all the common control classes */
136 DATETIME_Register ();
140 IPADDRESS_Register ();
141 LISTVIEW_Register ();
142 MONTHCAL_Register ();
143 NATIVEFONT_Register ();
145 PROGRESS_Register ();
151 TOOLTIPS_Register ();
152 TRACKBAR_Register ();
153 TREEVIEW_Register ();
156 /* subclass user32 controls */
157 THEMING_Initialize ();
160 case DLL_PROCESS_DETACH
:
161 if (lpvReserved
) break;
162 /* clean up subclassing */
163 THEMING_Uninitialize();
165 /* unregister all common control classes */
166 ANIMATE_Unregister ();
167 COMBOEX_Unregister ();
168 DATETIME_Unregister ();
169 FLATSB_Unregister ();
170 HEADER_Unregister ();
171 HOTKEY_Unregister ();
172 IPADDRESS_Unregister ();
173 LISTVIEW_Unregister ();
174 MONTHCAL_Unregister ();
175 NATIVEFONT_Unregister ();
177 PROGRESS_Unregister ();
179 STATUS_Unregister ();
180 SYSLINK_Unregister ();
182 TOOLBAR_Unregister ();
183 TOOLTIPS_Unregister ();
184 TRACKBAR_Unregister ();
185 TREEVIEW_Unregister ();
186 UPDOWN_Unregister ();
188 /* delete local pattern brush */
189 DeleteObject (COMCTL32_hPattern55AABrush
);
190 DeleteObject (COMCTL32_hPattern55AABitmap
);
192 /* delete global subclassing atom */
193 GlobalDeleteAtom (LOWORD(COMCTL32_wSubclass
));
194 TRACE("Subclassing atom deleted: %p\n", COMCTL32_wSubclass
);
202 /***********************************************************************
203 * MenuHelp [COMCTL32.2]
205 * Handles the setting of status bar help messages when the user
206 * selects menu items.
209 * uMsg [I] message (WM_MENUSELECT) (see NOTES)
210 * wParam [I] wParam of the message uMsg
211 * lParam [I] lParam of the message uMsg
212 * hMainMenu [I] handle to the application's main menu
213 * hInst [I] handle to the module that contains string resources
214 * hwndStatus [I] handle to the status bar window
215 * lpwIDs [I] pointer to an array of integers (see NOTES)
221 * The official documentation is incomplete!
222 * This is the correct documentation:
225 * MenuHelp() does NOT handle WM_COMMAND messages! It only handles
226 * WM_MENUSELECT messages.
229 * (will be written ...)
233 MenuHelp (UINT uMsg
, WPARAM wParam
, LPARAM lParam
, HMENU hMainMenu
,
234 HINSTANCE hInst
, HWND hwndStatus
, UINT
* lpwIDs
)
238 if (!IsWindow (hwndStatus
))
243 TRACE("WM_MENUSELECT wParam=0x%lX lParam=0x%lX\n",
246 if ((HIWORD(wParam
) == 0xFFFF) && (lParam
== 0)) {
247 /* menu was closed */
248 TRACE("menu was closed!\n");
249 SendMessageW (hwndStatus
, SB_SIMPLE
, FALSE
, 0);
252 /* menu item was selected */
253 if (HIWORD(wParam
) & MF_POPUP
)
254 uMenuID
= *(lpwIDs
+1);
256 uMenuID
= (UINT
)LOWORD(wParam
);
257 TRACE("uMenuID = %u\n", uMenuID
);
262 if (!LoadStringW (hInst
, uMenuID
, szText
, sizeof(szText
)/sizeof(szText
[0])))
265 SendMessageW (hwndStatus
, SB_SETTEXTW
,
266 255 | SBT_NOBORDERS
, (LPARAM
)szText
);
267 SendMessageW (hwndStatus
, SB_SIMPLE
, TRUE
, 0);
273 TRACE("WM_COMMAND wParam=0x%lX lParam=0x%lX\n",
275 /* WM_COMMAND is not invalid since it is documented
276 * in the windows api reference. So don't output
277 * any FIXME for WM_COMMAND
279 WARN("We don't care about the WM_COMMAND\n");
283 FIXME("Invalid Message 0x%x!\n", uMsg
);
289 /***********************************************************************
290 * ShowHideMenuCtl [COMCTL32.3]
292 * Shows or hides controls and updates the corresponding menu item.
295 * hwnd [I] handle to the client window.
296 * uFlags [I] menu command id.
297 * lpInfo [I] pointer to an array of integers. (See NOTES.)
304 * The official documentation is incomplete!
305 * This is the correct documentation:
308 * Handle to the window that contains the menu and controls.
311 * Identifier of the menu item to receive or lose a check mark.
314 * The array of integers contains pairs of values. BOTH values of
315 * the first pair must be the handles to the application's main menu.
316 * Each subsequent pair consists of a menu id and control id.
320 ShowHideMenuCtl (HWND hwnd
, UINT_PTR uFlags
, LPINT lpInfo
)
324 TRACE("%p, %lx, %p\n", hwnd
, uFlags
, lpInfo
);
329 if (!(lpInfo
[0]) || !(lpInfo
[1]))
332 /* search for control */
333 lpMenuId
= &lpInfo
[2];
334 while (*lpMenuId
!= uFlags
)
337 if (GetMenuState ((HMENU
)(DWORD_PTR
)lpInfo
[1], uFlags
, MF_BYCOMMAND
) & MFS_CHECKED
) {
338 /* uncheck menu item */
339 CheckMenuItem ((HMENU
)(DWORD_PTR
)lpInfo
[0], *lpMenuId
, MF_BYCOMMAND
| MF_UNCHECKED
);
343 SetWindowPos (GetDlgItem (hwnd
, *lpMenuId
), 0, 0, 0, 0, 0,
347 /* check menu item */
348 CheckMenuItem ((HMENU
)(DWORD_PTR
)lpInfo
[0], *lpMenuId
, MF_BYCOMMAND
| MF_CHECKED
);
352 SetWindowPos (GetDlgItem (hwnd
, *lpMenuId
), 0, 0, 0, 0, 0,
360 /***********************************************************************
361 * GetEffectiveClientRect [COMCTL32.4]
363 * Calculates the coordinates of a rectangle in the client area.
366 * hwnd [I] handle to the client window.
367 * lpRect [O] pointer to the rectangle of the client window
368 * lpInfo [I] pointer to an array of integers (see NOTES)
374 * The official documentation is incomplete!
375 * This is the correct documentation:
378 * (will be written ...)
382 GetEffectiveClientRect (HWND hwnd
, LPRECT lpRect
, const INT
*lpInfo
)
388 TRACE("(%p %p %p)\n",
389 hwnd
, lpRect
, lpInfo
);
391 GetClientRect (hwnd
, lpRect
);
399 hwndCtrl
= GetDlgItem (hwnd
, *lpRun
);
400 if (GetWindowLongW (hwndCtrl
, GWL_STYLE
) & WS_VISIBLE
) {
401 TRACE("control id 0x%x\n", *lpRun
);
402 GetWindowRect (hwndCtrl
, &rcCtrl
);
403 MapWindowPoints (NULL
, hwnd
, (LPPOINT
)&rcCtrl
, 2);
404 SubtractRect (lpRect
, lpRect
, &rcCtrl
);
411 /***********************************************************************
412 * DrawStatusTextW [COMCTL32.@]
414 * Draws text with borders, like in a status bar.
417 * hdc [I] handle to the window's display context
418 * lprc [I] pointer to a rectangle
419 * text [I] pointer to the text
420 * style [I] drawing style
426 * The style variable can have one of the following values:
427 * (will be written ...)
430 void WINAPI
DrawStatusTextW (HDC hdc
, LPCRECT lprc
, LPCWSTR text
, UINT style
)
433 UINT border
= BDR_SUNKENOUTER
;
435 if (style
& SBT_POPOUT
)
436 border
= BDR_RAISEDOUTER
;
437 else if (style
& SBT_NOBORDERS
)
440 DrawEdge (hdc
, &r
, border
, BF_RECT
|BF_ADJUST
);
444 int oldbkmode
= SetBkMode (hdc
, TRANSPARENT
);
445 UINT align
= DT_LEFT
;
448 if (style
& SBT_RTLREADING
)
449 FIXME("Unsupported RTL style!\n");
454 DrawTextW (hdc
, text
- strCnt
, strCnt
, &r
, align
|DT_VCENTER
|DT_SINGLELINE
|DT_NOPREFIX
);
457 if (align
==DT_RIGHT
) {
460 align
= (align
==DT_LEFT
? DT_CENTER
: DT_RIGHT
);
466 if (strCnt
) DrawTextW (hdc
, text
- strCnt
, -1, &r
, align
|DT_VCENTER
|DT_SINGLELINE
|DT_NOPREFIX
);
467 SetBkMode(hdc
, oldbkmode
);
472 /***********************************************************************
473 * DrawStatusText [COMCTL32.@]
474 * DrawStatusTextA [COMCTL32.5]
476 * Draws text with borders, like in a status bar.
479 * hdc [I] handle to the window's display context
480 * lprc [I] pointer to a rectangle
481 * text [I] pointer to the text
482 * style [I] drawing style
488 void WINAPI
DrawStatusTextA (HDC hdc
, LPCRECT lprc
, LPCSTR text
, UINT style
)
494 if ( (len
= MultiByteToWideChar( CP_ACP
, 0, text
, -1, NULL
, 0 )) ) {
495 if ( (textW
= Alloc( len
* sizeof(WCHAR
) )) )
496 MultiByteToWideChar( CP_ACP
, 0, text
, -1, textW
, len
);
499 DrawStatusTextW( hdc
, lprc
, textW
, style
);
504 /***********************************************************************
505 * CreateStatusWindow [COMCTL32.@]
506 * CreateStatusWindowA [COMCTL32.6]
508 * Creates a status bar
511 * style [I] window style
512 * text [I] pointer to the window text
513 * parent [I] handle to the parent window
514 * wid [I] control id of the status bar
517 * Success: handle to the status window
522 CreateStatusWindowA (LONG style
, LPCSTR text
, HWND parent
, UINT wid
)
524 return CreateWindowA(STATUSCLASSNAMEA
, text
, style
,
525 CW_USEDEFAULT
, CW_USEDEFAULT
,
526 CW_USEDEFAULT
, CW_USEDEFAULT
,
527 parent
, (HMENU
)(DWORD_PTR
)wid
, 0, 0);
531 /***********************************************************************
532 * CreateStatusWindowW [COMCTL32.@]
534 * Creates a status bar control
537 * style [I] window style
538 * text [I] pointer to the window text
539 * parent [I] handle to the parent window
540 * wid [I] control id of the status bar
543 * Success: handle to the status window
548 CreateStatusWindowW (LONG style
, LPCWSTR text
, HWND parent
, UINT wid
)
550 return CreateWindowW(STATUSCLASSNAMEW
, text
, style
,
551 CW_USEDEFAULT
, CW_USEDEFAULT
,
552 CW_USEDEFAULT
, CW_USEDEFAULT
,
553 parent
, (HMENU
)(DWORD_PTR
)wid
, 0, 0);
557 /***********************************************************************
558 * CreateUpDownControl [COMCTL32.16]
560 * Creates an up-down control
563 * style [I] window styles
564 * x [I] horizontal position of the control
565 * y [I] vertical position of the control
566 * cx [I] with of the control
567 * cy [I] height of the control
568 * parent [I] handle to the parent window
569 * id [I] the control's identifier
570 * inst [I] handle to the application's module instance
571 * buddy [I] handle to the buddy window, can be NULL
572 * maxVal [I] upper limit of the control
573 * minVal [I] lower limit of the control
574 * curVal [I] current value of the control
577 * Success: handle to the updown control
582 CreateUpDownControl (DWORD style
, INT x
, INT y
, INT cx
, INT cy
,
583 HWND parent
, INT id
, HINSTANCE inst
,
584 HWND buddy
, INT maxVal
, INT minVal
, INT curVal
)
587 CreateWindowW (UPDOWN_CLASSW
, 0, style
, x
, y
, cx
, cy
,
588 parent
, (HMENU
)(DWORD_PTR
)id
, inst
, 0);
590 SendMessageW (hUD
, UDM_SETBUDDY
, (WPARAM
)buddy
, 0);
591 SendMessageW (hUD
, UDM_SETRANGE
, 0, MAKELONG(maxVal
, minVal
));
592 SendMessageW (hUD
, UDM_SETPOS
, 0, MAKELONG(curVal
, 0));
599 /***********************************************************************
600 * InitCommonControls [COMCTL32.17]
602 * Registers the common controls.
611 * This function is just a dummy - all the controls are registered at
612 * the DLL initialization time. See InitCommonContolsEx for details.
616 InitCommonControls (void)
621 /***********************************************************************
622 * InitCommonControlsEx [COMCTL32.@]
624 * Registers the common controls.
627 * lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
634 * Probably all versions of comctl32 initializes the Win95 controls in DllMain
635 * during DLL initialization. Starting from comctl32 v5.82 all the controls
636 * are initialized there. We follow this behaviour and this function is just
639 * Note: when writing programs under Windows, if you don't call any function
640 * from comctl32 the linker may not link this DLL. If InitCommonControlsEx
641 * was the only comctl32 function you were calling and you remove it you may
642 * have a false impression that InitCommonControlsEx actually did something.
646 InitCommonControlsEx (const INITCOMMONCONTROLSEX
*lpInitCtrls
)
648 if (!lpInitCtrls
|| lpInitCtrls
->dwSize
!= sizeof(INITCOMMONCONTROLSEX
))
651 TRACE("(0x%08x)\n", lpInitCtrls
->dwICC
);
656 /***********************************************************************
657 * CreateToolbarEx [COMCTL32.@]
659 * Creates a toolbar window.
677 * Success: handle to the tool bar control
682 CreateToolbarEx (HWND hwnd
, DWORD style
, UINT wID
, INT nBitmaps
,
683 HINSTANCE hBMInst
, UINT_PTR wBMID
, LPCTBBUTTON lpButtons
,
684 INT iNumButtons
, INT dxButton
, INT dyButton
,
685 INT dxBitmap
, INT dyBitmap
, UINT uStructSize
)
690 CreateWindowExW(0, TOOLBARCLASSNAMEW
, NULL
, style
|WS_CHILD
, 0,0,100,30,
691 hwnd
, (HMENU
)(DWORD_PTR
)wID
, COMCTL32_hModule
, NULL
);
695 SendMessageW (hwndTB
, TB_BUTTONSTRUCTSIZE
, uStructSize
, 0);
697 /* set bitmap and button size */
698 /*If CreateToolbarEx receives 0, windows sets default values*/
703 if (dxBitmap
== 0 || dyBitmap
== 0)
704 dxBitmap
= dyBitmap
= 16;
705 SendMessageW(hwndTB
, TB_SETBITMAPSIZE
, 0, MAKELPARAM(dxBitmap
, dyBitmap
));
711 /* TB_SETBUTTONSIZE -> TB_SETBITMAPSIZE bug introduced for Windows compatibility */
712 if (dxButton
!= 0 && dyButton
!= 0)
713 SendMessageW(hwndTB
, TB_SETBITMAPSIZE
, 0, MAKELPARAM(dxButton
, dyButton
));
717 if (nBitmaps
> 0 || hBMInst
== HINST_COMMCTRL
)
719 tbab
.hInst
= hBMInst
;
722 SendMessageW (hwndTB
, TB_ADDBITMAP
, nBitmaps
, (LPARAM
)&tbab
);
726 SendMessageW (hwndTB
, TB_ADDBUTTONSW
, iNumButtons
, (LPARAM
)lpButtons
);
733 /***********************************************************************
734 * CreateMappedBitmap [COMCTL32.8]
736 * Loads a bitmap resource using a colour map.
739 * hInstance [I] Handle to the module containing the bitmap.
740 * idBitmap [I] The bitmap resource ID.
741 * wFlags [I] CMB_MASKED for using bitmap as a mask or 0 for normal.
742 * lpColorMap [I] Colour information needed for the bitmap or NULL (uses system colours).
743 * iNumMaps [I] Number of COLORMAP's pointed to by lpColorMap.
746 * Success: handle to the new bitmap
751 CreateMappedBitmap (HINSTANCE hInstance
, INT_PTR idBitmap
, UINT wFlags
,
752 LPCOLORMAP lpColorMap
, INT iNumMaps
)
756 const BITMAPINFOHEADER
*lpBitmap
;
757 LPBITMAPINFOHEADER lpBitmapInfo
;
758 UINT nSize
, nColorTableSize
, iColor
;
759 RGBQUAD
*pColorTable
;
760 INT i
, iMaps
, nWidth
, nHeight
;
763 LPCOLORMAP sysColorMap
;
765 COLORMAP internalColorMap
[4] =
766 {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
768 /* initialize pointer to colortable and default color table */
771 sysColorMap
= lpColorMap
;
774 internalColorMap
[0].to
= GetSysColor (COLOR_BTNTEXT
);
775 internalColorMap
[1].to
= GetSysColor (COLOR_BTNSHADOW
);
776 internalColorMap
[2].to
= GetSysColor (COLOR_BTNFACE
);
777 internalColorMap
[3].to
= GetSysColor (COLOR_BTNHIGHLIGHT
);
779 sysColorMap
= internalColorMap
;
782 hRsrc
= FindResourceW (hInstance
, (LPWSTR
)idBitmap
, (LPWSTR
)RT_BITMAP
);
785 hglb
= LoadResource (hInstance
, hRsrc
);
788 lpBitmap
= LockResource (hglb
);
789 if (lpBitmap
== NULL
)
792 if (lpBitmap
->biSize
>= sizeof(BITMAPINFOHEADER
) && lpBitmap
->biClrUsed
)
793 nColorTableSize
= lpBitmap
->biClrUsed
;
794 else if (lpBitmap
->biBitCount
<= 8)
795 nColorTableSize
= (1 << lpBitmap
->biBitCount
);
798 nSize
= lpBitmap
->biSize
;
799 if (nSize
== sizeof(BITMAPINFOHEADER
) && lpBitmap
->biCompression
== BI_BITFIELDS
)
800 nSize
+= 3 * sizeof(DWORD
);
801 nSize
+= nColorTableSize
* sizeof(RGBQUAD
);
802 lpBitmapInfo
= GlobalAlloc (GMEM_FIXED
, nSize
);
803 if (lpBitmapInfo
== NULL
)
805 RtlMoveMemory (lpBitmapInfo
, lpBitmap
, nSize
);
807 pColorTable
= (RGBQUAD
*)(((LPBYTE
)lpBitmapInfo
) + lpBitmapInfo
->biSize
);
809 for (iColor
= 0; iColor
< nColorTableSize
; iColor
++) {
810 for (i
= 0; i
< iMaps
; i
++) {
811 cRef
= RGB(pColorTable
[iColor
].rgbRed
,
812 pColorTable
[iColor
].rgbGreen
,
813 pColorTable
[iColor
].rgbBlue
);
814 if ( cRef
== sysColorMap
[i
].from
) {
816 if (wFlags
& CBS_MASKED
) {
817 if (sysColorMap
[i
].to
!= COLOR_BTNTEXT
)
818 pColorTable
[iColor
] = RGB(255, 255, 255);
822 pColorTable
[iColor
].rgbBlue
= GetBValue(sysColorMap
[i
].to
);
823 pColorTable
[iColor
].rgbGreen
= GetGValue(sysColorMap
[i
].to
);
824 pColorTable
[iColor
].rgbRed
= GetRValue(sysColorMap
[i
].to
);
829 nWidth
= lpBitmapInfo
->biWidth
;
830 nHeight
= lpBitmapInfo
->biHeight
;
831 hdcScreen
= GetDC (NULL
);
832 hbm
= CreateCompatibleBitmap (hdcScreen
, nWidth
, nHeight
);
834 HDC hdcDst
= CreateCompatibleDC (hdcScreen
);
835 HBITMAP hbmOld
= SelectObject (hdcDst
, hbm
);
836 const BYTE
*lpBits
= (const BYTE
*)lpBitmap
+ nSize
;
837 StretchDIBits (hdcDst
, 0, 0, nWidth
, nHeight
, 0, 0, nWidth
, nHeight
,
838 lpBits
, (LPBITMAPINFO
)lpBitmapInfo
, DIB_RGB_COLORS
,
840 SelectObject (hdcDst
, hbmOld
);
843 ReleaseDC (NULL
, hdcScreen
);
844 GlobalFree (lpBitmapInfo
);
851 /***********************************************************************
852 * CreateToolbar [COMCTL32.7]
854 * Creates a toolbar control.
867 * Success: handle to the tool bar control
871 * Do not use this function anymore. Use CreateToolbarEx instead.
875 CreateToolbar (HWND hwnd
, DWORD style
, UINT wID
, INT nBitmaps
,
876 HINSTANCE hBMInst
, UINT wBMID
,
877 LPCTBBUTTON lpButtons
,INT iNumButtons
)
879 return CreateToolbarEx (hwnd
, style
| CCS_NODIVIDER
, wID
, nBitmaps
,
880 hBMInst
, wBMID
, lpButtons
,
881 iNumButtons
, 0, 0, 0, 0, CCSIZEOF_STRUCT(TBBUTTON
, dwData
));
885 /***********************************************************************
886 * DllGetVersion [COMCTL32.@]
888 * Retrieves version information of the 'COMCTL32.DLL'
891 * pdvi [O] pointer to version information structure.
895 * Failure: E_INVALIDARG
898 * Returns version of a comctl32.dll from IE4.01 SP1.
901 HRESULT WINAPI
DllGetVersion (DLLVERSIONINFO
*pdvi
)
903 if (pdvi
->cbSize
!= sizeof(DLLVERSIONINFO
)) {
904 WARN("wrong DLLVERSIONINFO size from app\n");
908 pdvi
->dwMajorVersion
= COMCTL32_VERSION
;
909 pdvi
->dwMinorVersion
= COMCTL32_VERSION_MINOR
;
910 pdvi
->dwBuildNumber
= 2919;
911 pdvi
->dwPlatformID
= 6304;
913 TRACE("%u.%u.%u.%u\n",
914 pdvi
->dwMajorVersion
, pdvi
->dwMinorVersion
,
915 pdvi
->dwBuildNumber
, pdvi
->dwPlatformID
);
920 /***********************************************************************
921 * DllInstall (COMCTL32.@)
923 * Installs the ComCtl32 DLL.
927 * Failure: A HRESULT error
929 HRESULT WINAPI
DllInstall(BOOL bInstall
, LPCWSTR cmdline
)
931 TRACE("(%u, %s): stub\n", bInstall
, debugstr_w(cmdline
));
935 /***********************************************************************
936 * _TrackMouseEvent [COMCTL32.@]
938 * Requests notification of mouse events
940 * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
941 * to the hwnd specified in the ptme structure. After the event message
942 * is posted to the hwnd, the entry in the queue is removed.
944 * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
945 * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
946 * immediately and the TME_LEAVE flag being ignored.
949 * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
955 * IMPLEMENTATION moved to USER32.TrackMouseEvent
960 _TrackMouseEvent (TRACKMOUSEEVENT
*ptme
)
962 return TrackMouseEvent (ptme
);
965 /*************************************************************************
966 * GetMUILanguage [COMCTL32.@]
968 * Returns the user interface language in use by the current process.
971 * Language ID in use by the current process.
973 LANGID WINAPI
GetMUILanguage (VOID
)
975 return COMCTL32_uiLang
;
979 /*************************************************************************
980 * InitMUILanguage [COMCTL32.@]
982 * Sets the user interface language to be used by the current process.
987 VOID WINAPI
InitMUILanguage (LANGID uiLang
)
989 COMCTL32_uiLang
= uiLang
;
993 /***********************************************************************
994 * SetWindowSubclass [COMCTL32.410]
996 * Starts a window subclass
999 * hWnd [in] handle to window subclass.
1000 * pfnSubclass [in] Pointer to new window procedure.
1001 * uIDSubclass [in] Unique identifier of subclass together with pfnSubclass.
1002 * dwRef [in] Reference data to pass to window procedure.
1009 * If an application manually subclasses a window after subclassing it with
1010 * this API and then with this API again, then none of the previous
1011 * subclasses get called or the original window procedure.
1014 BOOL WINAPI
SetWindowSubclass (HWND hWnd
, SUBCLASSPROC pfnSubclass
,
1015 UINT_PTR uIDSubclass
, DWORD_PTR dwRef
)
1017 LPSUBCLASS_INFO stack
;
1018 LPSUBCLASSPROCS proc
;
1020 TRACE ("(%p, %p, %lx, %lx)\n", hWnd
, pfnSubclass
, uIDSubclass
, dwRef
);
1022 /* Since the window procedure that we set here has two additional arguments,
1023 * we can't simply set it as the new window procedure of the window. So we
1024 * set our own window procedure and then calculate the other two arguments
1027 /* See if we have been called for this window */
1028 stack
= GetPropW (hWnd
, COMCTL32_wSubclass
);
1030 /* allocate stack */
1031 stack
= Alloc (sizeof(SUBCLASS_INFO
));
1033 ERR ("Failed to allocate our Subclassing stack\n");
1036 SetPropW (hWnd
, COMCTL32_wSubclass
, stack
);
1038 /* set window procedure to our own and save the current one */
1039 if (IsWindowUnicode (hWnd
))
1040 stack
->origproc
= (WNDPROC
)SetWindowLongPtrW (hWnd
, GWLP_WNDPROC
,
1041 (DWORD_PTR
)COMCTL32_SubclassProc
);
1043 stack
->origproc
= (WNDPROC
)SetWindowLongPtrA (hWnd
, GWLP_WNDPROC
,
1044 (DWORD_PTR
)COMCTL32_SubclassProc
);
1047 /* Check to see if we have called this function with the same uIDSubClass
1048 * and pfnSubclass */
1049 proc
= stack
->SubclassProcs
;
1051 if ((proc
->id
== uIDSubclass
) &&
1052 (proc
->subproc
== pfnSubclass
)) {
1060 proc
= Alloc(sizeof(SUBCLASSPROCS
));
1062 ERR ("Failed to allocate subclass entry in stack\n");
1063 if (IsWindowUnicode (hWnd
))
1064 SetWindowLongPtrW (hWnd
, GWLP_WNDPROC
, (DWORD_PTR
)stack
->origproc
);
1066 SetWindowLongPtrA (hWnd
, GWLP_WNDPROC
, (DWORD_PTR
)stack
->origproc
);
1068 RemovePropW( hWnd
, COMCTL32_wSubclass
);
1072 proc
->subproc
= pfnSubclass
;
1074 proc
->id
= uIDSubclass
;
1075 proc
->next
= stack
->SubclassProcs
;
1076 stack
->SubclassProcs
= proc
;
1082 /***********************************************************************
1083 * GetWindowSubclass [COMCTL32.411]
1085 * Gets the Reference data from a subclass.
1088 * hWnd [in] Handle to the window which we are subclassing
1089 * pfnSubclass [in] Pointer to the subclass procedure
1090 * uID [in] Unique identifier of the subclassing procedure
1091 * pdwRef [out] Pointer to the reference data
1098 BOOL WINAPI
GetWindowSubclass (HWND hWnd
, SUBCLASSPROC pfnSubclass
,
1099 UINT_PTR uID
, DWORD_PTR
*pdwRef
)
1101 const SUBCLASS_INFO
*stack
;
1102 const SUBCLASSPROCS
*proc
;
1104 TRACE ("(%p, %p, %lx, %p)\n", hWnd
, pfnSubclass
, uID
, pdwRef
);
1106 /* See if we have been called for this window */
1107 stack
= GetPropW (hWnd
, COMCTL32_wSubclass
);
1111 proc
= stack
->SubclassProcs
;
1113 if ((proc
->id
== uID
) &&
1114 (proc
->subproc
== pfnSubclass
)) {
1115 *pdwRef
= proc
->ref
;
1125 /***********************************************************************
1126 * RemoveWindowSubclass [COMCTL32.412]
1128 * Removes a window subclass.
1131 * hWnd [in] Handle to the window which we are subclassing
1132 * pfnSubclass [in] Pointer to the subclass procedure
1133 * uID [in] Unique identifier of this subclass
1140 BOOL WINAPI
RemoveWindowSubclass(HWND hWnd
, SUBCLASSPROC pfnSubclass
, UINT_PTR uID
)
1142 LPSUBCLASS_INFO stack
;
1143 LPSUBCLASSPROCS prevproc
= NULL
;
1144 LPSUBCLASSPROCS proc
;
1147 TRACE ("(%p, %p, %lx)\n", hWnd
, pfnSubclass
, uID
);
1149 /* Find the Subclass to remove */
1150 stack
= GetPropW (hWnd
, COMCTL32_wSubclass
);
1154 proc
= stack
->SubclassProcs
;
1156 if ((proc
->id
== uID
) &&
1157 (proc
->subproc
== pfnSubclass
)) {
1160 stack
->SubclassProcs
= proc
->next
;
1162 prevproc
->next
= proc
->next
;
1164 if (stack
->stackpos
== proc
)
1165 stack
->stackpos
= stack
->stackpos
->next
;
1175 if (!stack
->SubclassProcs
&& !stack
->running
) {
1176 TRACE("Last Subclass removed, cleaning up\n");
1177 /* clean up our heap and reset the original window procedure */
1178 if (IsWindowUnicode (hWnd
))
1179 SetWindowLongPtrW (hWnd
, GWLP_WNDPROC
, (DWORD_PTR
)stack
->origproc
);
1181 SetWindowLongPtrA (hWnd
, GWLP_WNDPROC
, (DWORD_PTR
)stack
->origproc
);
1183 RemovePropW( hWnd
, COMCTL32_wSubclass
);
1189 /***********************************************************************
1190 * COMCTL32_SubclassProc (internal)
1192 * Window procedure for all subclassed windows.
1193 * Saves the current subclassing stack position to support nested messages
1195 static LRESULT WINAPI
COMCTL32_SubclassProc (HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1197 LPSUBCLASS_INFO stack
;
1198 LPSUBCLASSPROCS proc
;
1201 TRACE ("(%p, 0x%08x, 0x%08lx, 0x%08lx)\n", hWnd
, uMsg
, wParam
, lParam
);
1203 stack
= GetPropW (hWnd
, COMCTL32_wSubclass
);
1205 ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd
);
1209 /* Save our old stackpos to properly handle nested messages */
1210 proc
= stack
->stackpos
;
1211 stack
->stackpos
= stack
->SubclassProcs
;
1213 ret
= DefSubclassProc(hWnd
, uMsg
, wParam
, lParam
);
1215 stack
->stackpos
= proc
;
1217 if (!stack
->SubclassProcs
&& !stack
->running
) {
1218 TRACE("Last Subclass removed, cleaning up\n");
1219 /* clean up our heap and reset the original window procedure */
1220 if (IsWindowUnicode (hWnd
))
1221 SetWindowLongPtrW (hWnd
, GWLP_WNDPROC
, (DWORD_PTR
)stack
->origproc
);
1223 SetWindowLongPtrA (hWnd
, GWLP_WNDPROC
, (DWORD_PTR
)stack
->origproc
);
1225 RemovePropW( hWnd
, COMCTL32_wSubclass
);
1230 /***********************************************************************
1231 * DefSubclassProc [COMCTL32.413]
1233 * Calls the next window procedure (i.e. the one before this subclass)
1236 * hWnd [in] The window that we're subclassing
1238 * wParam [in] WPARAM
1239 * lParam [in] LPARAM
1246 LRESULT WINAPI
DefSubclassProc (HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1248 LPSUBCLASS_INFO stack
;
1251 TRACE ("(%p, 0x%08x, 0x%08lx, 0x%08lx)\n", hWnd
, uMsg
, wParam
, lParam
);
1253 /* retrieve our little stack from the Properties */
1254 stack
= GetPropW (hWnd
, COMCTL32_wSubclass
);
1256 ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd
);
1260 /* If we are at the end of stack then we have to call the original
1261 * window procedure */
1262 if (!stack
->stackpos
) {
1263 if (IsWindowUnicode (hWnd
))
1264 ret
= CallWindowProcW (stack
->origproc
, hWnd
, uMsg
, wParam
, lParam
);
1266 ret
= CallWindowProcA (stack
->origproc
, hWnd
, uMsg
, wParam
, lParam
);
1268 const SUBCLASSPROCS
*proc
= stack
->stackpos
;
1269 stack
->stackpos
= stack
->stackpos
->next
;
1270 /* call the Subclass procedure from the stack */
1271 ret
= proc
->subproc (hWnd
, uMsg
, wParam
, lParam
,
1272 proc
->id
, proc
->ref
);
1279 /***********************************************************************
1280 * COMCTL32_CreateToolTip [NOT AN API]
1282 * Creates a tooltip for the control specified in hwnd and does all
1283 * necessary setup and notifications.
1286 * hwndOwner [I] Handle to the window that will own the tool tip.
1289 * Success: Handle of tool tip window.
1294 COMCTL32_CreateToolTip(HWND hwndOwner
)
1298 hwndToolTip
= CreateWindowExW(0, TOOLTIPS_CLASSW
, NULL
, WS_POPUP
,
1299 CW_USEDEFAULT
, CW_USEDEFAULT
,
1300 CW_USEDEFAULT
, CW_USEDEFAULT
, hwndOwner
,
1303 /* Send NM_TOOLTIPSCREATED notification */
1306 NMTOOLTIPSCREATED nmttc
;
1307 /* true owner can be different if hwndOwner is a child window */
1308 HWND hwndTrueOwner
= GetWindow(hwndToolTip
, GW_OWNER
);
1309 nmttc
.hdr
.hwndFrom
= hwndTrueOwner
;
1310 nmttc
.hdr
.idFrom
= GetWindowLongPtrW(hwndTrueOwner
, GWLP_ID
);
1311 nmttc
.hdr
.code
= NM_TOOLTIPSCREATED
;
1312 nmttc
.hwndToolTips
= hwndToolTip
;
1314 SendMessageW(GetParent(hwndTrueOwner
), WM_NOTIFY
,
1315 GetWindowLongPtrW(hwndTrueOwner
, GWLP_ID
), (LPARAM
)&nmttc
);
1322 /***********************************************************************
1323 * COMCTL32_RefreshSysColors [NOT AN API]
1325 * Invoked on any control recognizing a WM_SYSCOLORCHANGE message to
1326 * refresh the color values in the color structure
1336 COMCTL32_RefreshSysColors(void)
1338 comctl32_color
.clrBtnHighlight
= GetSysColor (COLOR_BTNHIGHLIGHT
);
1339 comctl32_color
.clrBtnShadow
= GetSysColor (COLOR_BTNSHADOW
);
1340 comctl32_color
.clrBtnText
= GetSysColor (COLOR_BTNTEXT
);
1341 comctl32_color
.clrBtnFace
= GetSysColor (COLOR_BTNFACE
);
1342 comctl32_color
.clrHighlight
= GetSysColor (COLOR_HIGHLIGHT
);
1343 comctl32_color
.clrHighlightText
= GetSysColor (COLOR_HIGHLIGHTTEXT
);
1344 comctl32_color
.clrHotTrackingColor
= GetSysColor (COLOR_HOTLIGHT
);
1345 comctl32_color
.clr3dHilight
= GetSysColor (COLOR_3DHILIGHT
);
1346 comctl32_color
.clr3dShadow
= GetSysColor (COLOR_3DSHADOW
);
1347 comctl32_color
.clr3dDkShadow
= GetSysColor (COLOR_3DDKSHADOW
);
1348 comctl32_color
.clr3dFace
= GetSysColor (COLOR_3DFACE
);
1349 comctl32_color
.clrWindow
= GetSysColor (COLOR_WINDOW
);
1350 comctl32_color
.clrWindowText
= GetSysColor (COLOR_WINDOWTEXT
);
1351 comctl32_color
.clrGrayText
= GetSysColor (COLOR_GRAYTEXT
);
1352 comctl32_color
.clrActiveCaption
= GetSysColor (COLOR_ACTIVECAPTION
);
1353 comctl32_color
.clrInfoBk
= GetSysColor (COLOR_INFOBK
);
1354 comctl32_color
.clrInfoText
= GetSysColor (COLOR_INFOTEXT
);
1357 /***********************************************************************
1358 * COMCTL32_DrawInsertMark [NOT AN API]
1360 * Draws an insertion mark (which looks similar to an 'I').
1363 * hDC [I] Device context to draw onto.
1364 * lpRect [I] Co-ordinates of insertion mark.
1365 * clrInsertMark [I] Colour of the insertion mark.
1366 * bHorizontal [I] True if insert mark should be drawn horizontally,
1367 * vertical otherwise.
1373 * Draws up to but not including the bottom co-ordinate when drawing
1374 * vertically or the right co-ordinate when horizontal.
1376 void COMCTL32_DrawInsertMark(HDC hDC
, const RECT
*lpRect
, COLORREF clrInsertMark
, BOOL bHorizontal
)
1378 HPEN hPen
= CreatePen(PS_SOLID
, 1, clrInsertMark
);
1380 static const DWORD adwPolyPoints
[] = {4,4,4};
1381 LONG lCentre
= (bHorizontal
?
1382 lpRect
->top
+ (lpRect
->bottom
- lpRect
->top
)/2 :
1383 lpRect
->left
+ (lpRect
->right
- lpRect
->left
)/2);
1384 LONG l1
= (bHorizontal
? lpRect
->left
: lpRect
->top
);
1385 LONG l2
= (bHorizontal
? lpRect
->right
: lpRect
->bottom
);
1386 const POINT aptInsertMark
[] =
1388 /* top (V) or left (H) arrow */
1392 {lCentre
+ 1, l1
+ 2},
1396 {lCentre
+ 1, l1
- 1},
1397 {lCentre
+ 1, l2
- 2},
1398 /* bottom (V) or right (H) arrow */
1400 {lCentre
- 2, l2
- 1},
1401 {lCentre
+ 3, l2
- 1},
1402 {lCentre
+ 1, l2
- 3},
1404 hOldPen
= SelectObject(hDC
, hPen
);
1405 PolyPolyline(hDC
, aptInsertMark
, adwPolyPoints
, sizeof(adwPolyPoints
)/sizeof(adwPolyPoints
[0]));
1406 SelectObject(hDC
, hOldPen
);
1410 /***********************************************************************
1411 * COMCTL32_EnsureBitmapSize [internal]
1413 * If needed, enlarge the bitmap so that the width is at least cxMinWidth and
1414 * the height is at least cyMinHeight. If the bitmap already has these
1415 * dimensions nothing changes.
1418 * hBitmap [I/O] Bitmap to modify. The handle may change
1419 * cxMinWidth [I] If the width of the bitmap is smaller, then it will
1420 * be enlarged to this value
1421 * cyMinHeight [I] If the height of the bitmap is smaller, then it will
1422 * be enlarged to this value
1423 * cyBackground [I] The color with which the new area will be filled
1428 void COMCTL32_EnsureBitmapSize(HBITMAP
*pBitmap
, int cxMinWidth
, int cyMinHeight
, COLORREF crBackground
)
1433 HBITMAP hNewDCBitmap
, hOldDCBitmap
;
1437 if (!GetObjectW(*pBitmap
, sizeof(BITMAP
), &bmp
))
1439 cxNew
= (cxMinWidth
> bmp
.bmWidth
? cxMinWidth
: bmp
.bmWidth
);
1440 cyNew
= (cyMinHeight
> bmp
.bmHeight
? cyMinHeight
: bmp
.bmHeight
);
1441 if (cxNew
== bmp
.bmWidth
&& cyNew
== bmp
.bmHeight
)
1444 hdcNew
= CreateCompatibleDC(NULL
);
1445 hNewBitmap
= CreateBitmap(cxNew
, cyNew
, bmp
.bmPlanes
, bmp
.bmBitsPixel
, NULL
);
1446 hNewDCBitmap
= SelectObject(hdcNew
, hNewBitmap
);
1447 hNewDCBrush
= SelectObject(hdcNew
, CreateSolidBrush(crBackground
));
1449 hdcOld
= CreateCompatibleDC(NULL
);
1450 hOldDCBitmap
= SelectObject(hdcOld
, *pBitmap
);
1452 BitBlt(hdcNew
, 0, 0, bmp
.bmWidth
, bmp
.bmHeight
, hdcOld
, 0, 0, SRCCOPY
);
1453 if (bmp
.bmWidth
< cxMinWidth
)
1454 PatBlt(hdcNew
, bmp
.bmWidth
, 0, cxNew
, bmp
.bmHeight
, PATCOPY
);
1455 if (bmp
.bmHeight
< cyMinHeight
)
1456 PatBlt(hdcNew
, 0, bmp
.bmHeight
, bmp
.bmWidth
, cyNew
, PATCOPY
);
1457 if (bmp
.bmWidth
< cxMinWidth
&& bmp
.bmHeight
< cyMinHeight
)
1458 PatBlt(hdcNew
, bmp
.bmWidth
, bmp
.bmHeight
, cxNew
, cyNew
, PATCOPY
);
1460 SelectObject(hdcNew
, hNewDCBitmap
);
1461 DeleteObject(SelectObject(hdcNew
, hNewDCBrush
));
1463 SelectObject(hdcOld
, hOldDCBitmap
);
1466 DeleteObject(*pBitmap
);
1467 *pBitmap
= hNewBitmap
;
1471 void COMCTL32_GetFontMetrics(HFONT hFont
, TEXTMETRICW
*ptm
)
1473 HDC hdc
= GetDC(NULL
);
1476 hOldFont
= SelectObject(hdc
, hFont
);
1477 GetTextMetricsW(hdc
, ptm
);
1478 SelectObject(hdc
, hOldFont
);
1479 ReleaseDC(NULL
, hdc
);
1482 #ifndef OCM__BASE /* avoid including olectl.h */
1483 #define OCM__BASE (WM_USER+0x1c00)
1486 /***********************************************************************
1487 * COMCTL32_IsReflectedMessage [internal]
1489 * Some parents reflect notify messages - for some messages sent by the child,
1490 * they send it back with the message code increased by OCM__BASE (0x2000).
1491 * This allows better subclassing of controls. We don't need to handle such
1492 * messages but we don't want to print ERRs for them, so this helper function
1495 * Some of the codes are in the CCM_FIRST..CCM_LAST range, but there is no
1496 * collision with defined CCM_ codes.
1498 BOOL
COMCTL32_IsReflectedMessage(UINT uMsg
)
1502 case OCM__BASE
+ WM_COMMAND
:
1503 case OCM__BASE
+ WM_CTLCOLORBTN
:
1504 case OCM__BASE
+ WM_CTLCOLOREDIT
:
1505 case OCM__BASE
+ WM_CTLCOLORDLG
:
1506 case OCM__BASE
+ WM_CTLCOLORLISTBOX
:
1507 case OCM__BASE
+ WM_CTLCOLORMSGBOX
:
1508 case OCM__BASE
+ WM_CTLCOLORSCROLLBAR
:
1509 case OCM__BASE
+ WM_CTLCOLORSTATIC
:
1510 case OCM__BASE
+ WM_DRAWITEM
:
1511 case OCM__BASE
+ WM_MEASUREITEM
:
1512 case OCM__BASE
+ WM_DELETEITEM
:
1513 case OCM__BASE
+ WM_VKEYTOITEM
:
1514 case OCM__BASE
+ WM_CHARTOITEM
:
1515 case OCM__BASE
+ WM_COMPAREITEM
:
1516 case OCM__BASE
+ WM_HSCROLL
:
1517 case OCM__BASE
+ WM_VSCROLL
:
1518 case OCM__BASE
+ WM_PARENTNOTIFY
:
1519 case OCM__BASE
+ WM_NOTIFY
:
1526 /***********************************************************************
1527 * MirrorIcon [COMCTL32.414]
1529 * Mirrors an icon so that it will appear correctly on a mirrored DC.
1532 * phicon1 [I/O] Icon.
1533 * phicon2 [I/O] Icon.
1539 BOOL WINAPI
MirrorIcon(HICON
*phicon1
, HICON
*phicon2
)
1541 FIXME("(%p, %p): stub\n", phicon1
, phicon2
);
1545 static inline BOOL
IsDelimiter(WCHAR c
)
1558 static int CALLBACK
PathWordBreakProc(LPCWSTR lpch
, int ichCurrent
, int cch
, int code
)
1560 if (code
== WB_ISDELIMITER
)
1561 return IsDelimiter(lpch
[ichCurrent
]);
1564 int dir
= (code
== WB_LEFT
) ? -1 : 1;
1565 for(; 0 <= ichCurrent
&& ichCurrent
< cch
; ichCurrent
+= dir
)
1566 if (IsDelimiter(lpch
[ichCurrent
])) return ichCurrent
;
1571 /***********************************************************************
1572 * SetPathWordBreakProc [COMCTL32.384]
1574 * Sets the word break procedure for an edit control to one that understands
1575 * paths so that the user can jump over directories.
1578 * hwnd [I] Handle to edit control.
1579 * bSet [I] If this is TRUE then the word break proc is set, otherwise it is removed.
1582 * Result from EM_SETWORDBREAKPROC message.
1584 LRESULT WINAPI
SetPathWordBreakProc(HWND hwnd
, BOOL bSet
)
1586 return SendMessageW(hwnd
, EM_SETWORDBREAKPROC
, 0,
1587 (LPARAM
)(bSet
? PathWordBreakProc
: NULL
));
1590 /***********************************************************************
1591 * DrawShadowText [COMCTL32.@]
1593 * Draw text with shadow.
1595 int WINAPI
DrawShadowText(HDC hdc
, LPCWSTR text
, UINT length
, RECT
*rect
, DWORD flags
,
1596 COLORREF crText
, COLORREF crShadow
, int offset_x
, int offset_y
)
1602 FIXME("(%p, %s, %d, %p, 0x%08x, 0x%08x, 0x%08x, %d, %d): semi-stub\n", hdc
, debugstr_w(text
),
1603 length
, rect
, flags
, crText
, crShadow
, offset_x
, offset_y
);
1605 bkmode
= SetBkMode(hdc
, TRANSPARENT
);
1606 clr
= SetTextColor(hdc
, crShadow
);
1608 /* FIXME: for shadow we need to render normally, blur it, and blend with current background. */
1610 OffsetRect(&r
, 1, 1);
1611 DrawTextW(hdc
, text
, length
, &r
, flags
);
1613 SetTextColor(hdc
, crText
);
1615 /* with text color on top of a shadow */
1616 ret
= DrawTextW(hdc
, text
, length
, rect
, flags
);
1618 SetTextColor(hdc
, clr
);
1619 SetBkMode(hdc
, bkmode
);
1624 /***********************************************************************
1625 * TaskDialogIndirect [COMCTL32.@]
1627 HRESULT WINAPI
TaskDialogIndirect(const TASKDIALOGCONFIG
*pTaskConfig
, int *pnButton
,
1628 int *pnRadioButton
, BOOL
*pfVerificationFlagChecked
)
1632 FIXME("%p, %p, %p, %p\n", pTaskConfig
, pnButton
, pnRadioButton
, pfVerificationFlagChecked
);
1634 if (pTaskConfig
->dwCommonButtons
& TDCBF_YES_BUTTON
&&
1635 pTaskConfig
->dwCommonButtons
& TDCBF_NO_BUTTON
&&
1636 pTaskConfig
->dwCommonButtons
& TDCBF_CANCEL_BUTTON
)
1637 uType
|= MB_YESNOCANCEL
;
1639 if (pTaskConfig
->dwCommonButtons
& TDCBF_YES_BUTTON
&&
1640 pTaskConfig
->dwCommonButtons
& TDCBF_NO_BUTTON
)
1643 if (pTaskConfig
->dwCommonButtons
& TDCBF_RETRY_BUTTON
&&
1644 pTaskConfig
->dwCommonButtons
& TDCBF_CANCEL_BUTTON
)
1645 uType
|= MB_RETRYCANCEL
;
1647 if (pTaskConfig
->dwCommonButtons
& TDCBF_OK_BUTTON
&&
1648 pTaskConfig
->dwCommonButtons
& TDCBF_CANCEL_BUTTON
)
1649 uType
|= MB_OKCANCEL
;
1651 if (pTaskConfig
->dwCommonButtons
& TDCBF_OK_BUTTON
)
1653 ret
= MessageBoxW(pTaskConfig
->hwndParent
, pTaskConfig
->pszMainInstruction
,
1654 pTaskConfig
->pszWindowTitle
, uType
);
1655 FIXME("dwCommonButtons=%x uType=%x ret=%x\n", pTaskConfig
->dwCommonButtons
, uType
, ret
);
1657 if (pnButton
) *pnButton
= ret
;
1658 if (pnRadioButton
) *pnRadioButton
= pTaskConfig
->nDefaultButton
;
1659 if (pfVerificationFlagChecked
) *pfVerificationFlagChecked
= TRUE
;
1663 /***********************************************************************
1664 * LoadIconWithScaleDown [COMCTL32.@]
1666 HRESULT WINAPI
LoadIconWithScaleDown(HINSTANCE hinst
, const WCHAR
*name
, int cx
, int cy
, HICON
*icon
)
1668 TRACE("(%p, %s, %d, %d, %p)\n", hinst
, debugstr_w(name
), cx
, cy
, icon
);
1673 return E_INVALIDARG
;
1675 *icon
= LoadImageW(hinst
, name
, IMAGE_ICON
, cx
, cy
,
1676 (hinst
|| IS_INTRESOURCE(name
)) ? 0 : LR_LOADFROMFILE
);
1678 return HRESULT_FROM_WIN32(GetLastError());
1683 /***********************************************************************
1684 * LoadIconMetric [COMCTL32.@]
1686 HRESULT WINAPI
LoadIconMetric(HINSTANCE hinst
, const WCHAR
*name
, int size
, HICON
*icon
)
1690 TRACE("(%p, %s, %d, %p)\n", hinst
, debugstr_w(name
), size
, icon
);
1692 if (size
== LIM_SMALL
)
1694 cx
= GetSystemMetrics(SM_CXSMICON
);
1695 cy
= GetSystemMetrics(SM_CYSMICON
);
1697 else if (size
== LIM_LARGE
)
1699 cx
= GetSystemMetrics(SM_CXICON
);
1700 cy
= GetSystemMetrics(SM_CYICON
);
1705 return E_INVALIDARG
;
1708 return LoadIconWithScaleDown(hinst
, name
, cx
, cy
, icon
);