2 * Common controls functions
4 * Copyright 1997 Dimitrie O. Paun
5 * Copyright 1998,2000 Eric Kohl
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * This code was audited for completeness against the documented features
24 * of Comctl32.dll version 6.0 on Oct. 21, 2002, by Christian Neumair.
26 * Unless otherwise noted, we believe this code to be complete, as per
27 * the specification mentioned above.
28 * If you discover missing features, or bugs, please note them below.
31 * -- implement GetMUILanguage + InitMUILanguage
32 * -- LibMain => DLLMain ("DLLMain takes over the functionality of both the
33 * LibMain and the WEP function.", MSDN)
34 * -- finish NOTES for MenuHelp, GetEffectiveClientRect and GetStatusTextW
35 * -- FIXMEs + BUGS (search for them)
38 * -- ICC_ANIMATE_CLASS
43 * -- ICC_INTERNET_CLASSES
45 * -- ICC_LISTVIEW_CLASSES
46 * -- ICC_NATIVEFNTCTL_CLASS
47 * -- ICC_PAGESCROLLER_CLASS
48 * -- ICC_PROGRESS_CLASS
49 * -- ICC_STANDARD_CLASSES (not yet implemented)
51 * -- ICC_TREEVIEW_CLASSES
53 * -- ICC_USEREX_CLASSES
54 * -- ICC_WIN95_CLASSES
69 #define NO_SHLWAPI_STREAM
72 #include "wine/debug.h"
74 WINE_DEFAULT_DEBUG_CHANNEL(commctrl
);
76 extern void ANIMATE_Register(void);
77 extern void ANIMATE_Unregister(void);
78 extern void COMBOEX_Register(void);
79 extern void COMBOEX_Unregister(void);
80 extern void DATETIME_Register(void);
81 extern void DATETIME_Unregister(void);
82 extern void FLATSB_Register(void);
83 extern void FLATSB_Unregister(void);
84 extern void HEADER_Register(void);
85 extern void HEADER_Unregister(void);
86 extern void HOTKEY_Register(void);
87 extern void HOTKEY_Unregister(void);
88 extern void IPADDRESS_Register(void);
89 extern void IPADDRESS_Unregister(void);
90 extern void LISTVIEW_Register(void);
91 extern void LISTVIEW_Unregister(void);
92 extern void MONTHCAL_Register(void);
93 extern void MONTHCAL_Unregister(void);
94 extern void NATIVEFONT_Register(void);
95 extern void NATIVEFONT_Unregister(void);
96 extern void PAGER_Register(void);
97 extern void PAGER_Unregister(void);
98 extern void PROGRESS_Register(void);
99 extern void PROGRESS_Unregister(void);
100 extern void REBAR_Register(void);
101 extern void REBAR_Unregister(void);
102 extern void STATUS_Register(void);
103 extern void STATUS_Unregister(void);
104 extern void SYSLINK_Register(void);
105 extern void SYSLINK_Unregister(void);
106 extern void TAB_Register(void);
107 extern void TAB_Unregister(void);
108 extern void TOOLBAR_Register(void);
109 extern void TOOLBAR_Unregister(void);
110 extern void TOOLTIPS_Register(void);
111 extern void TOOLTIPS_Unregister(void);
112 extern void TRACKBAR_Register(void);
113 extern void TRACKBAR_Unregister(void);
114 extern void TREEVIEW_Register(void);
115 extern void TREEVIEW_Unregister(void);
116 extern void UPDOWN_Register(void);
117 extern void UPDOWN_Unregister(void);
119 LRESULT WINAPI
COMCTL32_SubclassProc (HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
);
121 LPWSTR COMCTL32_wSubclass
= NULL
;
122 HMODULE COMCTL32_hModule
= 0;
123 LANGID COMCTL32_uiLang
= MAKELANGID(LANG_NEUTRAL
, SUBLANG_NEUTRAL
);
124 HBRUSH COMCTL32_hPattern55AABrush
= NULL
;
125 COMCTL32_SysColor comctl32_color
;
127 static HBITMAP COMCTL32_hPattern55AABitmap
= NULL
;
129 static const WORD wPattern55AA
[] =
131 0x5555, 0xaaaa, 0x5555, 0xaaaa,
132 0x5555, 0xaaaa, 0x5555, 0xaaaa
135 static const WCHAR strCC32SubclassInfo
[] = {
136 'C','C','3','2','S','u','b','c','l','a','s','s','I','n','f','o',0
139 /***********************************************************************
142 * Initializes the internal 'COMCTL32.DLL'.
145 * hinstDLL [I] handle to the 'dlls' instance
147 * lpvReserved [I] reserverd, must be NULL
154 BOOL WINAPI
DllMain(HINSTANCE hinstDLL
, DWORD fdwReason
, LPVOID lpvReserved
)
156 TRACE("%p,%lx,%p\n", hinstDLL
, fdwReason
, lpvReserved
);
159 case DLL_PROCESS_ATTACH
:
160 DisableThreadLibraryCalls(hinstDLL
);
162 COMCTL32_hModule
= (HMODULE
)hinstDLL
;
164 /* add global subclassing atom (used by 'tooltip' and 'updown') */
165 COMCTL32_wSubclass
= (LPWSTR
)(DWORD
)GlobalAddAtomW (strCC32SubclassInfo
);
166 TRACE("Subclassing atom added: %p\n", COMCTL32_wSubclass
);
168 /* create local pattern brush */
169 COMCTL32_hPattern55AABitmap
= CreateBitmap (8, 8, 1, 1, wPattern55AA
);
170 COMCTL32_hPattern55AABrush
= CreatePatternBrush (COMCTL32_hPattern55AABitmap
);
172 /* Get all the colors at DLL load */
173 COMCTL32_RefreshSysColors();
175 /* register all Win95 common control classes */
180 LISTVIEW_Register ();
181 PROGRESS_Register ();
186 TOOLTIPS_Register ();
187 TRACKBAR_Register ();
188 TREEVIEW_Register ();
192 case DLL_PROCESS_DETACH
:
193 /* unregister all common control classes */
194 ANIMATE_Unregister ();
195 COMBOEX_Unregister ();
196 DATETIME_Unregister ();
197 FLATSB_Unregister ();
198 HEADER_Unregister ();
199 HOTKEY_Unregister ();
200 IPADDRESS_Unregister ();
201 LISTVIEW_Unregister ();
202 MONTHCAL_Unregister ();
203 NATIVEFONT_Unregister ();
205 PROGRESS_Unregister ();
207 STATUS_Unregister ();
208 SYSLINK_Unregister ();
210 TOOLBAR_Unregister ();
211 TOOLTIPS_Unregister ();
212 TRACKBAR_Unregister ();
213 TREEVIEW_Unregister ();
214 UPDOWN_Unregister ();
216 /* delete local pattern brush */
217 DeleteObject (COMCTL32_hPattern55AABrush
);
218 COMCTL32_hPattern55AABrush
= NULL
;
219 DeleteObject (COMCTL32_hPattern55AABitmap
);
220 COMCTL32_hPattern55AABitmap
= NULL
;
222 /* delete global subclassing atom */
223 GlobalDeleteAtom (LOWORD(COMCTL32_wSubclass
));
224 TRACE("Subclassing atom deleted: %p\n", COMCTL32_wSubclass
);
225 COMCTL32_wSubclass
= NULL
;
233 /***********************************************************************
234 * MenuHelp [COMCTL32.2]
236 * Handles the setting of status bar help messages when the user
237 * selects menu items.
240 * uMsg [I] message (WM_MENUSELECT) (see NOTES)
241 * wParam [I] wParam of the message uMsg
242 * lParam [I] lParam of the message uMsg
243 * hMainMenu [I] handle to the application's main menu
244 * hInst [I] handle to the module that contains string resources
245 * hwndStatus [I] handle to the status bar window
246 * lpwIDs [I] pointer to an array of integers (see NOTES)
252 * The official documentation is incomplete!
253 * This is the correct documentation:
256 * MenuHelp() does NOT handle WM_COMMAND messages! It only handles
257 * WM_MENUSELECT messages.
260 * (will be written ...)
264 MenuHelp (UINT uMsg
, WPARAM wParam
, LPARAM lParam
, HMENU hMainMenu
,
265 HINSTANCE hInst
, HWND hwndStatus
, UINT
* lpwIDs
)
269 if (!IsWindow (hwndStatus
))
274 TRACE("WM_MENUSELECT wParam=0x%X lParam=0x%lX\n",
277 if ((HIWORD(wParam
) == 0xFFFF) && (lParam
== 0)) {
278 /* menu was closed */
279 TRACE("menu was closed!\n");
280 SendMessageW (hwndStatus
, SB_SIMPLE
, FALSE
, 0);
283 /* menu item was selected */
284 if (HIWORD(wParam
) & MF_POPUP
)
285 uMenuID
= (UINT
)*(lpwIDs
+1);
287 uMenuID
= (UINT
)LOWORD(wParam
);
288 TRACE("uMenuID = %u\n", uMenuID
);
293 if (!LoadStringW (hInst
, uMenuID
, szText
, sizeof(szText
)/sizeof(szText
[0])))
296 SendMessageW (hwndStatus
, SB_SETTEXTW
,
297 255 | SBT_NOBORDERS
, (LPARAM
)szText
);
298 SendMessageW (hwndStatus
, SB_SIMPLE
, TRUE
, 0);
304 TRACE("WM_COMMAND wParam=0x%X lParam=0x%lX\n",
306 /* WM_COMMAND is not invalid since it is documented
307 * in the windows api reference. So don't output
308 * any FIXME for WM_COMMAND
310 WARN("We don't care about the WM_COMMAND\n");
314 FIXME("Invalid Message 0x%x!\n", uMsg
);
320 /***********************************************************************
321 * ShowHideMenuCtl [COMCTL32.3]
323 * Shows or hides controls and updates the corresponding menu item.
326 * hwnd [I] handle to the client window.
327 * uFlags [I] menu command id.
328 * lpInfo [I] pointer to an array of integers. (See NOTES.)
335 * The official documentation is incomplete!
336 * This is the correct documentation:
339 * Handle to the window that contains the menu and controls.
342 * Identifier of the menu item to receive or lose a check mark.
345 * The array of integers contains pairs of values. BOTH values of
346 * the first pair must be the handles to the application's main menu.
347 * Each subsequent pair consists of a menu id and control id.
351 ShowHideMenuCtl (HWND hwnd
, UINT uFlags
, LPINT lpInfo
)
355 TRACE("%p, %x, %p\n", hwnd
, uFlags
, lpInfo
);
360 if (!(lpInfo
[0]) || !(lpInfo
[1]))
363 /* search for control */
364 lpMenuId
= &lpInfo
[2];
365 while (*lpMenuId
!= uFlags
)
368 if (GetMenuState ((HMENU
)lpInfo
[1], uFlags
, MF_BYCOMMAND
) & MFS_CHECKED
) {
369 /* uncheck menu item */
370 CheckMenuItem ((HMENU
)lpInfo
[0], *lpMenuId
, MF_BYCOMMAND
| MF_UNCHECKED
);
374 SetWindowPos (GetDlgItem (hwnd
, *lpMenuId
), 0, 0, 0, 0, 0,
378 /* check menu item */
379 CheckMenuItem ((HMENU
)lpInfo
[0], *lpMenuId
, MF_BYCOMMAND
| MF_CHECKED
);
383 SetWindowPos (GetDlgItem (hwnd
, *lpMenuId
), 0, 0, 0, 0, 0,
391 /***********************************************************************
392 * GetEffectiveClientRect [COMCTL32.4]
394 * Calculates the coordinates of a rectangle in the client area.
397 * hwnd [I] handle to the client window.
398 * lpRect [O] pointer to the rectangle of the client window
399 * lpInfo [I] pointer to an array of integers (see NOTES)
405 * The official documentation is incomplete!
406 * This is the correct documentation:
409 * (will be written ...)
413 GetEffectiveClientRect (HWND hwnd
, LPRECT lpRect
, LPINT lpInfo
)
419 TRACE("(0x%08lx 0x%08lx 0x%08lx)\n",
420 (DWORD
)hwnd
, (DWORD
)lpRect
, (DWORD
)lpInfo
);
422 GetClientRect (hwnd
, lpRect
);
430 hwndCtrl
= GetDlgItem (hwnd
, *lpRun
);
431 if (GetWindowLongW (hwndCtrl
, GWL_STYLE
) & WS_VISIBLE
) {
432 TRACE("control id 0x%x\n", *lpRun
);
433 GetWindowRect (hwndCtrl
, &rcCtrl
);
434 MapWindowPoints (NULL
, hwnd
, (LPPOINT
)&rcCtrl
, 2);
435 SubtractRect (lpRect
, lpRect
, &rcCtrl
);
442 /***********************************************************************
443 * DrawStatusTextW [COMCTL32.@]
445 * Draws text with borders, like in a status bar.
448 * hdc [I] handle to the window's display context
449 * lprc [I] pointer to a rectangle
450 * text [I] pointer to the text
451 * style [I] drawing style
457 * The style variable can have one of the following values:
458 * (will be written ...)
461 void WINAPI
DrawStatusTextW (HDC hdc
, LPRECT lprc
, LPCWSTR text
, UINT style
)
464 UINT border
= BDR_SUNKENOUTER
;
466 if (style
& SBT_POPOUT
)
467 border
= BDR_RAISEDOUTER
;
468 else if (style
& SBT_NOBORDERS
)
471 DrawEdge (hdc
, &r
, border
, BF_RECT
|BF_ADJUST
);
475 int oldbkmode
= SetBkMode (hdc
, TRANSPARENT
);
476 UINT align
= DT_LEFT
;
477 if (*text
== L
'\t') {
480 if (*text
== L
'\t') {
486 if (style
& SBT_RTLREADING
)
487 FIXME("Unsupported RTL style!\n");
488 DrawTextW (hdc
, text
, -1, &r
, align
|DT_VCENTER
|DT_SINGLELINE
|DT_NOPREFIX
);
489 SetBkMode(hdc
, oldbkmode
);
494 /***********************************************************************
495 * DrawStatusText [COMCTL32.@]
496 * DrawStatusTextA [COMCTL32.5]
498 * Draws text with borders, like in a status bar.
501 * hdc [I] handle to the window's display context
502 * lprc [I] pointer to a rectangle
503 * text [I] pointer to the text
504 * style [I] drawing style
510 void WINAPI
DrawStatusTextA (HDC hdc
, LPRECT lprc
, LPCSTR text
, UINT style
)
516 if ( (len
= MultiByteToWideChar( CP_ACP
, 0, text
, -1, NULL
, 0 )) ) {
517 if ( (textW
= Alloc( len
* sizeof(WCHAR
) )) )
518 MultiByteToWideChar( CP_ACP
, 0, text
, -1, textW
, len
);
521 DrawStatusTextW( hdc
, lprc
, textW
, style
);
526 /***********************************************************************
527 * CreateStatusWindow [COMCTL32.@]
528 * CreateStatusWindowA [COMCTL32.6]
530 * Creates a status bar
533 * style [I] window style
534 * text [I] pointer to the window text
535 * parent [I] handle to the parent window
536 * wid [I] control id of the status bar
539 * Success: handle to the status window
544 CreateStatusWindowA (LONG style
, LPCSTR text
, HWND parent
, UINT wid
)
546 return CreateWindowA(STATUSCLASSNAMEA
, text
, style
,
547 CW_USEDEFAULT
, CW_USEDEFAULT
,
548 CW_USEDEFAULT
, CW_USEDEFAULT
,
549 parent
, (HMENU
)wid
, 0, 0);
553 /***********************************************************************
554 * CreateStatusWindowW [COMCTL32.@]
556 * Creates a status bar control
559 * style [I] window style
560 * text [I] pointer to the window text
561 * parent [I] handle to the parent window
562 * wid [I] control id of the status bar
565 * Success: handle to the status window
570 CreateStatusWindowW (LONG style
, LPCWSTR text
, HWND parent
, UINT wid
)
572 return CreateWindowW(STATUSCLASSNAMEW
, text
, style
,
573 CW_USEDEFAULT
, CW_USEDEFAULT
,
574 CW_USEDEFAULT
, CW_USEDEFAULT
,
575 parent
, (HMENU
)wid
, 0, 0);
579 /***********************************************************************
580 * CreateUpDownControl [COMCTL32.16]
582 * Creates an up-down control
585 * style [I] window styles
586 * x [I] horizontal position of the control
587 * y [I] vertical position of the control
588 * cx [I] with of the control
589 * cy [I] height of the control
590 * parent [I] handle to the parent window
591 * id [I] the control's identifier
592 * inst [I] handle to the application's module instance
593 * buddy [I] handle to the buddy window, can be NULL
594 * maxVal [I] upper limit of the control
595 * minVal [I] lower limit of the control
596 * curVal [I] current value of the control
599 * Success: handle to the updown control
604 CreateUpDownControl (DWORD style
, INT x
, INT y
, INT cx
, INT cy
,
605 HWND parent
, INT id
, HINSTANCE inst
,
606 HWND buddy
, INT maxVal
, INT minVal
, INT curVal
)
609 CreateWindowW (UPDOWN_CLASSW
, 0, style
, x
, y
, cx
, cy
,
610 parent
, (HMENU
)id
, inst
, 0);
612 SendMessageW (hUD
, UDM_SETBUDDY
, (WPARAM
)buddy
, 0);
613 SendMessageW (hUD
, UDM_SETRANGE
, 0, MAKELONG(maxVal
, minVal
));
614 SendMessageW (hUD
, UDM_SETPOS
, 0, MAKELONG(curVal
, 0));
621 /***********************************************************************
622 * InitCommonControls [COMCTL32.17]
624 * Registers the common controls.
633 * This function is just a dummy.
634 * The Win95 controls are registered at the DLL's initialization.
635 * To register other controls InitCommonControlsEx() must be used.
639 InitCommonControls (void)
644 /***********************************************************************
645 * InitCommonControlsEx [COMCTL32.@]
647 * Registers the common controls.
650 * lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
657 * Only the additional common controls are registered by this function.
658 * The Win95 controls are registered at the DLL's initialization.
661 * implement the following control classes:
663 * ICC_STANDARD_CLASSES
667 InitCommonControlsEx (LPINITCOMMONCONTROLSEX lpInitCtrls
)
674 if (lpInitCtrls
->dwSize
!= sizeof(INITCOMMONCONTROLSEX
))
677 TRACE("(0x%08lx)\n", lpInitCtrls
->dwICC
);
679 for (cCount
= 0; cCount
< 32; cCount
++) {
680 dwMask
= 1 << cCount
;
681 if (!(lpInitCtrls
->dwICC
& dwMask
))
684 switch (lpInitCtrls
->dwICC
& dwMask
) {
685 /* dummy initialization */
686 case ICC_ANIMATE_CLASS
:
687 case ICC_BAR_CLASSES
:
688 case ICC_LISTVIEW_CLASSES
:
689 case ICC_TREEVIEW_CLASSES
:
690 case ICC_TAB_CLASSES
:
691 case ICC_UPDOWN_CLASS
:
692 case ICC_PROGRESS_CLASS
:
693 case ICC_HOTKEY_CLASS
:
696 /* advanced classes - not included in Win95 */
697 case ICC_DATE_CLASSES
:
698 MONTHCAL_Register ();
699 DATETIME_Register ();
702 case ICC_USEREX_CLASSES
:
706 case ICC_COOL_CLASSES
:
710 case ICC_INTERNET_CLASSES
:
711 IPADDRESS_Register ();
714 case ICC_PAGESCROLLER_CLASS
:
718 case ICC_NATIVEFNTCTL_CLASS
:
719 NATIVEFONT_Register ();
727 FIXME("Unknown class! dwICC=0x%lX\n", dwMask
);
736 /***********************************************************************
737 * CreateToolbarEx [COMCTL32.@]
739 * Creates a toolbar window.
757 * Success: handle to the tool bar control
762 CreateToolbarEx (HWND hwnd
, DWORD style
, UINT wID
, INT nBitmaps
,
763 HINSTANCE hBMInst
, UINT wBMID
, LPCTBBUTTON lpButtons
,
764 INT iNumButtons
, INT dxButton
, INT dyButton
,
765 INT dxBitmap
, INT dyBitmap
, UINT uStructSize
)
770 CreateWindowExW(0, TOOLBARCLASSNAMEW
, NULL
, style
|WS_CHILD
, 0,0,100,30,
771 hwnd
, (HMENU
)wID
, COMCTL32_hModule
, NULL
);
775 SendMessageW (hwndTB
, TB_BUTTONSTRUCTSIZE
, (WPARAM
)uStructSize
, 0);
777 /* set bitmap and button size */
778 /*If CreateToolbarEx receives 0, windows sets default values*/
783 SendMessageW (hwndTB
, TB_SETBITMAPSIZE
, 0,
784 MAKELPARAM((WORD
)dxBitmap
, (WORD
)dyBitmap
));
790 SendMessageW (hwndTB
, TB_SETBUTTONSIZE
, 0,
791 MAKELPARAM((WORD
)dxButton
, (WORD
)dyButton
));
797 tbab
.hInst
= hBMInst
;
800 SendMessageW (hwndTB
, TB_ADDBITMAP
, (WPARAM
)nBitmaps
, (LPARAM
)&tbab
);
804 SendMessageW (hwndTB
, TB_ADDBUTTONSW
,
805 (WPARAM
)iNumButtons
, (LPARAM
)lpButtons
);
812 /***********************************************************************
813 * CreateMappedBitmap [COMCTL32.8]
815 * Loads a bitmap resource using a colour map.
818 * hInstance [I] Handle to the module containing the bitmap.
819 * idBitmap [I] The bitmap resource ID.
820 * wFlags [I] CMB_MASKED for using bitmap as a mask or 0 for normal.
821 * lpColorMap [I] Colour information needed for the bitmap or NULL (uses system colours).
822 * iNumMaps [I] Number of COLORMAP's pointed to by lpColorMap.
825 * Success: handle to the new bitmap
830 CreateMappedBitmap (HINSTANCE hInstance
, INT idBitmap
, UINT wFlags
,
831 LPCOLORMAP lpColorMap
, INT iNumMaps
)
835 LPBITMAPINFOHEADER lpBitmap
, lpBitmapInfo
;
836 UINT nSize
, nColorTableSize
, iColor
;
837 RGBQUAD
*pColorTable
;
838 INT i
, iMaps
, nWidth
, nHeight
;
841 LPCOLORMAP sysColorMap
;
843 COLORMAP internalColorMap
[4] =
844 {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
846 /* initialize pointer to colortable and default color table */
849 sysColorMap
= lpColorMap
;
852 internalColorMap
[0].to
= GetSysColor (COLOR_BTNTEXT
);
853 internalColorMap
[1].to
= GetSysColor (COLOR_BTNSHADOW
);
854 internalColorMap
[2].to
= GetSysColor (COLOR_BTNFACE
);
855 internalColorMap
[3].to
= GetSysColor (COLOR_BTNHIGHLIGHT
);
857 sysColorMap
= (LPCOLORMAP
)internalColorMap
;
860 hRsrc
= FindResourceW (hInstance
, (LPWSTR
)idBitmap
, (LPWSTR
)RT_BITMAP
);
863 hglb
= LoadResource (hInstance
, hRsrc
);
866 lpBitmap
= (LPBITMAPINFOHEADER
)LockResource (hglb
);
867 if (lpBitmap
== NULL
)
870 if (lpBitmap
->biSize
>= sizeof(BITMAPINFOHEADER
) && lpBitmap
->biClrUsed
)
871 nColorTableSize
= lpBitmap
->biClrUsed
;
872 else if (lpBitmap
->biBitCount
<= 8)
873 nColorTableSize
= (1 << lpBitmap
->biBitCount
);
876 nSize
= lpBitmap
->biSize
+ nColorTableSize
* sizeof(RGBQUAD
);
877 lpBitmapInfo
= (LPBITMAPINFOHEADER
)GlobalAlloc (GMEM_FIXED
, nSize
);
878 if (lpBitmapInfo
== NULL
)
880 RtlMoveMemory (lpBitmapInfo
, lpBitmap
, nSize
);
882 pColorTable
= (RGBQUAD
*)(((LPBYTE
)lpBitmapInfo
)+(UINT
)lpBitmapInfo
->biSize
);
884 for (iColor
= 0; iColor
< nColorTableSize
; iColor
++) {
885 for (i
= 0; i
< iMaps
; i
++) {
886 cRef
= RGB(pColorTable
[iColor
].rgbRed
,
887 pColorTable
[iColor
].rgbGreen
,
888 pColorTable
[iColor
].rgbBlue
);
889 if ( cRef
== sysColorMap
[i
].from
) {
891 if (wFlags
& CBS_MASKED
) {
892 if (sysColorMap
[i
].to
!= COLOR_BTNTEXT
)
893 pColorTable
[iColor
] = RGB(255, 255, 255);
897 pColorTable
[iColor
].rgbBlue
= GetBValue(sysColorMap
[i
].to
);
898 pColorTable
[iColor
].rgbGreen
= GetGValue(sysColorMap
[i
].to
);
899 pColorTable
[iColor
].rgbRed
= GetRValue(sysColorMap
[i
].to
);
904 nWidth
= (INT
)lpBitmapInfo
->biWidth
;
905 nHeight
= (INT
)lpBitmapInfo
->biHeight
;
906 hdcScreen
= GetDC (NULL
);
907 hbm
= CreateCompatibleBitmap (hdcScreen
, nWidth
, nHeight
);
909 HDC hdcDst
= CreateCompatibleDC (hdcScreen
);
910 HBITMAP hbmOld
= SelectObject (hdcDst
, hbm
);
911 LPBYTE lpBits
= (LPBYTE
)(lpBitmap
+ 1);
912 lpBits
+= nColorTableSize
* sizeof(RGBQUAD
);
913 StretchDIBits (hdcDst
, 0, 0, nWidth
, nHeight
, 0, 0, nWidth
, nHeight
,
914 lpBits
, (LPBITMAPINFO
)lpBitmapInfo
, DIB_RGB_COLORS
,
916 SelectObject (hdcDst
, hbmOld
);
919 ReleaseDC (NULL
, hdcScreen
);
920 GlobalFree ((HGLOBAL
)lpBitmapInfo
);
927 /***********************************************************************
928 * CreateToolbar [COMCTL32.7]
930 * Creates a toolbar control.
943 * Success: handle to the tool bar control
947 * Do not use this functions anymore. Use CreateToolbarEx instead.
951 CreateToolbar (HWND hwnd
, DWORD style
, UINT wID
, INT nBitmaps
,
952 HINSTANCE hBMInst
, UINT wBMID
,
953 LPCTBBUTTON lpButtons
,INT iNumButtons
)
955 return CreateToolbarEx (hwnd
, style
| CCS_NODIVIDER
, wID
, nBitmaps
,
956 hBMInst
, wBMID
, lpButtons
,
957 iNumButtons
, 0, 0, 0, 0, CCSIZEOF_STRUCT(TBBUTTON
, dwData
));
961 /***********************************************************************
962 * DllGetVersion [COMCTL32.@]
964 * Retrieves version information of the 'COMCTL32.DLL'
967 * pdvi [O] pointer to version information structure.
971 * Failure: E_INVALIDARG
974 * Returns version of a comctl32.dll from IE4.01 SP1.
978 COMCTL32_DllGetVersion (DLLVERSIONINFO
*pdvi
)
980 if (pdvi
->cbSize
!= sizeof(DLLVERSIONINFO
)) {
981 WARN("wrong DLLVERSIONINFO size from app\n");
985 pdvi
->dwMajorVersion
= COMCTL32_VERSION
;
986 pdvi
->dwMinorVersion
= COMCTL32_VERSION_MINOR
;
987 pdvi
->dwBuildNumber
= 2919;
988 pdvi
->dwPlatformID
= 6304;
990 TRACE("%lu.%lu.%lu.%lu\n",
991 pdvi
->dwMajorVersion
, pdvi
->dwMinorVersion
,
992 pdvi
->dwBuildNumber
, pdvi
->dwPlatformID
);
997 /***********************************************************************
998 * DllInstall (COMCTL32.@)
1000 * Installs the ComCtl32 DLL.
1004 * Failure: A HRESULT error
1006 HRESULT WINAPI
COMCTL32_DllInstall(BOOL bInstall
, LPCWSTR cmdline
)
1008 FIXME("(%s, %s): stub\n", bInstall
?"TRUE":"FALSE",
1009 debugstr_w(cmdline
));
1014 /***********************************************************************
1015 * _TrackMouseEvent [COMCTL32.@]
1017 * Requests notification of mouse events
1019 * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
1020 * to the hwnd specified in the ptme structure. After the event message
1021 * is posted to the hwnd, the entry in the queue is removed.
1023 * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
1024 * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
1025 * immediately and the TME_LEAVE flag being ignored.
1028 * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
1034 * IMPLEMENTATION moved to USER32.TrackMouseEvent
1039 _TrackMouseEvent (TRACKMOUSEEVENT
*ptme
)
1041 return TrackMouseEvent (ptme
);
1044 /*************************************************************************
1045 * GetMUILanguage [COMCTL32.@]
1047 * Returns the user interface language in use by the current process.
1050 * Language ID in use by the current process.
1052 LANGID WINAPI
GetMUILanguage (VOID
)
1054 return COMCTL32_uiLang
;
1058 /*************************************************************************
1059 * InitMUILanguage [COMCTL32.@]
1061 * Sets the user interface language to be used by the current process.
1066 VOID WINAPI
InitMUILanguage (LANGID uiLang
)
1068 COMCTL32_uiLang
= uiLang
;
1072 /***********************************************************************
1073 * SetWindowSubclass [COMCTL32.410]
1075 * Starts a window subclass
1078 * hWnd [in] handle to window subclass.
1079 * pfnSubclass [in] Pointer to new window procedure.
1080 * uIDSubclass [in] Unique identifier of sublass together with pfnSubclass.
1081 * dwRef [in] Reference data to pass to window procedure.
1088 * If an application manually subclasses a window after subclassing it with
1089 * this API and then with this API again, then none of the previous
1090 * subclasses get called or the origional window procedure.
1093 BOOL WINAPI
SetWindowSubclass (HWND hWnd
, SUBCLASSPROC pfnSubclass
,
1094 UINT_PTR uIDSubclass
, DWORD_PTR dwRef
)
1096 LPSUBCLASS_INFO stack
;
1097 LPSUBCLASSPROCS proc
;
1099 TRACE ("(%p, %p, %x, %lx)\n", hWnd
, pfnSubclass
, uIDSubclass
, dwRef
);
1101 /* Since the window procedure that we set here has two additional arguments,
1102 * we can't simply set it as the new window procedure of the window. So we
1103 * set our own window procedure and then calculate the other two arguments
1106 /* See if we have been called for this window */
1107 stack
= (LPSUBCLASS_INFO
)GetPropW (hWnd
, COMCTL32_wSubclass
);
1109 /* allocate stack */
1110 stack
= Alloc (sizeof(SUBCLASS_INFO
));
1112 ERR ("Failed to allocate our Subclassing stack\n");
1115 SetPropW (hWnd
, COMCTL32_wSubclass
, (HANDLE
)stack
);
1117 /* set window procedure to our own and save the current one */
1118 if (IsWindowUnicode (hWnd
))
1119 stack
->origproc
= (WNDPROC
)SetWindowLongPtrW (hWnd
, GWLP_WNDPROC
,
1120 (DWORD_PTR
)COMCTL32_SubclassProc
);
1122 stack
->origproc
= (WNDPROC
)SetWindowLongPtrA (hWnd
, GWLP_WNDPROC
,
1123 (DWORD_PTR
)COMCTL32_SubclassProc
);
1126 /* Check to see if we have called this function with the same uIDSubClass
1127 * and pfnSubclass */
1128 proc
= stack
->SubclassProcs
;
1130 if ((proc
->id
== uIDSubclass
) &&
1131 (proc
->subproc
== pfnSubclass
)) {
1139 proc
= Alloc(sizeof(SUBCLASSPROCS
));
1141 ERR ("Failed to allocate subclass entry in stack\n");
1142 if (IsWindowUnicode (hWnd
))
1143 SetWindowLongPtrW (hWnd
, GWLP_WNDPROC
, (DWORD_PTR
)stack
->origproc
);
1145 SetWindowLongPtrA (hWnd
, GWLP_WNDPROC
, (DWORD_PTR
)stack
->origproc
);
1147 RemovePropW( hWnd
, COMCTL32_wSubclass
);
1151 proc
->subproc
= pfnSubclass
;
1153 proc
->id
= uIDSubclass
;
1154 proc
->next
= stack
->SubclassProcs
;
1155 stack
->SubclassProcs
= proc
;
1161 /***********************************************************************
1162 * GetWindowSubclass [COMCTL32.411]
1164 * Gets the Reference data from a subclass.
1167 * hWnd [in] Handle to window which were subclassing
1168 * pfnSubclass [in] Pointer to the subclass procedure
1169 * uID [in] Unique indentifier of the subclassing procedure
1170 * pdwRef [out] Pointer to the reference data
1177 BOOL WINAPI
GetWindowSubclass (HWND hWnd
, SUBCLASSPROC pfnSubclass
,
1178 UINT_PTR uID
, DWORD_PTR
*pdwRef
)
1180 LPSUBCLASS_INFO stack
;
1181 LPSUBCLASSPROCS proc
;
1183 TRACE ("(%p, %p, %x, %p)\n", hWnd
, pfnSubclass
, uID
, pdwRef
);
1185 /* See if we have been called for this window */
1186 stack
= (LPSUBCLASS_INFO
)GetPropW (hWnd
, COMCTL32_wSubclass
);
1190 proc
= stack
->SubclassProcs
;
1192 if ((proc
->id
== uID
) &&
1193 (proc
->subproc
== pfnSubclass
)) {
1194 *pdwRef
= proc
->ref
;
1204 /***********************************************************************
1205 * RemoveWindowSubclass [COMCTL32.412]
1207 * Removes a window subclass.
1210 * hWnd [in] Handle to the window were subclassing
1211 * pfnSubclass [in] Pointer to the subclass procedure
1212 * uID [in] Unique identifier of this subclass
1219 BOOL WINAPI
RemoveWindowSubclass(HWND hWnd
, SUBCLASSPROC pfnSubclass
, UINT_PTR uID
)
1221 LPSUBCLASS_INFO stack
;
1222 LPSUBCLASSPROCS prevproc
= NULL
;
1223 LPSUBCLASSPROCS proc
;
1226 TRACE ("(%p, %p, %x)\n", hWnd
, pfnSubclass
, uID
);
1228 /* Find the Subclass to remove */
1229 stack
= (LPSUBCLASS_INFO
)GetPropW (hWnd
, COMCTL32_wSubclass
);
1233 proc
= stack
->SubclassProcs
;
1235 if ((proc
->id
== uID
) &&
1236 (proc
->subproc
== pfnSubclass
)) {
1239 stack
->SubclassProcs
= proc
->next
;
1241 prevproc
->next
= proc
->next
;
1243 if (stack
->stackpos
== proc
)
1244 stack
->stackpos
= stack
->stackpos
->next
;
1254 if (!stack
->SubclassProcs
&& !stack
->running
) {
1255 TRACE("Last Subclass removed, cleaning up\n");
1256 /* clean up our heap and reset the origional window procedure */
1257 if (IsWindowUnicode (hWnd
))
1258 SetWindowLongPtrW (hWnd
, GWLP_WNDPROC
, (DWORD_PTR
)stack
->origproc
);
1260 SetWindowLongPtrA (hWnd
, GWLP_WNDPROC
, (DWORD_PTR
)stack
->origproc
);
1262 RemovePropW( hWnd
, COMCTL32_wSubclass
);
1268 /***********************************************************************
1269 * COMCTL32_SubclassProc (internal)
1271 * Window procedure for all subclassed windows.
1272 * Saves the current subclassing stack position to support nested messages
1274 LRESULT WINAPI
COMCTL32_SubclassProc (HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1276 LPSUBCLASS_INFO stack
;
1277 LPSUBCLASSPROCS proc
;
1280 TRACE ("(%p, 0x%08x, 0x%08x, 0x%08lx)\n", hWnd
, uMsg
, wParam
, lParam
);
1282 stack
= (LPSUBCLASS_INFO
)GetPropW (hWnd
, COMCTL32_wSubclass
);
1284 ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd
);
1288 /* Save our old stackpos to properly handle nested messages */
1289 proc
= stack
->stackpos
;
1290 stack
->stackpos
= stack
->SubclassProcs
;
1292 ret
= DefSubclassProc(hWnd
, uMsg
, wParam
, lParam
);
1294 stack
->stackpos
= proc
;
1296 if (!stack
->SubclassProcs
&& !stack
->running
) {
1297 TRACE("Last Subclass removed, cleaning up\n");
1298 /* clean up our heap and reset the origional window procedure */
1299 if (IsWindowUnicode (hWnd
))
1300 SetWindowLongPtrW (hWnd
, GWLP_WNDPROC
, (DWORD_PTR
)stack
->origproc
);
1302 SetWindowLongPtrA (hWnd
, GWLP_WNDPROC
, (DWORD_PTR
)stack
->origproc
);
1304 RemovePropW( hWnd
, COMCTL32_wSubclass
);
1309 /***********************************************************************
1310 * DefSubclassProc [COMCTL32.413]
1312 * Calls the next window procedure (ie. the one before this subclass)
1315 * hWnd [in] The window that we're subclassing
1317 * wParam [in] WPARAM
1318 * lParam [in] LPARAM
1325 LRESULT WINAPI
DefSubclassProc (HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1327 LPSUBCLASS_INFO stack
;
1330 TRACE ("(%p, 0x%08x, 0x%08x, 0x%08lx)\n", hWnd
, uMsg
, wParam
, lParam
);
1332 /* retrieve our little stack from the Properties */
1333 stack
= (LPSUBCLASS_INFO
)GetPropW (hWnd
, COMCTL32_wSubclass
);
1335 ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd
);
1339 /* If we are at the end of stack then we have to call the original
1340 * window procedure */
1341 if (!stack
->stackpos
) {
1342 if (IsWindowUnicode (hWnd
))
1343 ret
= CallWindowProcW (stack
->origproc
, hWnd
, uMsg
, wParam
, lParam
);
1345 ret
= CallWindowProcA (stack
->origproc
, hWnd
, uMsg
, wParam
, lParam
);
1347 LPSUBCLASSPROCS proc
= stack
->stackpos
;
1348 stack
->stackpos
= stack
->stackpos
->next
;
1349 /* call the Subclass procedure from the stack */
1350 ret
= proc
->subproc (hWnd
, uMsg
, wParam
, lParam
,
1351 proc
->id
, proc
->ref
);
1358 /***********************************************************************
1359 * COMCTL32_CreateToolTip [NOT AN API]
1361 * Creates a tooltip for the control specified in hwnd and does all
1362 * necessary setup and notifications.
1365 * hwndOwner [I] Handle to the window that will own the tool tip.
1368 * Success: Handle of tool tip window.
1373 COMCTL32_CreateToolTip(HWND hwndOwner
)
1377 hwndToolTip
= CreateWindowExW(0, TOOLTIPS_CLASSW
, NULL
, 0,
1378 CW_USEDEFAULT
, CW_USEDEFAULT
,
1379 CW_USEDEFAULT
, CW_USEDEFAULT
, hwndOwner
,
1382 /* Send NM_TOOLTIPSCREATED notification */
1385 NMTOOLTIPSCREATED nmttc
;
1386 /* true owner can be different if hwndOwner is a child window */
1387 HWND hwndTrueOwner
= GetWindow(hwndToolTip
, GW_OWNER
);
1388 nmttc
.hdr
.hwndFrom
= hwndTrueOwner
;
1389 nmttc
.hdr
.idFrom
= GetWindowLongPtrW(hwndTrueOwner
, GWLP_ID
);
1390 nmttc
.hdr
.code
= NM_TOOLTIPSCREATED
;
1391 nmttc
.hwndToolTips
= hwndToolTip
;
1393 SendMessageW(GetParent(hwndTrueOwner
), WM_NOTIFY
,
1394 (WPARAM
)GetWindowLongPtrW(hwndTrueOwner
, GWLP_ID
),
1402 /***********************************************************************
1403 * COMCTL32_RefreshSysColors [NOT AN API]
1405 * Invoked on any control recognizing a WM_SYSCOLORCHANGE message to
1406 * refresh the color values in the color structure
1416 COMCTL32_RefreshSysColors(void)
1418 comctl32_color
.clrBtnHighlight
= GetSysColor (COLOR_BTNHIGHLIGHT
);
1419 comctl32_color
.clrBtnShadow
= GetSysColor (COLOR_BTNSHADOW
);
1420 comctl32_color
.clrBtnText
= GetSysColor (COLOR_BTNTEXT
);
1421 comctl32_color
.clrBtnFace
= GetSysColor (COLOR_BTNFACE
);
1422 comctl32_color
.clrHighlight
= GetSysColor (COLOR_HIGHLIGHT
);
1423 comctl32_color
.clrHighlightText
= GetSysColor (COLOR_HIGHLIGHTTEXT
);
1424 comctl32_color
.clr3dHilight
= GetSysColor (COLOR_3DHILIGHT
);
1425 comctl32_color
.clr3dShadow
= GetSysColor (COLOR_3DSHADOW
);
1426 comctl32_color
.clr3dDkShadow
= GetSysColor (COLOR_3DDKSHADOW
);
1427 comctl32_color
.clr3dFace
= GetSysColor (COLOR_3DFACE
);
1428 comctl32_color
.clrWindow
= GetSysColor (COLOR_WINDOW
);
1429 comctl32_color
.clrWindowText
= GetSysColor (COLOR_WINDOWTEXT
);
1430 comctl32_color
.clrGrayText
= GetSysColor (COLOR_GRAYTEXT
);
1431 comctl32_color
.clrActiveCaption
= GetSysColor (COLOR_ACTIVECAPTION
);
1432 comctl32_color
.clrInfoBk
= GetSysColor (COLOR_INFOBK
);
1433 comctl32_color
.clrInfoText
= GetSysColor (COLOR_INFOTEXT
);
1436 /***********************************************************************
1437 * COMCTL32_DrawInsertMark [NOT AN API]
1439 * Draws an insertion mark (which looks similar to an 'I').
1442 * hDC [I] Device context to draw onto.
1443 * lpRect [I] Co-ordinates of insertion mark.
1444 * clrInsertMark [I] Colour of the insertion mark.
1445 * bHorizontal [I] True if insert mark should be drawn horizontally,
1446 * vertical otherwise.
1452 * Draws up to but not including the bottom co-ordinate when drawing
1453 * vertically or the right co-ordinate when horizontal.
1455 void COMCTL32_DrawInsertMark(HDC hDC
, const RECT
*lpRect
, COLORREF clrInsertMark
, BOOL bHorizontal
)
1457 HPEN hPen
= CreatePen(PS_SOLID
, 1, clrInsertMark
);
1459 static const DWORD adwPolyPoints
[] = {4,4,4};
1460 LONG lCentre
= (bHorizontal
?
1461 lpRect
->top
+ (lpRect
->bottom
- lpRect
->top
)/2 :
1462 lpRect
->left
+ (lpRect
->right
- lpRect
->left
)/2);
1463 LONG l1
= (bHorizontal
? lpRect
->left
: lpRect
->top
);
1464 LONG l2
= (bHorizontal
? lpRect
->right
: lpRect
->bottom
);
1465 const POINT aptInsertMark
[] =
1467 /* top (V) or left (H) arrow */
1471 {lCentre
+ 1, l1
+ 2},
1475 {lCentre
+ 1, l1
- 1},
1476 {lCentre
+ 1, l2
- 2},
1477 /* bottom (V) or right (H) arrow */
1479 {lCentre
- 2, l2
- 1},
1480 {lCentre
+ 3, l2
- 1},
1481 {lCentre
+ 1, l2
- 3},
1483 hOldPen
= SelectObject(hDC
, hPen
);
1484 PolyPolyline(hDC
, aptInsertMark
, adwPolyPoints
, sizeof(adwPolyPoints
)/sizeof(adwPolyPoints
[0]));
1485 SelectObject(hDC
, hOldPen
);
1489 /***********************************************************************
1490 * MirrorIcon [COMCTL32.414]
1492 * Mirrors an icon so that it will appear correctly on a mirrored DC.
1495 * phicon1 [I/O] Icon.
1496 * phicon2 [I/O] Icon.
1502 BOOL WINAPI
MirrorIcon(HICON
*phicon1
, HICON
*phicon2
)
1504 FIXME("(%p, %p): stub\n", phicon1
, phicon2
);
1508 static inline int IsDelimiter(WCHAR c
)
1521 static int CALLBACK
PathWordBreakProc(LPWSTR lpch
, int ichCurrent
, int cch
, int code
)
1523 if (code
== WB_ISDELIMITER
)
1524 return IsDelimiter(lpch
[ichCurrent
]);
1527 int dir
= (code
== WB_LEFT
) ? -1 : 1;
1528 for(; 0 <= ichCurrent
&& ichCurrent
< cch
; ichCurrent
+= dir
)
1529 if (IsDelimiter(lpch
[ichCurrent
])) return ichCurrent
;
1534 /***********************************************************************
1535 * SetPathWordBreakProc [COMCTL32.384]
1537 * Sets the word break procedure for an edit control to one that understands
1538 * paths so that the user can jump over directories.
1541 * hwnd [I] Handle to edit control.
1542 * bSet [I] If this is TRUE then the word break proc is set, otherwise it is removed.
1545 * Result from EM_SETWORDBREAKPROC message.
1547 LRESULT WINAPI
SetPathWordBreakProc(HWND hwnd
, BOOL bSet
)
1549 return SendMessageW(hwnd
, EM_SETWORDBREAKPROC
, 0,
1550 (LPARAM
)(bSet
? PathWordBreakProc
: NULL
));