quartz: Free two assert calls from having side effects.
[wine/testsucceed.git] / dlls / comctl32 / commctrl.c
blob76ab3a1dfe71006ca13c767215fc01f34fc1f9b8
1 /*
2 * Common controls functions
4 * Copyright 1997 Dimitrie O. Paun
5 * Copyright 1998,2000 Eric Kohl
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 * NOTES
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.
30 * TODO
31 * -- implement GetMUILanguage + InitMUILanguage
32 * -- finish NOTES for MenuHelp, GetEffectiveClientRect and GetStatusTextW
33 * -- FIXMEs + BUGS (search for them)
35 * Control Classes
36 * -- ICC_ANIMATE_CLASS
37 * -- ICC_BAR_CLASSES
38 * -- ICC_COOL_CLASSES
39 * -- ICC_DATE_CLASSES
40 * -- ICC_HOTKEY_CLASS
41 * -- ICC_INTERNET_CLASSES
42 * -- ICC_LINK_CLASS
43 * -- ICC_LISTVIEW_CLASSES
44 * -- ICC_NATIVEFNTCTL_CLASS
45 * -- ICC_PAGESCROLLER_CLASS
46 * -- ICC_PROGRESS_CLASS
47 * -- ICC_STANDARD_CLASSES (not yet implemented)
48 * -- ICC_TAB_CLASSES
49 * -- ICC_TREEVIEW_CLASSES
50 * -- ICC_UPDOWN_CLASS
51 * -- ICC_USEREX_CLASSES
52 * -- ICC_WIN95_CLASSES
55 #include <stdarg.h>
56 #include <string.h>
57 #include <stdlib.h>
59 #include "windef.h"
60 #include "winbase.h"
61 #include "wingdi.h"
62 #include "winuser.h"
63 #include "winnls.h"
64 #include "commctrl.h"
65 #include "winerror.h"
66 #include "winreg.h"
67 #define NO_SHLWAPI_STREAM
68 #include "shlwapi.h"
69 #include "comctl32.h"
70 #include "wine/debug.h"
72 WINE_DEFAULT_DEBUG_CHANNEL(commctrl);
75 static LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
77 static LPWSTR COMCTL32_wSubclass = NULL;
78 HMODULE COMCTL32_hModule = 0;
79 static LANGID COMCTL32_uiLang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
80 HBRUSH COMCTL32_hPattern55AABrush = NULL;
81 COMCTL32_SysColor comctl32_color;
83 static HBITMAP COMCTL32_hPattern55AABitmap = NULL;
85 static const WORD wPattern55AA[] =
87 0x5555, 0xaaaa, 0x5555, 0xaaaa,
88 0x5555, 0xaaaa, 0x5555, 0xaaaa
91 static const WCHAR strCC32SubclassInfo[] = {
92 'C','C','3','2','S','u','b','c','l','a','s','s','I','n','f','o',0
96 /***********************************************************************
97 * DllMain [Internal]
99 * Initializes the internal 'COMCTL32.DLL'.
101 * PARAMS
102 * hinstDLL [I] handle to the 'dlls' instance
103 * fdwReason [I]
104 * lpvReserved [I] reserved, must be NULL
106 * RETURNS
107 * Success: TRUE
108 * Failure: FALSE
111 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
113 TRACE("%p,%x,%p\n", hinstDLL, fdwReason, lpvReserved);
115 switch (fdwReason) {
116 case DLL_PROCESS_ATTACH:
117 DisableThreadLibraryCalls(hinstDLL);
119 COMCTL32_hModule = hinstDLL;
121 /* add global subclassing atom (used by 'tooltip' and 'updown') */
122 COMCTL32_wSubclass = (LPWSTR)(DWORD_PTR)GlobalAddAtomW (strCC32SubclassInfo);
123 TRACE("Subclassing atom added: %p\n", COMCTL32_wSubclass);
125 /* create local pattern brush */
126 COMCTL32_hPattern55AABitmap = CreateBitmap (8, 8, 1, 1, wPattern55AA);
127 COMCTL32_hPattern55AABrush = CreatePatternBrush (COMCTL32_hPattern55AABitmap);
129 /* Get all the colors at DLL load */
130 COMCTL32_RefreshSysColors();
132 /* like comctl32 5.82+ register all the common control classes */
133 ANIMATE_Register ();
134 COMBOEX_Register ();
135 DATETIME_Register ();
136 FLATSB_Register ();
137 HEADER_Register ();
138 HOTKEY_Register ();
139 IPADDRESS_Register ();
140 LISTVIEW_Register ();
141 MONTHCAL_Register ();
142 NATIVEFONT_Register ();
143 PAGER_Register ();
144 PROGRESS_Register ();
145 REBAR_Register ();
146 STATUS_Register ();
147 SYSLINK_Register ();
148 TAB_Register ();
149 TOOLBAR_Register ();
150 TOOLTIPS_Register ();
151 TRACKBAR_Register ();
152 TREEVIEW_Register ();
153 UPDOWN_Register ();
155 /* subclass user32 controls */
156 THEMING_Initialize ();
157 break;
159 case DLL_PROCESS_DETACH:
160 /* clean up subclassing */
161 THEMING_Uninitialize();
163 /* unregister all common control classes */
164 ANIMATE_Unregister ();
165 COMBOEX_Unregister ();
166 DATETIME_Unregister ();
167 FLATSB_Unregister ();
168 HEADER_Unregister ();
169 HOTKEY_Unregister ();
170 IPADDRESS_Unregister ();
171 LISTVIEW_Unregister ();
172 MONTHCAL_Unregister ();
173 NATIVEFONT_Unregister ();
174 PAGER_Unregister ();
175 PROGRESS_Unregister ();
176 REBAR_Unregister ();
177 STATUS_Unregister ();
178 SYSLINK_Unregister ();
179 TAB_Unregister ();
180 TOOLBAR_Unregister ();
181 TOOLTIPS_Unregister ();
182 TRACKBAR_Unregister ();
183 TREEVIEW_Unregister ();
184 UPDOWN_Unregister ();
186 /* delete local pattern brush */
187 DeleteObject (COMCTL32_hPattern55AABrush);
188 COMCTL32_hPattern55AABrush = NULL;
189 DeleteObject (COMCTL32_hPattern55AABitmap);
190 COMCTL32_hPattern55AABitmap = NULL;
192 /* delete global subclassing atom */
193 GlobalDeleteAtom (LOWORD(COMCTL32_wSubclass));
194 TRACE("Subclassing atom deleted: %p\n", COMCTL32_wSubclass);
195 COMCTL32_wSubclass = NULL;
196 break;
199 return TRUE;
203 /***********************************************************************
204 * MenuHelp [COMCTL32.2]
206 * Handles the setting of status bar help messages when the user
207 * selects menu items.
209 * PARAMS
210 * uMsg [I] message (WM_MENUSELECT) (see NOTES)
211 * wParam [I] wParam of the message uMsg
212 * lParam [I] lParam of the message uMsg
213 * hMainMenu [I] handle to the application's main menu
214 * hInst [I] handle to the module that contains string resources
215 * hwndStatus [I] handle to the status bar window
216 * lpwIDs [I] pointer to an array of integers (see NOTES)
218 * RETURNS
219 * No return value
221 * NOTES
222 * The official documentation is incomplete!
223 * This is the correct documentation:
225 * uMsg:
226 * MenuHelp() does NOT handle WM_COMMAND messages! It only handles
227 * WM_MENUSELECT messages.
229 * lpwIDs:
230 * (will be written ...)
233 VOID WINAPI
234 MenuHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu,
235 HINSTANCE hInst, HWND hwndStatus, UINT* lpwIDs)
237 UINT uMenuID = 0;
239 if (!IsWindow (hwndStatus))
240 return;
242 switch (uMsg) {
243 case WM_MENUSELECT:
244 TRACE("WM_MENUSELECT wParam=0x%lX lParam=0x%lX\n",
245 wParam, lParam);
247 if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {
248 /* menu was closed */
249 TRACE("menu was closed!\n");
250 SendMessageW (hwndStatus, SB_SIMPLE, FALSE, 0);
252 else {
253 /* menu item was selected */
254 if (HIWORD(wParam) & MF_POPUP)
255 uMenuID = *(lpwIDs+1);
256 else
257 uMenuID = (UINT)LOWORD(wParam);
258 TRACE("uMenuID = %u\n", uMenuID);
260 if (uMenuID) {
261 WCHAR szText[256];
263 if (!LoadStringW (hInst, uMenuID, szText, sizeof(szText)/sizeof(szText[0])))
264 szText[0] = '\0';
266 SendMessageW (hwndStatus, SB_SETTEXTW,
267 255 | SBT_NOBORDERS, (LPARAM)szText);
268 SendMessageW (hwndStatus, SB_SIMPLE, TRUE, 0);
271 break;
273 case WM_COMMAND :
274 TRACE("WM_COMMAND wParam=0x%lX lParam=0x%lX\n",
275 wParam, lParam);
276 /* WM_COMMAND is not invalid since it is documented
277 * in the windows api reference. So don't output
278 * any FIXME for WM_COMMAND
280 WARN("We don't care about the WM_COMMAND\n");
281 break;
283 default:
284 FIXME("Invalid Message 0x%x!\n", uMsg);
285 break;
290 /***********************************************************************
291 * ShowHideMenuCtl [COMCTL32.3]
293 * Shows or hides controls and updates the corresponding menu item.
295 * PARAMS
296 * hwnd [I] handle to the client window.
297 * uFlags [I] menu command id.
298 * lpInfo [I] pointer to an array of integers. (See NOTES.)
300 * RETURNS
301 * Success: TRUE
302 * Failure: FALSE
304 * NOTES
305 * The official documentation is incomplete!
306 * This is the correct documentation:
308 * hwnd
309 * Handle to the window that contains the menu and controls.
311 * uFlags
312 * Identifier of the menu item to receive or lose a check mark.
314 * lpInfo
315 * The array of integers contains pairs of values. BOTH values of
316 * the first pair must be the handles to the application's main menu.
317 * Each subsequent pair consists of a menu id and control id.
320 BOOL WINAPI
321 ShowHideMenuCtl (HWND hwnd, UINT_PTR uFlags, LPINT lpInfo)
323 LPINT lpMenuId;
325 TRACE("%p, %lx, %p\n", hwnd, uFlags, lpInfo);
327 if (lpInfo == NULL)
328 return FALSE;
330 if (!(lpInfo[0]) || !(lpInfo[1]))
331 return FALSE;
333 /* search for control */
334 lpMenuId = &lpInfo[2];
335 while (*lpMenuId != uFlags)
336 lpMenuId += 2;
338 if (GetMenuState ((HMENU)(DWORD_PTR)lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) {
339 /* uncheck menu item */
340 CheckMenuItem ((HMENU)(DWORD_PTR)lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_UNCHECKED);
342 /* hide control */
343 lpMenuId++;
344 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
345 SWP_HIDEWINDOW);
347 else {
348 /* check menu item */
349 CheckMenuItem ((HMENU)(DWORD_PTR)lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_CHECKED);
351 /* show control */
352 lpMenuId++;
353 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
354 SWP_SHOWWINDOW);
357 return TRUE;
361 /***********************************************************************
362 * GetEffectiveClientRect [COMCTL32.4]
364 * Calculates the coordinates of a rectangle in the client area.
366 * PARAMS
367 * hwnd [I] handle to the client window.
368 * lpRect [O] pointer to the rectangle of the client window
369 * lpInfo [I] pointer to an array of integers (see NOTES)
371 * RETURNS
372 * No return value.
374 * NOTES
375 * The official documentation is incomplete!
376 * This is the correct documentation:
378 * lpInfo
379 * (will be written ...)
382 VOID WINAPI
383 GetEffectiveClientRect (HWND hwnd, LPRECT lpRect, const INT *lpInfo)
385 RECT rcCtrl;
386 const INT *lpRun;
387 HWND hwndCtrl;
389 TRACE("(%p %p %p)\n",
390 hwnd, lpRect, lpInfo);
392 GetClientRect (hwnd, lpRect);
393 lpRun = lpInfo;
395 do {
396 lpRun += 2;
397 if (*lpRun == 0)
398 return;
399 lpRun++;
400 hwndCtrl = GetDlgItem (hwnd, *lpRun);
401 if (GetWindowLongW (hwndCtrl, GWL_STYLE) & WS_VISIBLE) {
402 TRACE("control id 0x%x\n", *lpRun);
403 GetWindowRect (hwndCtrl, &rcCtrl);
404 MapWindowPoints (NULL, hwnd, (LPPOINT)&rcCtrl, 2);
405 SubtractRect (lpRect, lpRect, &rcCtrl);
407 lpRun++;
408 } while (*lpRun);
412 /***********************************************************************
413 * DrawStatusTextW [COMCTL32.@]
415 * Draws text with borders, like in a status bar.
417 * PARAMS
418 * hdc [I] handle to the window's display context
419 * lprc [I] pointer to a rectangle
420 * text [I] pointer to the text
421 * style [I] drawing style
423 * RETURNS
424 * No return value.
426 * NOTES
427 * The style variable can have one of the following values:
428 * (will be written ...)
431 void WINAPI DrawStatusTextW (HDC hdc, LPCRECT lprc, LPCWSTR text, UINT style)
433 RECT r = *lprc;
434 UINT border = BDR_SUNKENOUTER;
436 if (style & SBT_POPOUT)
437 border = BDR_RAISEDOUTER;
438 else if (style & SBT_NOBORDERS)
439 border = 0;
441 DrawEdge (hdc, &r, border, BF_RECT|BF_ADJUST);
443 /* now draw text */
444 if (text) {
445 int oldbkmode = SetBkMode (hdc, TRANSPARENT);
446 UINT align = DT_LEFT;
447 int strCnt = 0;
449 if (style & SBT_RTLREADING)
450 FIXME("Unsupported RTL style!\n");
451 r.left += 3;
452 do {
453 if (*text == '\t') {
454 if (strCnt) {
455 DrawTextW (hdc, text - strCnt, strCnt, &r, align|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX);
456 strCnt = 0;
458 if (align==DT_RIGHT) {
459 break;
461 align = (align==DT_LEFT ? DT_CENTER : DT_RIGHT);
462 } else {
463 strCnt++;
465 } while(*text++);
467 if (strCnt) DrawTextW (hdc, text - strCnt, -1, &r, align|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX);
468 SetBkMode(hdc, oldbkmode);
473 /***********************************************************************
474 * DrawStatusText [COMCTL32.@]
475 * DrawStatusTextA [COMCTL32.5]
477 * Draws text with borders, like in a status bar.
479 * PARAMS
480 * hdc [I] handle to the window's display context
481 * lprc [I] pointer to a rectangle
482 * text [I] pointer to the text
483 * style [I] drawing style
485 * RETURNS
486 * No return value.
489 void WINAPI DrawStatusTextA (HDC hdc, LPCRECT lprc, LPCSTR text, UINT style)
491 INT len;
492 LPWSTR textW = NULL;
494 if ( text ) {
495 if ( (len = MultiByteToWideChar( CP_ACP, 0, text, -1, NULL, 0 )) ) {
496 if ( (textW = Alloc( len * sizeof(WCHAR) )) )
497 MultiByteToWideChar( CP_ACP, 0, text, -1, textW, len );
500 DrawStatusTextW( hdc, lprc, textW, style );
501 Free( textW );
505 /***********************************************************************
506 * CreateStatusWindow [COMCTL32.@]
507 * CreateStatusWindowA [COMCTL32.6]
509 * Creates a status bar
511 * PARAMS
512 * style [I] window style
513 * text [I] pointer to the window text
514 * parent [I] handle to the parent window
515 * wid [I] control id of the status bar
517 * RETURNS
518 * Success: handle to the status window
519 * Failure: 0
522 HWND WINAPI
523 CreateStatusWindowA (LONG style, LPCSTR text, HWND parent, UINT wid)
525 return CreateWindowA(STATUSCLASSNAMEA, text, style,
526 CW_USEDEFAULT, CW_USEDEFAULT,
527 CW_USEDEFAULT, CW_USEDEFAULT,
528 parent, (HMENU)(DWORD_PTR)wid, 0, 0);
532 /***********************************************************************
533 * CreateStatusWindowW [COMCTL32.@]
535 * Creates a status bar control
537 * PARAMS
538 * style [I] window style
539 * text [I] pointer to the window text
540 * parent [I] handle to the parent window
541 * wid [I] control id of the status bar
543 * RETURNS
544 * Success: handle to the status window
545 * Failure: 0
548 HWND WINAPI
549 CreateStatusWindowW (LONG style, LPCWSTR text, HWND parent, UINT wid)
551 return CreateWindowW(STATUSCLASSNAMEW, text, style,
552 CW_USEDEFAULT, CW_USEDEFAULT,
553 CW_USEDEFAULT, CW_USEDEFAULT,
554 parent, (HMENU)(DWORD_PTR)wid, 0, 0);
558 /***********************************************************************
559 * CreateUpDownControl [COMCTL32.16]
561 * Creates an up-down control
563 * PARAMS
564 * style [I] window styles
565 * x [I] horizontal position of the control
566 * y [I] vertical position of the control
567 * cx [I] with of the control
568 * cy [I] height of the control
569 * parent [I] handle to the parent window
570 * id [I] the control's identifier
571 * inst [I] handle to the application's module instance
572 * buddy [I] handle to the buddy window, can be NULL
573 * maxVal [I] upper limit of the control
574 * minVal [I] lower limit of the control
575 * curVal [I] current value of the control
577 * RETURNS
578 * Success: handle to the updown control
579 * Failure: 0
582 HWND WINAPI
583 CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
584 HWND parent, INT id, HINSTANCE inst,
585 HWND buddy, INT maxVal, INT minVal, INT curVal)
587 HWND hUD =
588 CreateWindowW (UPDOWN_CLASSW, 0, style, x, y, cx, cy,
589 parent, (HMENU)(DWORD_PTR)id, inst, 0);
590 if (hUD) {
591 SendMessageW (hUD, UDM_SETBUDDY, (WPARAM)buddy, 0);
592 SendMessageW (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));
593 SendMessageW (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));
596 return hUD;
600 /***********************************************************************
601 * InitCommonControls [COMCTL32.17]
603 * Registers the common controls.
605 * PARAMS
606 * No parameters.
608 * RETURNS
609 * No return values.
611 * NOTES
612 * This function is just a dummy - all the controls are registered at
613 * the DLL initialization time. See InitCommonContolsEx for details.
616 VOID WINAPI
617 InitCommonControls (void)
622 /***********************************************************************
623 * InitCommonControlsEx [COMCTL32.@]
625 * Registers the common controls.
627 * PARAMS
628 * lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
630 * RETURNS
631 * Success: TRUE
632 * Failure: FALSE
634 * NOTES
635 * Probably all versions of comctl32 initializes the Win95 controls in DllMain
636 * during DLL initialization. Starting from comctl32 v5.82 all the controls
637 * are initialized there. We follow this behaviour and this function is just
638 * a dummy.
640 * Note: when writing programs under Windows, if you don't call any function
641 * from comctl32 the linker may not link this DLL. If InitCommonControlsEx
642 * was the only comctl32 function you were calling and you remove it you may
643 * have a false impression that InitCommonControlsEx actually did something.
646 BOOL WINAPI
647 InitCommonControlsEx (const INITCOMMONCONTROLSEX *lpInitCtrls)
649 if (!lpInitCtrls || lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
650 return FALSE;
652 TRACE("(0x%08x)\n", lpInitCtrls->dwICC);
653 return TRUE;
657 /***********************************************************************
658 * CreateToolbarEx [COMCTL32.@]
660 * Creates a toolbar window.
662 * PARAMS
663 * hwnd
664 * style
665 * wID
666 * nBitmaps
667 * hBMInst
668 * wBMID
669 * lpButtons
670 * iNumButtons
671 * dxButton
672 * dyButton
673 * dxBitmap
674 * dyBitmap
675 * uStructSize
677 * RETURNS
678 * Success: handle to the tool bar control
679 * Failure: 0
682 HWND WINAPI
683 CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
684 HINSTANCE hBMInst, UINT_PTR wBMID, LPCTBBUTTON lpButtons,
685 INT iNumButtons, INT dxButton, INT dyButton,
686 INT dxBitmap, INT dyBitmap, UINT uStructSize)
688 HWND hwndTB;
690 hwndTB =
691 CreateWindowExW(0, TOOLBARCLASSNAMEW, NULL, style|WS_CHILD, 0,0,100,30,
692 hwnd, (HMENU)(DWORD_PTR)wID, COMCTL32_hModule, NULL);
693 if(hwndTB) {
694 TBADDBITMAP tbab;
696 SendMessageW (hwndTB, TB_BUTTONSTRUCTSIZE, uStructSize, 0);
698 /* set bitmap and button size */
699 /*If CreateToolbarEx receives 0, windows sets default values*/
700 if (dxBitmap < 0)
701 dxBitmap = 16;
702 if (dyBitmap < 0)
703 dyBitmap = 16;
704 if (dxBitmap == 0 || dyBitmap == 0)
705 dxBitmap = dyBitmap = 16;
706 SendMessageW(hwndTB, TB_SETBITMAPSIZE, 0, MAKELPARAM(dxBitmap, dyBitmap));
708 if (dxButton < 0)
709 dxButton = dxBitmap;
710 if (dyButton < 0)
711 dyButton = dyBitmap;
712 /* TB_SETBUTTONSIZE -> TB_SETBITMAPSIZE bug introduced for Windows compatibility */
713 if (dxButton != 0 && dyButton != 0)
714 SendMessageW(hwndTB, TB_SETBITMAPSIZE, 0, MAKELPARAM(dxButton, dyButton));
717 /* add bitmaps */
718 if (nBitmaps > 0 || hBMInst == HINST_COMMCTRL)
720 tbab.hInst = hBMInst;
721 tbab.nID = wBMID;
723 SendMessageW (hwndTB, TB_ADDBITMAP, nBitmaps, (LPARAM)&tbab);
725 /* add buttons */
726 if(iNumButtons > 0)
727 SendMessageW (hwndTB, TB_ADDBUTTONSW, iNumButtons, (LPARAM)lpButtons);
730 return hwndTB;
734 /***********************************************************************
735 * CreateMappedBitmap [COMCTL32.8]
737 * Loads a bitmap resource using a colour map.
739 * PARAMS
740 * hInstance [I] Handle to the module containing the bitmap.
741 * idBitmap [I] The bitmap resource ID.
742 * wFlags [I] CMB_MASKED for using bitmap as a mask or 0 for normal.
743 * lpColorMap [I] Colour information needed for the bitmap or NULL (uses system colours).
744 * iNumMaps [I] Number of COLORMAP's pointed to by lpColorMap.
746 * RETURNS
747 * Success: handle to the new bitmap
748 * Failure: 0
751 HBITMAP WINAPI
752 CreateMappedBitmap (HINSTANCE hInstance, INT_PTR idBitmap, UINT wFlags,
753 LPCOLORMAP lpColorMap, INT iNumMaps)
755 HGLOBAL hglb;
756 HRSRC hRsrc;
757 const BITMAPINFOHEADER *lpBitmap;
758 LPBITMAPINFOHEADER lpBitmapInfo;
759 UINT nSize, nColorTableSize, iColor;
760 RGBQUAD *pColorTable;
761 INT i, iMaps, nWidth, nHeight;
762 HDC hdcScreen;
763 HBITMAP hbm;
764 LPCOLORMAP sysColorMap;
765 COLORREF cRef;
766 COLORMAP internalColorMap[4] =
767 {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
769 /* initialize pointer to colortable and default color table */
770 if (lpColorMap) {
771 iMaps = iNumMaps;
772 sysColorMap = lpColorMap;
774 else {
775 internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT);
776 internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW);
777 internalColorMap[2].to = GetSysColor (COLOR_BTNFACE);
778 internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT);
779 iMaps = 4;
780 sysColorMap = internalColorMap;
783 hRsrc = FindResourceW (hInstance, (LPWSTR)idBitmap, (LPWSTR)RT_BITMAP);
784 if (hRsrc == 0)
785 return 0;
786 hglb = LoadResource (hInstance, hRsrc);
787 if (hglb == 0)
788 return 0;
789 lpBitmap = LockResource (hglb);
790 if (lpBitmap == NULL)
791 return 0;
793 if (lpBitmap->biSize >= sizeof(BITMAPINFOHEADER) && lpBitmap->biClrUsed)
794 nColorTableSize = lpBitmap->biClrUsed;
795 else if (lpBitmap->biBitCount <= 8)
796 nColorTableSize = (1 << lpBitmap->biBitCount);
797 else
798 nColorTableSize = 0;
799 nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
800 lpBitmapInfo = GlobalAlloc (GMEM_FIXED, nSize);
801 if (lpBitmapInfo == NULL)
802 return 0;
803 RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);
805 pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo) + lpBitmapInfo->biSize);
807 for (iColor = 0; iColor < nColorTableSize; iColor++) {
808 for (i = 0; i < iMaps; i++) {
809 cRef = RGB(pColorTable[iColor].rgbRed,
810 pColorTable[iColor].rgbGreen,
811 pColorTable[iColor].rgbBlue);
812 if ( cRef == sysColorMap[i].from) {
813 #if 0
814 if (wFlags & CBS_MASKED) {
815 if (sysColorMap[i].to != COLOR_BTNTEXT)
816 pColorTable[iColor] = RGB(255, 255, 255);
818 else
819 #endif
820 pColorTable[iColor].rgbBlue = GetBValue(sysColorMap[i].to);
821 pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);
822 pColorTable[iColor].rgbRed = GetRValue(sysColorMap[i].to);
823 break;
827 nWidth = lpBitmapInfo->biWidth;
828 nHeight = lpBitmapInfo->biHeight;
829 hdcScreen = GetDC (NULL);
830 hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
831 if (hbm) {
832 HDC hdcDst = CreateCompatibleDC (hdcScreen);
833 HBITMAP hbmOld = SelectObject (hdcDst, hbm);
834 const BYTE *lpBits = (const BYTE *)lpBitmap + nSize;
835 StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
836 lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
837 SRCCOPY);
838 SelectObject (hdcDst, hbmOld);
839 DeleteDC (hdcDst);
841 ReleaseDC (NULL, hdcScreen);
842 GlobalFree (lpBitmapInfo);
843 FreeResource (hglb);
845 return hbm;
849 /***********************************************************************
850 * CreateToolbar [COMCTL32.7]
852 * Creates a toolbar control.
854 * PARAMS
855 * hwnd
856 * style
857 * wID
858 * nBitmaps
859 * hBMInst
860 * wBMID
861 * lpButtons
862 * iNumButtons
864 * RETURNS
865 * Success: handle to the tool bar control
866 * Failure: 0
868 * NOTES
869 * Do not use this functions anymore. Use CreateToolbarEx instead.
872 HWND WINAPI
873 CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
874 HINSTANCE hBMInst, UINT wBMID,
875 LPCTBBUTTON lpButtons,INT iNumButtons)
877 return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
878 hBMInst, wBMID, lpButtons,
879 iNumButtons, 0, 0, 0, 0, CCSIZEOF_STRUCT(TBBUTTON, dwData));
883 /***********************************************************************
884 * DllGetVersion [COMCTL32.@]
886 * Retrieves version information of the 'COMCTL32.DLL'
888 * PARAMS
889 * pdvi [O] pointer to version information structure.
891 * RETURNS
892 * Success: S_OK
893 * Failure: E_INVALIDARG
895 * NOTES
896 * Returns version of a comctl32.dll from IE4.01 SP1.
899 HRESULT WINAPI DllGetVersion (DLLVERSIONINFO *pdvi)
901 if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
902 WARN("wrong DLLVERSIONINFO size from app\n");
903 return E_INVALIDARG;
906 pdvi->dwMajorVersion = COMCTL32_VERSION;
907 pdvi->dwMinorVersion = COMCTL32_VERSION_MINOR;
908 pdvi->dwBuildNumber = 2919;
909 pdvi->dwPlatformID = 6304;
911 TRACE("%u.%u.%u.%u\n",
912 pdvi->dwMajorVersion, pdvi->dwMinorVersion,
913 pdvi->dwBuildNumber, pdvi->dwPlatformID);
915 return S_OK;
918 /***********************************************************************
919 * DllInstall (COMCTL32.@)
921 * Installs the ComCtl32 DLL.
923 * RETURNS
924 * Success: S_OK
925 * Failure: A HRESULT error
927 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
929 TRACE("(%u, %s): stub\n", bInstall, debugstr_w(cmdline));
930 return S_OK;
933 /***********************************************************************
934 * _TrackMouseEvent [COMCTL32.@]
936 * Requests notification of mouse events
938 * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
939 * to the hwnd specified in the ptme structure. After the event message
940 * is posted to the hwnd, the entry in the queue is removed.
942 * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
943 * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
944 * immediately and the TME_LEAVE flag being ignored.
946 * PARAMS
947 * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
949 * RETURNS
950 * Success: non-zero
951 * Failure: zero
953 * IMPLEMENTATION moved to USER32.TrackMouseEvent
957 BOOL WINAPI
958 _TrackMouseEvent (TRACKMOUSEEVENT *ptme)
960 return TrackMouseEvent (ptme);
963 /*************************************************************************
964 * GetMUILanguage [COMCTL32.@]
966 * Returns the user interface language in use by the current process.
968 * RETURNS
969 * Language ID in use by the current process.
971 LANGID WINAPI GetMUILanguage (VOID)
973 return COMCTL32_uiLang;
977 /*************************************************************************
978 * InitMUILanguage [COMCTL32.@]
980 * Sets the user interface language to be used by the current process.
982 * RETURNS
983 * Nothing.
985 VOID WINAPI InitMUILanguage (LANGID uiLang)
987 COMCTL32_uiLang = uiLang;
991 /***********************************************************************
992 * SetWindowSubclass [COMCTL32.410]
994 * Starts a window subclass
996 * PARAMS
997 * hWnd [in] handle to window subclass.
998 * pfnSubclass [in] Pointer to new window procedure.
999 * uIDSubclass [in] Unique identifier of subclass together with pfnSubclass.
1000 * dwRef [in] Reference data to pass to window procedure.
1002 * RETURNS
1003 * Success: non-zero
1004 * Failure: zero
1006 * BUGS
1007 * If an application manually subclasses a window after subclassing it with
1008 * this API and then with this API again, then none of the previous
1009 * subclasses get called or the original window procedure.
1012 BOOL WINAPI SetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
1013 UINT_PTR uIDSubclass, DWORD_PTR dwRef)
1015 LPSUBCLASS_INFO stack;
1016 LPSUBCLASSPROCS proc;
1018 TRACE ("(%p, %p, %lx, %lx)\n", hWnd, pfnSubclass, uIDSubclass, dwRef);
1020 /* Since the window procedure that we set here has two additional arguments,
1021 * we can't simply set it as the new window procedure of the window. So we
1022 * set our own window procedure and then calculate the other two arguments
1023 * from there. */
1025 /* See if we have been called for this window */
1026 stack = GetPropW (hWnd, COMCTL32_wSubclass);
1027 if (!stack) {
1028 /* allocate stack */
1029 stack = Alloc (sizeof(SUBCLASS_INFO));
1030 if (!stack) {
1031 ERR ("Failed to allocate our Subclassing stack\n");
1032 return FALSE;
1034 SetPropW (hWnd, COMCTL32_wSubclass, stack);
1036 /* set window procedure to our own and save the current one */
1037 if (IsWindowUnicode (hWnd))
1038 stack->origproc = (WNDPROC)SetWindowLongPtrW (hWnd, GWLP_WNDPROC,
1039 (DWORD_PTR)COMCTL32_SubclassProc);
1040 else
1041 stack->origproc = (WNDPROC)SetWindowLongPtrA (hWnd, GWLP_WNDPROC,
1042 (DWORD_PTR)COMCTL32_SubclassProc);
1044 else {
1045 /* Check to see if we have called this function with the same uIDSubClass
1046 * and pfnSubclass */
1047 proc = stack->SubclassProcs;
1048 while (proc) {
1049 if ((proc->id == uIDSubclass) &&
1050 (proc->subproc == pfnSubclass)) {
1051 proc->ref = dwRef;
1052 return TRUE;
1054 proc = proc->next;
1058 proc = Alloc(sizeof(SUBCLASSPROCS));
1059 if (!proc) {
1060 ERR ("Failed to allocate subclass entry in stack\n");
1061 if (IsWindowUnicode (hWnd))
1062 SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1063 else
1064 SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1065 Free (stack);
1066 RemovePropW( hWnd, COMCTL32_wSubclass );
1067 return FALSE;
1070 proc->subproc = pfnSubclass;
1071 proc->ref = dwRef;
1072 proc->id = uIDSubclass;
1073 proc->next = stack->SubclassProcs;
1074 stack->SubclassProcs = proc;
1076 return TRUE;
1080 /***********************************************************************
1081 * GetWindowSubclass [COMCTL32.411]
1083 * Gets the Reference data from a subclass.
1085 * PARAMS
1086 * hWnd [in] Handle to window which were subclassing
1087 * pfnSubclass [in] Pointer to the subclass procedure
1088 * uID [in] Unique identifier of the subclassing procedure
1089 * pdwRef [out] Pointer to the reference data
1091 * RETURNS
1092 * Success: Non-zero
1093 * Failure: 0
1096 BOOL WINAPI GetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
1097 UINT_PTR uID, DWORD_PTR *pdwRef)
1099 const SUBCLASS_INFO *stack;
1100 const SUBCLASSPROCS *proc;
1102 TRACE ("(%p, %p, %lx, %p)\n", hWnd, pfnSubclass, uID, pdwRef);
1104 /* See if we have been called for this window */
1105 stack = GetPropW (hWnd, COMCTL32_wSubclass);
1106 if (!stack)
1107 return FALSE;
1109 proc = stack->SubclassProcs;
1110 while (proc) {
1111 if ((proc->id == uID) &&
1112 (proc->subproc == pfnSubclass)) {
1113 *pdwRef = proc->ref;
1114 return TRUE;
1116 proc = proc->next;
1119 return FALSE;
1123 /***********************************************************************
1124 * RemoveWindowSubclass [COMCTL32.412]
1126 * Removes a window subclass.
1128 * PARAMS
1129 * hWnd [in] Handle to the window were subclassing
1130 * pfnSubclass [in] Pointer to the subclass procedure
1131 * uID [in] Unique identifier of this subclass
1133 * RETURNS
1134 * Success: non-zero
1135 * Failure: zero
1138 BOOL WINAPI RemoveWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR uID)
1140 LPSUBCLASS_INFO stack;
1141 LPSUBCLASSPROCS prevproc = NULL;
1142 LPSUBCLASSPROCS proc;
1143 BOOL ret = FALSE;
1145 TRACE ("(%p, %p, %lx)\n", hWnd, pfnSubclass, uID);
1147 /* Find the Subclass to remove */
1148 stack = GetPropW (hWnd, COMCTL32_wSubclass);
1149 if (!stack)
1150 return FALSE;
1152 proc = stack->SubclassProcs;
1153 while (proc) {
1154 if ((proc->id == uID) &&
1155 (proc->subproc == pfnSubclass)) {
1157 if (!prevproc)
1158 stack->SubclassProcs = proc->next;
1159 else
1160 prevproc->next = proc->next;
1162 if (stack->stackpos == proc)
1163 stack->stackpos = stack->stackpos->next;
1165 Free (proc);
1166 ret = TRUE;
1167 break;
1169 prevproc = proc;
1170 proc = proc->next;
1173 if (!stack->SubclassProcs && !stack->running) {
1174 TRACE("Last Subclass removed, cleaning up\n");
1175 /* clean up our heap and reset the original window procedure */
1176 if (IsWindowUnicode (hWnd))
1177 SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1178 else
1179 SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1180 Free (stack);
1181 RemovePropW( hWnd, COMCTL32_wSubclass );
1184 return ret;
1187 /***********************************************************************
1188 * COMCTL32_SubclassProc (internal)
1190 * Window procedure for all subclassed windows.
1191 * Saves the current subclassing stack position to support nested messages
1193 static LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1195 LPSUBCLASS_INFO stack;
1196 LPSUBCLASSPROCS proc;
1197 LRESULT ret;
1199 TRACE ("(%p, 0x%08x, 0x%08lx, 0x%08lx)\n", hWnd, uMsg, wParam, lParam);
1201 stack = GetPropW (hWnd, COMCTL32_wSubclass);
1202 if (!stack) {
1203 ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
1204 return 0;
1207 /* Save our old stackpos to properly handle nested messages */
1208 proc = stack->stackpos;
1209 stack->stackpos = stack->SubclassProcs;
1210 stack->running++;
1211 ret = DefSubclassProc(hWnd, uMsg, wParam, lParam);
1212 stack->running--;
1213 stack->stackpos = proc;
1215 if (!stack->SubclassProcs && !stack->running) {
1216 TRACE("Last Subclass removed, cleaning up\n");
1217 /* clean up our heap and reset the original window procedure */
1218 if (IsWindowUnicode (hWnd))
1219 SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1220 else
1221 SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1222 Free (stack);
1223 RemovePropW( hWnd, COMCTL32_wSubclass );
1225 return ret;
1228 /***********************************************************************
1229 * DefSubclassProc [COMCTL32.413]
1231 * Calls the next window procedure (i.e. the one before this subclass)
1233 * PARAMS
1234 * hWnd [in] The window that we're subclassing
1235 * uMsg [in] Message
1236 * wParam [in] WPARAM
1237 * lParam [in] LPARAM
1239 * RETURNS
1240 * Success: non-zero
1241 * Failure: zero
1244 LRESULT WINAPI DefSubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1246 LPSUBCLASS_INFO stack;
1247 LRESULT ret;
1249 TRACE ("(%p, 0x%08x, 0x%08lx, 0x%08lx)\n", hWnd, uMsg, wParam, lParam);
1251 /* retrieve our little stack from the Properties */
1252 stack = GetPropW (hWnd, COMCTL32_wSubclass);
1253 if (!stack) {
1254 ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
1255 return 0;
1258 /* If we are at the end of stack then we have to call the original
1259 * window procedure */
1260 if (!stack->stackpos) {
1261 if (IsWindowUnicode (hWnd))
1262 ret = CallWindowProcW (stack->origproc, hWnd, uMsg, wParam, lParam);
1263 else
1264 ret = CallWindowProcA (stack->origproc, hWnd, uMsg, wParam, lParam);
1265 } else {
1266 const SUBCLASSPROCS *proc = stack->stackpos;
1267 stack->stackpos = stack->stackpos->next;
1268 /* call the Subclass procedure from the stack */
1269 ret = proc->subproc (hWnd, uMsg, wParam, lParam,
1270 proc->id, proc->ref);
1273 return ret;
1277 /***********************************************************************
1278 * COMCTL32_CreateToolTip [NOT AN API]
1280 * Creates a tooltip for the control specified in hwnd and does all
1281 * necessary setup and notifications.
1283 * PARAMS
1284 * hwndOwner [I] Handle to the window that will own the tool tip.
1286 * RETURNS
1287 * Success: Handle of tool tip window.
1288 * Failure: NULL
1291 HWND
1292 COMCTL32_CreateToolTip(HWND hwndOwner)
1294 HWND hwndToolTip;
1296 hwndToolTip = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, WS_POPUP,
1297 CW_USEDEFAULT, CW_USEDEFAULT,
1298 CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner,
1299 0, 0, 0);
1301 /* Send NM_TOOLTIPSCREATED notification */
1302 if (hwndToolTip)
1304 NMTOOLTIPSCREATED nmttc;
1305 /* true owner can be different if hwndOwner is a child window */
1306 HWND hwndTrueOwner = GetWindow(hwndToolTip, GW_OWNER);
1307 nmttc.hdr.hwndFrom = hwndTrueOwner;
1308 nmttc.hdr.idFrom = GetWindowLongPtrW(hwndTrueOwner, GWLP_ID);
1309 nmttc.hdr.code = NM_TOOLTIPSCREATED;
1310 nmttc.hwndToolTips = hwndToolTip;
1312 SendMessageW(GetParent(hwndTrueOwner), WM_NOTIFY,
1313 GetWindowLongPtrW(hwndTrueOwner, GWLP_ID), (LPARAM)&nmttc);
1316 return hwndToolTip;
1320 /***********************************************************************
1321 * COMCTL32_RefreshSysColors [NOT AN API]
1323 * Invoked on any control recognizing a WM_SYSCOLORCHANGE message to
1324 * refresh the color values in the color structure
1326 * PARAMS
1327 * none
1329 * RETURNS
1330 * none
1333 VOID
1334 COMCTL32_RefreshSysColors(void)
1336 comctl32_color.clrBtnHighlight = GetSysColor (COLOR_BTNHIGHLIGHT);
1337 comctl32_color.clrBtnShadow = GetSysColor (COLOR_BTNSHADOW);
1338 comctl32_color.clrBtnText = GetSysColor (COLOR_BTNTEXT);
1339 comctl32_color.clrBtnFace = GetSysColor (COLOR_BTNFACE);
1340 comctl32_color.clrHighlight = GetSysColor (COLOR_HIGHLIGHT);
1341 comctl32_color.clrHighlightText = GetSysColor (COLOR_HIGHLIGHTTEXT);
1342 comctl32_color.clrHotTrackingColor = GetSysColor (COLOR_HOTLIGHT);
1343 comctl32_color.clr3dHilight = GetSysColor (COLOR_3DHILIGHT);
1344 comctl32_color.clr3dShadow = GetSysColor (COLOR_3DSHADOW);
1345 comctl32_color.clr3dDkShadow = GetSysColor (COLOR_3DDKSHADOW);
1346 comctl32_color.clr3dFace = GetSysColor (COLOR_3DFACE);
1347 comctl32_color.clrWindow = GetSysColor (COLOR_WINDOW);
1348 comctl32_color.clrWindowText = GetSysColor (COLOR_WINDOWTEXT);
1349 comctl32_color.clrGrayText = GetSysColor (COLOR_GRAYTEXT);
1350 comctl32_color.clrActiveCaption = GetSysColor (COLOR_ACTIVECAPTION);
1351 comctl32_color.clrInfoBk = GetSysColor (COLOR_INFOBK);
1352 comctl32_color.clrInfoText = GetSysColor (COLOR_INFOTEXT);
1355 /***********************************************************************
1356 * COMCTL32_DrawInsertMark [NOT AN API]
1358 * Draws an insertion mark (which looks similar to an 'I').
1360 * PARAMS
1361 * hDC [I] Device context to draw onto.
1362 * lpRect [I] Co-ordinates of insertion mark.
1363 * clrInsertMark [I] Colour of the insertion mark.
1364 * bHorizontal [I] True if insert mark should be drawn horizontally,
1365 * vertical otherwise.
1367 * RETURNS
1368 * none
1370 * NOTES
1371 * Draws up to but not including the bottom co-ordinate when drawing
1372 * vertically or the right co-ordinate when horizontal.
1374 void COMCTL32_DrawInsertMark(HDC hDC, const RECT *lpRect, COLORREF clrInsertMark, BOOL bHorizontal)
1376 HPEN hPen = CreatePen(PS_SOLID, 1, clrInsertMark);
1377 HPEN hOldPen;
1378 static const DWORD adwPolyPoints[] = {4,4,4};
1379 LONG lCentre = (bHorizontal ?
1380 lpRect->top + (lpRect->bottom - lpRect->top)/2 :
1381 lpRect->left + (lpRect->right - lpRect->left)/2);
1382 LONG l1 = (bHorizontal ? lpRect->left : lpRect->top);
1383 LONG l2 = (bHorizontal ? lpRect->right : lpRect->bottom);
1384 const POINT aptInsertMark[] =
1386 /* top (V) or left (H) arrow */
1387 {lCentre , l1 + 2},
1388 {lCentre - 2, l1 },
1389 {lCentre + 3, l1 },
1390 {lCentre + 1, l1 + 2},
1391 /* middle line */
1392 {lCentre , l2 - 2},
1393 {lCentre , l1 - 1},
1394 {lCentre + 1, l1 - 1},
1395 {lCentre + 1, l2 - 2},
1396 /* bottom (V) or right (H) arrow */
1397 {lCentre , l2 - 3},
1398 {lCentre - 2, l2 - 1},
1399 {lCentre + 3, l2 - 1},
1400 {lCentre + 1, l2 - 3},
1402 hOldPen = SelectObject(hDC, hPen);
1403 PolyPolyline(hDC, aptInsertMark, adwPolyPoints, sizeof(adwPolyPoints)/sizeof(adwPolyPoints[0]));
1404 SelectObject(hDC, hOldPen);
1405 DeleteObject(hPen);
1408 /***********************************************************************
1409 * COMCTL32_EnsureBitmapSize [internal]
1411 * If needed, enlarge the bitmap so that the width is at least cxMinWidth and
1412 * the height is at least cyMinHeight. If the bitmap already has these
1413 * dimensions nothing changes.
1415 * PARAMS
1416 * hBitmap [I/O] Bitmap to modify. The handle may change
1417 * cxMinWidth [I] If the width of the bitmap is smaller, then it will
1418 * be enlarged to this value
1419 * cyMinHeight [I] If the height of the bitmap is smaller, then it will
1420 * be enlarged to this value
1421 * cyBackground [I] The color with which the new area will be filled
1423 * RETURNS
1424 * none
1426 void COMCTL32_EnsureBitmapSize(HBITMAP *pBitmap, int cxMinWidth, int cyMinHeight, COLORREF crBackground)
1428 int cxNew, cyNew;
1429 BITMAP bmp;
1430 HBITMAP hNewBitmap;
1431 HBITMAP hNewDCBitmap, hOldDCBitmap;
1432 HBRUSH hNewDCBrush;
1433 HDC hdcNew, hdcOld;
1435 if (!GetObjectW(*pBitmap, sizeof(BITMAP), &bmp))
1436 return;
1437 cxNew = (cxMinWidth > bmp.bmWidth ? cxMinWidth : bmp.bmWidth);
1438 cyNew = (cyMinHeight > bmp.bmHeight ? cyMinHeight : bmp.bmHeight);
1439 if (cxNew == bmp.bmWidth && cyNew == bmp.bmHeight)
1440 return;
1442 hdcNew = CreateCompatibleDC(NULL);
1443 hNewBitmap = CreateBitmap(cxNew, cyNew, bmp.bmPlanes, bmp.bmBitsPixel, NULL);
1444 hNewDCBitmap = SelectObject(hdcNew, hNewBitmap);
1445 hNewDCBrush = SelectObject(hdcNew, CreateSolidBrush(crBackground));
1447 hdcOld = CreateCompatibleDC(NULL);
1448 hOldDCBitmap = SelectObject(hdcOld, *pBitmap);
1450 BitBlt(hdcNew, 0, 0, bmp.bmWidth, bmp.bmHeight, hdcOld, 0, 0, SRCCOPY);
1451 if (bmp.bmWidth < cxMinWidth)
1452 PatBlt(hdcNew, bmp.bmWidth, 0, cxNew, bmp.bmHeight, PATCOPY);
1453 if (bmp.bmHeight < cyMinHeight)
1454 PatBlt(hdcNew, 0, bmp.bmHeight, bmp.bmWidth, cyNew, PATCOPY);
1455 if (bmp.bmWidth < cxMinWidth && bmp.bmHeight < cyMinHeight)
1456 PatBlt(hdcNew, bmp.bmWidth, bmp.bmHeight, cxNew, cyNew, PATCOPY);
1458 SelectObject(hdcNew, hNewDCBitmap);
1459 DeleteObject(SelectObject(hdcNew, hNewDCBrush));
1460 DeleteDC(hdcNew);
1461 SelectObject(hdcOld, hOldDCBitmap);
1462 DeleteDC(hdcOld);
1464 DeleteObject(*pBitmap);
1465 *pBitmap = hNewBitmap;
1466 return;
1469 void COMCTL32_GetFontMetrics(HFONT hFont, TEXTMETRICW *ptm)
1471 HDC hdc = GetDC(NULL);
1472 HFONT hOldFont;
1474 hOldFont = SelectObject(hdc, hFont);
1475 GetTextMetricsW(hdc, ptm);
1476 SelectObject(hdc, hOldFont);
1477 ReleaseDC(NULL, hdc);
1480 #ifndef OCM__BASE /* avoid including olectl.h */
1481 #define OCM__BASE (WM_USER+0x1c00)
1482 #endif
1484 /***********************************************************************
1485 * COMCTL32_IsReflectedMessage [internal]
1487 * Some parents reflect notify messages - for some messages sent by the child,
1488 * they send it back with the message code increased by OCM__BASE (0x2000).
1489 * This allows better subclassing of controls. We don't need to handle such
1490 * messages but we don't want to print ERRs for them, so this helper function
1491 * identifies them.
1493 * Some of the codes are in the CCM_FIRST..CCM_LAST range, but there is no
1494 * colision with defined CCM_ codes.
1496 BOOL COMCTL32_IsReflectedMessage(UINT uMsg)
1498 switch (uMsg)
1500 case OCM__BASE + WM_COMMAND:
1501 case OCM__BASE + WM_CTLCOLORBTN:
1502 case OCM__BASE + WM_CTLCOLOREDIT:
1503 case OCM__BASE + WM_CTLCOLORDLG:
1504 case OCM__BASE + WM_CTLCOLORLISTBOX:
1505 case OCM__BASE + WM_CTLCOLORMSGBOX:
1506 case OCM__BASE + WM_CTLCOLORSCROLLBAR:
1507 case OCM__BASE + WM_CTLCOLORSTATIC:
1508 case OCM__BASE + WM_DRAWITEM:
1509 case OCM__BASE + WM_MEASUREITEM:
1510 case OCM__BASE + WM_DELETEITEM:
1511 case OCM__BASE + WM_VKEYTOITEM:
1512 case OCM__BASE + WM_CHARTOITEM:
1513 case OCM__BASE + WM_COMPAREITEM:
1514 case OCM__BASE + WM_HSCROLL:
1515 case OCM__BASE + WM_VSCROLL:
1516 case OCM__BASE + WM_PARENTNOTIFY:
1517 case OCM__BASE + WM_NOTIFY:
1518 return TRUE;
1519 default:
1520 return FALSE;
1524 /***********************************************************************
1525 * MirrorIcon [COMCTL32.414]
1527 * Mirrors an icon so that it will appear correctly on a mirrored DC.
1529 * PARAMS
1530 * phicon1 [I/O] Icon.
1531 * phicon2 [I/O] Icon.
1533 * RETURNS
1534 * Success: TRUE.
1535 * Failure: FALSE.
1537 BOOL WINAPI MirrorIcon(HICON *phicon1, HICON *phicon2)
1539 FIXME("(%p, %p): stub\n", phicon1, phicon2);
1540 return FALSE;
1543 static inline int IsDelimiter(WCHAR c)
1545 switch(c)
1547 case '/':
1548 case '\\':
1549 case '.':
1550 case ' ':
1551 return TRUE;
1553 return FALSE;
1556 static int CALLBACK PathWordBreakProc(LPCWSTR lpch, int ichCurrent, int cch, int code)
1558 if (code == WB_ISDELIMITER)
1559 return IsDelimiter(lpch[ichCurrent]);
1560 else
1562 int dir = (code == WB_LEFT) ? -1 : 1;
1563 for(; 0 <= ichCurrent && ichCurrent < cch; ichCurrent += dir)
1564 if (IsDelimiter(lpch[ichCurrent])) return ichCurrent;
1566 return ichCurrent;
1569 /***********************************************************************
1570 * SetPathWordBreakProc [COMCTL32.384]
1572 * Sets the word break procedure for an edit control to one that understands
1573 * paths so that the user can jump over directories.
1575 * PARAMS
1576 * hwnd [I] Handle to edit control.
1577 * bSet [I] If this is TRUE then the word break proc is set, otherwise it is removed.
1579 * RETURNS
1580 * Result from EM_SETWORDBREAKPROC message.
1582 LRESULT WINAPI SetPathWordBreakProc(HWND hwnd, BOOL bSet)
1584 return SendMessageW(hwnd, EM_SETWORDBREAKPROC, 0,
1585 (LPARAM)(bSet ? PathWordBreakProc : NULL));
1588 /***********************************************************************
1589 * DrawShadowText [COMCTL32.@]
1591 * Draw text with shadow.
1593 int WINAPI DrawShadowText(HDC hdc, LPCWSTR pszText, UINT cch, RECT *rect, DWORD dwFlags,
1594 COLORREF crText, COLORREF crShadow, int ixOffset, int iyOffset)
1596 FIXME("(%p, %s, %d, %p, %d, 0x%08x, 0x%08x, %d, %d): stub\n", hdc, debugstr_w(pszText), cch, rect, dwFlags,
1597 crText, crShadow, ixOffset, iyOffset);
1598 return DrawTextW(hdc, pszText, cch, rect, DT_LEFT);
1601 /***********************************************************************
1602 * TaskDialogIndirect [COMCTL32.@]
1604 HRESULT WINAPI TaskDialogIndirect(const TASKDIALOGCONFIG *pTaskConfig, int *pnButton,
1605 int *pnRadioButton, BOOL *pfVerificationFlagChecked)
1607 UINT uType = 0;
1608 INT ret;
1609 FIXME("%p, %p, %p, %p\n", pTaskConfig, pnButton, pnRadioButton, pfVerificationFlagChecked);
1611 if (pTaskConfig->dwCommonButtons & TDCBF_YES_BUTTON &&
1612 pTaskConfig->dwCommonButtons & TDCBF_NO_BUTTON &&
1613 pTaskConfig->dwCommonButtons & TDCBF_CANCEL_BUTTON)
1614 uType |= MB_YESNOCANCEL;
1615 else
1616 if (pTaskConfig->dwCommonButtons & TDCBF_YES_BUTTON &&
1617 pTaskConfig->dwCommonButtons & TDCBF_NO_BUTTON)
1618 uType |= MB_YESNO;
1619 else
1620 if (pTaskConfig->dwCommonButtons & TDCBF_RETRY_BUTTON &&
1621 pTaskConfig->dwCommonButtons & TDCBF_CANCEL_BUTTON)
1622 uType |= MB_RETRYCANCEL;
1623 else
1624 if (pTaskConfig->dwCommonButtons & TDCBF_OK_BUTTON &&
1625 pTaskConfig->dwCommonButtons & TDCBF_CANCEL_BUTTON)
1626 uType |= MB_OKCANCEL;
1627 else
1628 if (pTaskConfig->dwCommonButtons & TDCBF_OK_BUTTON)
1629 uType |= MB_OK;
1630 ret = MessageBoxW(pTaskConfig->hwndParent, pTaskConfig->pszMainInstruction,
1631 pTaskConfig->pszWindowTitle, uType);
1632 FIXME("dwCommonButtons=%x uType=%x ret=%x\n", pTaskConfig->dwCommonButtons, uType, ret);
1634 if (pnButton) *pnButton = ret;
1635 if (pnRadioButton) *pnRadioButton = pTaskConfig->nDefaultButton;
1636 if (pfVerificationFlagChecked) *pfVerificationFlagChecked = TRUE;
1637 return S_OK;