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 belive 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
44 * -- ICC_LINK_CLASS (not yet implemented)
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
64 #define NO_SHLWAPI_STREAM
67 #include "wine/debug.h"
69 WINE_DEFAULT_DEBUG_CHANNEL(commctrl);
71 extern void ANIMATE_Register(void);
72 extern void ANIMATE_Unregister(void);
73 extern void COMBOEX_Register(void);
74 extern void COMBOEX_Unregister(void);
75 extern void DATETIME_Register(void);
76 extern void DATETIME_Unregister(void);
77 extern void FLATSB_Register(void);
78 extern void FLATSB_Unregister(void);
79 extern void HEADER_Register(void);
80 extern void HEADER_Unregister(void);
81 extern void HOTKEY_Register(void);
82 extern void HOTKEY_Unregister(void);
83 extern void IPADDRESS_Register(void);
84 extern void IPADDRESS_Unregister(void);
85 extern void LISTVIEW_Register(void);
86 extern void LISTVIEW_Unregister(void);
87 extern void MONTHCAL_Register(void);
88 extern void MONTHCAL_Unregister(void);
89 extern void NATIVEFONT_Register(void);
90 extern void NATIVEFONT_Unregister(void);
91 extern void PAGER_Register(void);
92 extern void PAGER_Unregister(void);
93 extern void PROGRESS_Register(void);
94 extern void PROGRESS_Unregister(void);
95 extern void REBAR_Register(void);
96 extern void REBAR_Unregister(void);
97 extern void STATUS_Register(void);
98 extern void STATUS_Unregister(void);
99 extern void TAB_Register(void);
100 extern void TAB_Unregister(void);
101 extern void TOOLBAR_Register(void);
102 extern void TOOLBAR_Unregister(void);
103 extern void TOOLTIPS_Register(void);
104 extern void TOOLTIPS_Unregister(void);
105 extern void TRACKBAR_Register(void);
106 extern void TRACKBAR_Unregister(void);
107 extern void TREEVIEW_Register(void);
108 extern void TREEVIEW_Unregister(void);
109 extern void UPDOWN_Register(void);
110 extern void UPDOWN_Unregister(void);
113 HANDLE COMCTL32_hHeap = (HANDLE)NULL;
114 LPSTR COMCTL32_aSubclass = (LPSTR)NULL;
115 HMODULE COMCTL32_hModule = 0;
116 LANGID COMCTL32_uiLang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
117 HBRUSH COMCTL32_hPattern55AABrush = (HANDLE)NULL;
118 COMCTL32_SysColor comctl32_color;
120 static HBITMAP COMCTL32_hPattern55AABitmap = (HANDLE)NULL;
122 static const WORD wPattern55AA[] =
124 0x5555, 0xaaaa, 0x5555, 0xaaaa,
125 0x5555, 0xaaaa, 0x5555, 0xaaaa
129 /***********************************************************************
130 * COMCTL32_LibMain [Internal] Initializes the internal 'COMCTL32.DLL'.
133 * hinstDLL [I] handle to the 'dlls' instance
135 * lpvReserved [I] reserverd, must be NULL
143 COMCTL32_LibMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
145 TRACE("%p,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
148 case DLL_PROCESS_ATTACH:
149 COMCTL32_hModule = (HMODULE)hinstDLL;
151 /* create private heap */
152 COMCTL32_hHeap = HeapCreate (0, 0x10000, 0);
153 TRACE("Heap created: %p\n", COMCTL32_hHeap);
155 /* add global subclassing atom (used by 'tooltip' and 'updown') */
156 COMCTL32_aSubclass = (LPSTR)(DWORD)GlobalAddAtomA ("CC32SubclassInfo");
157 TRACE("Subclassing atom added: %p\n", COMCTL32_aSubclass);
159 /* create local pattern brush */
160 COMCTL32_hPattern55AABitmap = CreateBitmap (8, 8, 1, 1, wPattern55AA);
161 COMCTL32_hPattern55AABrush = CreatePatternBrush (COMCTL32_hPattern55AABitmap);
163 /* Get all the colors at DLL load */
164 COMCTL32_RefreshSysColors();
166 /* register all Win95 common control classes */
171 LISTVIEW_Register ();
172 PROGRESS_Register ();
176 TOOLTIPS_Register ();
177 TRACKBAR_Register ();
178 TREEVIEW_Register ();
182 case DLL_PROCESS_DETACH:
183 /* unregister all common control classes */
184 ANIMATE_Unregister ();
185 COMBOEX_Unregister ();
186 DATETIME_Unregister ();
187 FLATSB_Unregister ();
188 HEADER_Unregister ();
189 HOTKEY_Unregister ();
190 IPADDRESS_Unregister ();
191 LISTVIEW_Unregister ();
192 MONTHCAL_Unregister ();
193 NATIVEFONT_Unregister ();
195 PROGRESS_Unregister ();
197 STATUS_Unregister ();
199 TOOLBAR_Unregister ();
200 TOOLTIPS_Unregister ();
201 TRACKBAR_Unregister ();
202 TREEVIEW_Unregister ();
203 UPDOWN_Unregister ();
205 /* delete local pattern brush */
206 DeleteObject (COMCTL32_hPattern55AABrush);
207 COMCTL32_hPattern55AABrush = (HANDLE)NULL;
208 DeleteObject (COMCTL32_hPattern55AABitmap);
209 COMCTL32_hPattern55AABitmap = (HANDLE)NULL;
211 /* delete global subclassing atom */
212 GlobalDeleteAtom (LOWORD(COMCTL32_aSubclass));
213 TRACE("Subclassing atom deleted: %p\n", COMCTL32_aSubclass);
214 COMCTL32_aSubclass = (LPSTR)NULL;
216 /* destroy private heap */
217 HeapDestroy (COMCTL32_hHeap);
218 TRACE("Heap destroyed: %p\n", COMCTL32_hHeap);
219 COMCTL32_hHeap = (HANDLE)NULL;
227 /***********************************************************************
228 * MenuHelp [COMCTL32.2]
231 * uMsg [I] message (WM_MENUSELECT) (see NOTES)
232 * wParam [I] wParam of the message uMsg
233 * lParam [I] lParam of the message uMsg
234 * hMainMenu [I] handle to the application's main menu
235 * hInst [I] handle to the module that contains string resources
236 * hwndStatus [I] handle to the status bar window
237 * lpwIDs [I] pointer to an array of integers (see NOTES)
243 * The official documentation is incomplete!
244 * This is the correct documentation:
247 * MenuHelp() does NOT handle WM_COMMAND messages! It only handles
248 * WM_MENUSELECT messages.
251 * (will be written ...)
255 MenuHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu,
256 HINSTANCE hInst, HWND hwndStatus, UINT* lpwIDs)
260 if (!IsWindow (hwndStatus))
265 TRACE("WM_MENUSELECT wParam=0x%X lParam=0x%lX\n",
268 if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {
269 /* menu was closed */
270 TRACE("menu was closed!\n");
271 SendMessageA (hwndStatus, SB_SIMPLE, FALSE, 0);
274 /* menu item was selected */
275 if (HIWORD(wParam) & MF_POPUP)
276 uMenuID = (UINT)*(lpwIDs+1);
278 uMenuID = (UINT)LOWORD(wParam);
279 TRACE("uMenuID = %u\n", uMenuID);
284 if (!LoadStringA (hInst, uMenuID, szText, 256))
287 SendMessageA (hwndStatus, SB_SETTEXTA,
288 255 | SBT_NOBORDERS, (LPARAM)szText);
289 SendMessageA (hwndStatus, SB_SIMPLE, TRUE, 0);
295 TRACE("WM_COMMAND wParam=0x%X lParam=0x%lX\n",
297 /* WM_COMMAND is not invalid since it is documented
298 * in the windows api reference. So don't output
299 * any FIXME for WM_COMMAND
301 WARN("We don't care about the WM_COMMAND\n");
305 FIXME("Invalid Message 0x%x!\n", uMsg);
311 /***********************************************************************
312 * ShowHideMenuCtl [COMCTL32.3]
314 * Shows or hides controls and updates the corresponding menu item.
317 * hwnd [I] handle to the client window.
318 * uFlags [I] menu command id.
319 * lpInfo [I] pointer to an array of integers. (See NOTES.)
326 * The official documentation is incomplete!
327 * This is the correct documentation:
330 * Handle to the window that contains the menu and controls.
333 * Identifier of the menu item to receive or loose a check mark.
336 * The array of integers contains pairs of values. BOTH values of
337 * the first pair must be the handles to the application's main menu.
338 * Each subsequent pair consists of a menu id and control id.
342 ShowHideMenuCtl (HWND hwnd, UINT uFlags, LPINT lpInfo)
346 TRACE("%p, %x, %p\n", hwnd, uFlags, lpInfo);
351 if (!(lpInfo[0]) || !(lpInfo[1]))
354 /* search for control */
355 lpMenuId = &lpInfo[2];
356 while (*lpMenuId != uFlags)
359 if (GetMenuState ((HMENU)lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) {
360 /* uncheck menu item */
361 CheckMenuItem ((HMENU)lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_UNCHECKED);
365 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
369 /* check menu item */
370 CheckMenuItem ((HMENU)lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_CHECKED);
374 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
382 /***********************************************************************
383 * GetEffectiveClientRect [COMCTL32.4]
386 * hwnd [I] handle to the client window.
387 * lpRect [O] pointer to the rectangle of the client window
388 * lpInfo [I] pointer to an array of integers (see NOTES)
394 * The official documentation is incomplete!
395 * This is the correct documentation:
398 * (will be written ...)
402 GetEffectiveClientRect (HWND hwnd, LPRECT lpRect, LPINT lpInfo)
408 TRACE("(0x%08lx 0x%08lx 0x%08lx)\n",
409 (DWORD)hwnd, (DWORD)lpRect, (DWORD)lpInfo);
411 GetClientRect (hwnd, lpRect);
419 hwndCtrl = GetDlgItem (hwnd, *lpRun);
420 if (GetWindowLongA (hwndCtrl, GWL_STYLE) & WS_VISIBLE) {
421 TRACE("control id 0x%x\n", *lpRun);
422 GetWindowRect (hwndCtrl, &rcCtrl);
423 MapWindowPoints ((HWND)0, hwnd, (LPPOINT)&rcCtrl, 2);
424 SubtractRect (lpRect, lpRect, &rcCtrl);
431 /***********************************************************************
432 * DrawStatusTextW [COMCTL32.@]
434 * Draws text with borders, like in a status bar.
437 * hdc [I] handle to the window's display context
438 * lprc [I] pointer to a rectangle
439 * text [I] pointer to the text
440 * style [I] drawing style
446 * The style variable can have one of the following values:
447 * (will be written ...)
450 void WINAPI DrawStatusTextW (HDC hdc, LPRECT lprc, LPCWSTR text, UINT style)
453 UINT border = BDR_SUNKENOUTER;
455 if (style & SBT_POPOUT)
456 border = BDR_RAISEDOUTER;
457 else if (style & SBT_NOBORDERS)
460 DrawEdge (hdc, &r, border, BF_RECT|BF_ADJUST);
464 int oldbkmode = SetBkMode (hdc, TRANSPARENT);
465 UINT align = DT_LEFT;
466 if (*text == L'\t') {
469 if (*text == L'\t') {
475 if (style & SBT_RTLREADING)
476 FIXME("Unsupported RTL style!\n");
477 DrawTextW (hdc, text, -1, &r, align|DT_VCENTER|DT_SINGLELINE);
478 SetBkMode(hdc, oldbkmode);
483 /***********************************************************************
484 * DrawStatusText [COMCTL32.@]
485 * DrawStatusTextA [COMCTL32.5]
487 * Draws text with borders, like in a status bar.
490 * hdc [I] handle to the window's display context
491 * lprc [I] pointer to a rectangle
492 * text [I] pointer to the text
493 * style [I] drawing style
499 void WINAPI DrawStatusTextA (HDC hdc, LPRECT lprc, LPCSTR text, UINT style)
505 if ( (len = MultiByteToWideChar( CP_ACP, 0, text, -1, NULL, 0 )) ) {
506 if ( (textW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) )) )
507 MultiByteToWideChar( CP_ACP, 0, text, -1, textW, len );
510 DrawStatusTextW( hdc, lprc, textW, style );
511 HeapFree( GetProcessHeap(), 0, textW );
515 /***********************************************************************
516 * CreateStatusWindow [COMCTL32.@]
517 * CreateStatusWindowA [COMCTL32.6]
519 * Creates a status bar
522 * style [I] window style
523 * text [I] pointer to the window text
524 * parent [I] handle to the parent window
525 * wid [I] control id of the status bar
528 * Success: handle to the status window
533 CreateStatusWindowA (INT style, LPCSTR text, HWND parent, UINT wid)
535 return CreateWindowA(STATUSCLASSNAMEA, text, style,
536 CW_USEDEFAULT, CW_USEDEFAULT,
537 CW_USEDEFAULT, CW_USEDEFAULT,
538 parent, (HMENU)wid, 0, 0);
542 /***********************************************************************
543 * CreateStatusWindowW [COMCTL32.@] Creates a status bar control
546 * style [I] window style
547 * text [I] pointer to the window text
548 * parent [I] handle to the parent window
549 * wid [I] control id of the status bar
552 * Success: handle to the status window
557 CreateStatusWindowW (INT style, LPCWSTR text, HWND parent, UINT wid)
559 return CreateWindowW(STATUSCLASSNAMEW, text, style,
560 CW_USEDEFAULT, CW_USEDEFAULT,
561 CW_USEDEFAULT, CW_USEDEFAULT,
562 parent, (HMENU)wid, 0, 0);
566 /***********************************************************************
567 * CreateUpDownControl [COMCTL32.16] Creates an up-down control
570 * style [I] window styles
571 * x [I] horizontal position of the control
572 * y [I] vertical position of the control
573 * cx [I] with of the control
574 * cy [I] height of the control
575 * parent [I] handle to the parent window
576 * id [I] the control's identifier
577 * inst [I] handle to the application's module instance
578 * buddy [I] handle to the buddy window, can be NULL
579 * maxVal [I] upper limit of the control
580 * minVal [I] lower limit of the control
581 * curVal [I] current value of the control
584 * Success: handle to the updown control
589 CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
590 HWND parent, INT id, HINSTANCE inst,
591 HWND buddy, INT maxVal, INT minVal, INT curVal)
594 CreateWindowA (UPDOWN_CLASSA, 0, style, x, y, cx, cy,
595 parent, (HMENU)id, inst, 0);
597 SendMessageA (hUD, UDM_SETBUDDY, (WPARAM)buddy, 0);
598 SendMessageA (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));
599 SendMessageA (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));
606 /***********************************************************************
607 * InitCommonControls [COMCTL32.17]
609 * Registers the common controls.
618 * This function is just a dummy.
619 * The Win95 controls are registered at the DLL's initialization.
620 * To register other controls InitCommonControlsEx() must be used.
624 InitCommonControls (void)
629 /***********************************************************************
630 * InitCommonControlsEx [COMCTL32.@]
632 * Registers the common controls.
635 * lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
642 * Only the additional common controls are registered by this function.
643 * The Win95 controls are registered at the DLL's initialization.
646 * implement the following control classes:
648 * ICC_STANDARD_CLASSES
652 InitCommonControlsEx (LPINITCOMMONCONTROLSEX lpInitCtrls)
659 if (lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
662 TRACE("(0x%08lx)\n", lpInitCtrls->dwICC);
664 for (cCount = 0; cCount < 32; cCount++) {
665 dwMask = 1 << cCount;
666 if (!(lpInitCtrls->dwICC & dwMask))
669 switch (lpInitCtrls->dwICC & dwMask) {
670 /* dummy initialization */
671 case ICC_ANIMATE_CLASS:
672 case ICC_BAR_CLASSES:
673 case ICC_LISTVIEW_CLASSES:
674 case ICC_TREEVIEW_CLASSES:
675 case ICC_TAB_CLASSES:
676 case ICC_UPDOWN_CLASS:
677 case ICC_PROGRESS_CLASS:
678 case ICC_HOTKEY_CLASS:
681 /* advanced classes - not included in Win95 */
682 case ICC_DATE_CLASSES:
683 MONTHCAL_Register ();
684 DATETIME_Register ();
687 case ICC_USEREX_CLASSES:
691 case ICC_COOL_CLASSES:
695 case ICC_INTERNET_CLASSES:
696 IPADDRESS_Register ();
699 case ICC_PAGESCROLLER_CLASS:
703 case ICC_NATIVEFNTCTL_CLASS:
704 NATIVEFONT_Register ();
708 FIXME("Unknown class! dwICC=0x%lX\n", dwMask);
717 /***********************************************************************
718 * CreateToolbarEx [COMCTL32.@] Creates a tool bar window
736 * Success: handle to the tool bar control
741 CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
742 HINSTANCE hBMInst, UINT wBMID, LPCTBBUTTON lpButtons,
743 INT iNumButtons, INT dxButton, INT dyButton,
744 INT dxBitmap, INT dyBitmap, UINT uStructSize)
748 /* If not position is specified then put it at the top */
749 if ((style & CCS_BOTTOM) == 0) {
754 CreateWindowExA (0, TOOLBARCLASSNAMEA, "", style|WS_CHILD, 0, 0, 0, 0,
755 hwnd, (HMENU)wID, 0, NULL);
759 SendMessageA (hwndTB, TB_BUTTONSTRUCTSIZE,
760 (WPARAM)uStructSize, 0);
762 /* set bitmap and button size */
763 /*If CreateToolbarEx receives 0, windows sets default values*/
768 SendMessageA (hwndTB, TB_SETBITMAPSIZE, 0,
769 MAKELPARAM((WORD)dxBitmap, (WORD)dyBitmap));
775 SendMessageA (hwndTB, TB_SETBUTTONSIZE, 0,
776 MAKELPARAM((WORD)dxButton, (WORD)dyButton));
782 tbab.hInst = hBMInst;
785 SendMessageA (hwndTB, TB_ADDBITMAP,
786 (WPARAM)nBitmaps, (LPARAM)&tbab);
790 SendMessageA (hwndTB, TB_ADDBUTTONSA,
791 (WPARAM)iNumButtons, (LPARAM)lpButtons);
798 /***********************************************************************
799 * CreateMappedBitmap [COMCTL32.8]
809 * Success: handle to the new bitmap
814 CreateMappedBitmap (HINSTANCE hInstance, INT idBitmap, UINT wFlags,
815 LPCOLORMAP lpColorMap, INT iNumMaps)
819 LPBITMAPINFOHEADER lpBitmap, lpBitmapInfo;
820 UINT nSize, nColorTableSize;
821 RGBQUAD *pColorTable;
822 INT iColor, i, iMaps, nWidth, nHeight;
825 LPCOLORMAP sysColorMap;
827 COLORMAP internalColorMap[4] =
828 {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
830 /* initialize pointer to colortable and default color table */
833 sysColorMap = lpColorMap;
836 internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT);
837 internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW);
838 internalColorMap[2].to = GetSysColor (COLOR_BTNFACE);
839 internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT);
841 sysColorMap = (LPCOLORMAP)internalColorMap;
844 hRsrc = FindResourceA (hInstance, (LPSTR)idBitmap, RT_BITMAPA);
847 hglb = LoadResource (hInstance, hRsrc);
850 lpBitmap = (LPBITMAPINFOHEADER)LockResource (hglb);
851 if (lpBitmap == NULL)
854 nColorTableSize = (1 << lpBitmap->biBitCount);
855 nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
856 lpBitmapInfo = (LPBITMAPINFOHEADER)GlobalAlloc (GMEM_FIXED, nSize);
857 if (lpBitmapInfo == NULL)
859 RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);
861 pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo)+(UINT)lpBitmapInfo->biSize);
863 for (iColor = 0; iColor < nColorTableSize; iColor++) {
864 for (i = 0; i < iMaps; i++) {
865 cRef = RGB(pColorTable[iColor].rgbRed,
866 pColorTable[iColor].rgbGreen,
867 pColorTable[iColor].rgbBlue);
868 if ( cRef == sysColorMap[i].from) {
870 if (wFlags & CBS_MASKED) {
871 if (sysColorMap[i].to != COLOR_BTNTEXT)
872 pColorTable[iColor] = RGB(255, 255, 255);
876 pColorTable[iColor].rgbBlue = GetBValue(sysColorMap[i].to);
877 pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);
878 pColorTable[iColor].rgbRed = GetRValue(sysColorMap[i].to);
883 nWidth = (INT)lpBitmapInfo->biWidth;
884 nHeight = (INT)lpBitmapInfo->biHeight;
885 hdcScreen = GetDC ((HWND)0);
886 hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
888 HDC hdcDst = CreateCompatibleDC (hdcScreen);
889 HBITMAP hbmOld = SelectObject (hdcDst, hbm);
890 LPBYTE lpBits = (LPBYTE)(lpBitmap + 1);
891 lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
892 StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
893 lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
895 SelectObject (hdcDst, hbmOld);
898 ReleaseDC ((HWND)0, hdcScreen);
899 GlobalFree ((HGLOBAL)lpBitmapInfo);
906 /***********************************************************************
907 * CreateToolbar [COMCTL32.7] Creates a tool bar control
920 * Success: handle to the tool bar control
924 * Do not use this functions anymore. Use CreateToolbarEx instead.
928 CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
929 HINSTANCE hBMInst, UINT wBMID,
930 LPCOLDTBBUTTON lpButtons,INT iNumButtons)
932 return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
933 hBMInst, wBMID, (LPCTBBUTTON)lpButtons,
934 iNumButtons, 0, 0, 0, 0, sizeof (OLDTBBUTTON));
938 /***********************************************************************
939 * DllGetVersion [COMCTL32.@]
941 * Retrieves version information of the 'COMCTL32.DLL'
944 * pdvi [O] pointer to version information structure.
948 * Failure: E_INVALIDARG
951 * Returns version of a comctl32.dll from IE4.01 SP1.
955 COMCTL32_DllGetVersion (DLLVERSIONINFO *pdvi)
957 if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
958 WARN("wrong DLLVERSIONINFO size from app\n");
962 pdvi->dwMajorVersion = COMCTL32_VERSION;
963 pdvi->dwMinorVersion = COMCTL32_VERSION_MINOR;
964 pdvi->dwBuildNumber = 2919;
965 pdvi->dwPlatformID = 6304;
967 TRACE("%lu.%lu.%lu.%lu\n",
968 pdvi->dwMajorVersion, pdvi->dwMinorVersion,
969 pdvi->dwBuildNumber, pdvi->dwPlatformID);
974 /***********************************************************************
975 * DllInstall (COMCTL32.@)
977 HRESULT WINAPI COMCTL32_DllInstall(BOOL bInstall, LPCWSTR cmdline)
979 FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
980 debugstr_w(cmdline));
985 /***********************************************************************
986 * _TrackMouseEvent [COMCTL32.@]
988 * Requests notification of mouse events
990 * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
991 * to the hwnd specified in the ptme structure. After the event message
992 * is posted to the hwnd, the entry in the queue is removed.
994 * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
995 * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
996 * immediately and the TME_LEAVE flag being ignored.
999 * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
1005 * IMPLEMENTATION moved to USER32.TrackMouseEvent
1010 _TrackMouseEvent (TRACKMOUSEEVENT *ptme)
1012 return TrackMouseEvent (ptme);
1015 /*************************************************************************
1016 * GetMUILanguage [COMCTL32.@]
1018 * FIXME: "Returns the language currently in use by the common controls
1019 * for a particular process." (MSDN)
1022 LANGID WINAPI GetMUILanguage (VOID)
1024 return COMCTL32_uiLang;
1028 /*************************************************************************
1029 * InitMUILanguage [COMCTL32.@]
1031 * FIXME: "Enables an application to specify a language to be used with
1032 * the common controls that is different than the system language." (MSDN)
1036 VOID WINAPI InitMUILanguage (LANGID uiLang)
1038 COMCTL32_uiLang = uiLang;
1042 /***********************************************************************
1043 * SetWindowSubclass [COMCTL32.@]
1045 * Starts a window subclass
1048 * hWnd [in] handle to window subclass.
1049 * pfnSubclass [in] Pointer to new window procedure.
1050 * uIDSubclass [in] Unique identifier of sublass together with pfnSubclass.
1051 * dwRef [in] Reference data to pass to window procedure.
1058 * If an application manually subclasses a window after subclassing it with
1059 * this API and then with this API again, then none of the previous
1060 * subclasses get called or the origional window procedure.
1063 BOOL WINAPI SetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
1064 UINT_PTR uIDSubclass, DWORD_PTR dwRef)
1066 LPSUBCLASS_INFO stack;
1069 TRACE ("(%p, %p, %x, %lx)\n", hWnd, pfnSubclass, uIDSubclass, dwRef);
1071 /* Since the window procedure that we set here has two additional arguments,
1072 * we can't simply set it as the new window procedure of the window. So we
1073 * set our own window procedure and then calculate the other two arguments
1076 /* See if we have been called for this window */
1077 stack = (LPSUBCLASS_INFO)GetPropA (hWnd, COMCTL32_aSubclass);
1079 /* allocate stack */
1080 stack = (LPSUBCLASS_INFO)HeapAlloc (GetProcessHeap(), HEAP_ZERO_MEMORY,
1081 sizeof(SUBCLASS_INFO));
1083 ERR ("Failed to allocate our Subclassing stack");
1086 SetPropA (hWnd, COMCTL32_aSubclass, (HANDLE)stack);
1088 /* set window procedure to our own and save the current one */
1089 if (IsWindowUnicode (hWnd))
1090 stack->origproc = (WNDPROC)SetWindowLongW (hWnd, GWL_WNDPROC,
1091 (LONG)DefSubclassProc);
1093 stack->origproc = (WNDPROC)SetWindowLongA (hWnd, GWL_WNDPROC,
1094 (LONG)DefSubclassProc);
1097 if (IsWindowUnicode (hWnd))
1098 current = (WNDPROC)GetWindowLongW (hWnd, GWL_WNDPROC);
1100 current = (WNDPROC)GetWindowLongA (hWnd, GWL_WNDPROC);
1102 if (current != DefSubclassProc) {
1103 ERR ("Application has subclassed with our procedure, then manually, then with us again. The current implementation can't handle this.\n");
1108 /* Check to see if we have called this function with the same uIDSubClass
1109 * and pfnSubclass */
1110 for (n = 0; n <= stack->stacknum + stack->stacknew - 1; n++)
1111 if ((stack->SubclassProcs[n].id == uIDSubclass) &&
1112 (stack->SubclassProcs[n].subproc == pfnSubclass)) {
1113 stack->SubclassProcs[n].ref = dwRef;
1117 if ((stack->stacknum + stack->stacknew) >= 32) {
1118 ERR ("We have a Subclass stack overflow, please increment size");
1122 /* we can't simply increment both stackpos and stacknum because there might
1123 * be a window procedure running lower in the stack, we can only get them
1124 * up to date once the last window procedure has run */
1125 if (stack->stacknum == stack->stackpos) {
1131 newnum = stack->stacknew + stack->stacknum - 1;
1133 stack->SubclassProcs[newnum].subproc = pfnSubclass;
1134 stack->SubclassProcs[newnum].ref = dwRef;
1135 stack->SubclassProcs[newnum].id = uIDSubclass;
1141 /***********************************************************************
1142 * GetWindowSubclass [COMCTL32.@]
1144 * Gets the Reference data from a subclass.
1147 * hWnd [in] Handle to window which were subclassing
1148 * pfnSubclass [in] Pointer to the subclass procedure
1149 * iID [in] Unique indentifier of the subclassing procedure
1150 * pdwRef [out] Pointer to the reference data
1157 BOOL WINAPI GetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
1158 UINT_PTR uID, DWORD_PTR *pdwRef)
1160 LPSUBCLASS_INFO stack;
1163 TRACE ("(%p, %p, %x, %p)\n", hWnd, pfnSubclass, uID, pdwRef);
1165 /* See if we have been called for this window */
1166 stack = (LPSUBCLASS_INFO)GetPropA (hWnd, COMCTL32_aSubclass);
1170 for (n = 0; n <= stack->stacknum + stack->stacknew - 1; n++)
1171 if ((stack->SubclassProcs[n].id == uID) &&
1172 (stack->SubclassProcs[n].subproc == pfnSubclass)) {
1173 *pdwRef = stack->SubclassProcs[n].ref;
1181 /***********************************************************************
1182 * RemoveWindowSubclass [COMCTL32.@]
1184 * Removes a window subclass.
1187 * hWnd [in] Handle to the window were subclassing
1188 * pfnSubclass [in] Pointer to the subclass procedure
1189 * uID [in] Unique identifier of this subclass
1196 BOOL WINAPI RemoveWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR uID)
1198 LPSUBCLASS_INFO stack;
1201 TRACE ("(%p, %p, %x)\n", hWnd, pfnSubclass, uID);
1203 /* Find the Subclass to remove */
1204 stack = (LPSUBCLASS_INFO)GetPropA (hWnd, COMCTL32_aSubclass);
1208 if ((stack->stacknum == stack->stackpos == 1) && !stack->stacknew) {
1209 TRACE("Last Subclass removed, cleaning up\n");
1210 /* clean up our heap and reset the origional window procedure */
1211 if (IsWindowUnicode (hWnd))
1212 SetWindowLongW (hWnd, GWL_WNDPROC, (LONG)stack->origproc);
1214 SetWindowLongA (hWnd, GWL_WNDPROC, (LONG)stack->origproc);
1215 HeapFree (GetProcessHeap (), 0, stack);
1216 RemovePropA( hWnd, COMCTL32_aSubclass );
1220 for (n = stack->stacknum + stack->stacknew - 1; n >= 0; n--)
1221 if ((stack->SubclassProcs[n].id == uID) &&
1222 (stack->SubclassProcs[n].subproc == pfnSubclass)) {
1223 if (n != (stack->stacknum + stack->stacknew))
1224 /* Fill the hole in the stack */
1225 memmove (&stack->SubclassProcs[n], &stack->SubclassProcs[n + 1],
1226 sizeof(stack->SubclassProcs[0]) * (stack->stacknew + stack->stacknum - n));
1227 stack->SubclassProcs[n].subproc = NULL;
1228 stack->SubclassProcs[n].ref = 0;
1229 stack->SubclassProcs[n].id = 0;
1231 /* If we are currently running a window procedure we have to manipulate
1232 * the stack position pointers so that we don't corrupt the stack */
1233 if ((n < stack->stackpos) || (stack->stackpos == stack->stacknum)) {
1236 } else if (n >= stack->stackpos)
1245 /***********************************************************************
1246 * DefSubclassProc [COMCTL32.@]
1248 * Calls the next window procedure (ie. the one before this subclass)
1251 * hWnd [in] The window that we're subclassing
1253 * wParam [in] WPARAM
1254 * lParam [in] LPARAM
1261 LRESULT WINAPI DefSubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1263 LPSUBCLASS_INFO stack;
1267 /* retrieve our little stack from the Properties */
1268 stack = (LPSUBCLASS_INFO)GetPropA (hWnd, COMCTL32_aSubclass);
1270 ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
1274 /* If we are at pos 0 then we have to call the origional window procedure */
1275 if (stack->stackpos == 0) {
1276 if (IsWindowUnicode (hWnd))
1277 return CallWindowProcW (stack->origproc, hWnd, uMsg, wParam, lParam);
1279 return CallWindowProcA (stack->origproc, hWnd, uMsg, wParam, lParam);
1282 stackpos = --stack->stackpos;
1283 /* call the Subclass procedure from the stack */
1284 ret = stack->SubclassProcs[stackpos].subproc (hWnd, uMsg, wParam, lParam,
1285 stack->SubclassProcs[stackpos].id, stack->SubclassProcs[stackpos].ref);
1288 if ((stack->stackpos == stack->stacknum) && stack->stacknew) {
1289 stack->stacknum += stack->stacknew;
1290 stack->stackpos += stack->stacknew;
1291 stack->stacknew = 0;
1294 /* If we removed the last entry in our stack while a window procedure was
1295 * running then we have to clean up */
1296 if (stack->stackpos == stack->stacknum == 0) {
1297 TRACE("Last Subclass removed, cleaning up\n");
1298 /* clean up our heap and reset the origional window procedure */
1299 if (IsWindowUnicode (hWnd))
1300 SetWindowLongW (hWnd, GWL_WNDPROC, (LONG)stack->origproc);
1302 SetWindowLongA (hWnd, GWL_WNDPROC, (LONG)stack->origproc);
1303 HeapFree (GetProcessHeap (), 0, stack);
1304 RemovePropA( hWnd, COMCTL32_aSubclass );
1312 /***********************************************************************
1313 * COMCTL32_CreateToolTip [NOT AN API]
1315 * Creates a tooltip for the control specified in hwnd and does all
1316 * necessary setup and notifications.
1319 * hwndOwner [I] Handle to the window that will own the tool tip.
1322 * Success: Handle of tool tip window.
1327 COMCTL32_CreateToolTip(HWND hwndOwner)
1331 hwndToolTip = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
1332 CW_USEDEFAULT, CW_USEDEFAULT,
1333 CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner,
1336 /* Send NM_TOOLTIPSCREATED notification */
1339 NMTOOLTIPSCREATED nmttc;
1340 /* true owner can be different if hwndOwner is a child window */
1341 HWND hwndTrueOwner = GetWindow(hwndToolTip, GW_OWNER);
1342 nmttc.hdr.hwndFrom = hwndTrueOwner;
1343 nmttc.hdr.idFrom = GetWindowLongA(hwndTrueOwner, GWL_ID);
1344 nmttc.hdr.code = NM_TOOLTIPSCREATED;
1345 nmttc.hwndToolTips = hwndToolTip;
1347 SendMessageA(GetParent(hwndTrueOwner), WM_NOTIFY,
1348 (WPARAM)GetWindowLongA(hwndTrueOwner, GWL_ID),
1356 /***********************************************************************
1357 * COMCTL32_RefreshSysColors [NOT AN API]
1359 * Invoked on any control recognizing a WM_SYSCOLORCHANGE message to
1360 * refresh the color values in the color structure
1370 COMCTL32_RefreshSysColors(void)
1372 comctl32_color.clrBtnHighlight = GetSysColor (COLOR_BTNHIGHLIGHT);
1373 comctl32_color.clrBtnShadow = GetSysColor (COLOR_BTNSHADOW);
1374 comctl32_color.clrBtnText = GetSysColor (COLOR_BTNTEXT);
1375 comctl32_color.clrBtnFace = GetSysColor (COLOR_BTNFACE);
1376 comctl32_color.clrHighlight = GetSysColor (COLOR_HIGHLIGHT);
1377 comctl32_color.clrHighlightText = GetSysColor (COLOR_HIGHLIGHTTEXT);
1378 comctl32_color.clr3dHilight = GetSysColor (COLOR_3DHILIGHT);
1379 comctl32_color.clr3dShadow = GetSysColor (COLOR_3DSHADOW);
1380 comctl32_color.clr3dDkShadow = GetSysColor (COLOR_3DDKSHADOW);
1381 comctl32_color.clr3dFace = GetSysColor (COLOR_3DFACE);
1382 comctl32_color.clrWindow = GetSysColor (COLOR_WINDOW);
1383 comctl32_color.clrWindowText = GetSysColor (COLOR_WINDOWTEXT);
1384 comctl32_color.clrGrayText = GetSysColor (COLOR_GRAYTEXT);
1385 comctl32_color.clrActiveCaption = GetSysColor (COLOR_ACTIVECAPTION);
1386 comctl32_color.clrInfoBk = GetSysColor (COLOR_INFOBK);
1387 comctl32_color.clrInfoText = GetSysColor (COLOR_INFOTEXT);