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