netcfgx: Add INetCfgLock support.
[wine/multimedia.git] / dlls / comctl32 / commctrl.c
blob4f4e2b18be7163a61e8d007e3c21a27eaa46ef2d
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 if (lpvReserved) break;
161 /* clean up subclassing */
162 THEMING_Uninitialize();
164 /* unregister all common control classes */
165 ANIMATE_Unregister ();
166 COMBOEX_Unregister ();
167 DATETIME_Unregister ();
168 FLATSB_Unregister ();
169 HEADER_Unregister ();
170 HOTKEY_Unregister ();
171 IPADDRESS_Unregister ();
172 LISTVIEW_Unregister ();
173 MONTHCAL_Unregister ();
174 NATIVEFONT_Unregister ();
175 PAGER_Unregister ();
176 PROGRESS_Unregister ();
177 REBAR_Unregister ();
178 STATUS_Unregister ();
179 SYSLINK_Unregister ();
180 TAB_Unregister ();
181 TOOLBAR_Unregister ();
182 TOOLTIPS_Unregister ();
183 TRACKBAR_Unregister ();
184 TREEVIEW_Unregister ();
185 UPDOWN_Unregister ();
187 /* delete local pattern brush */
188 DeleteObject (COMCTL32_hPattern55AABrush);
189 DeleteObject (COMCTL32_hPattern55AABitmap);
191 /* delete global subclassing atom */
192 GlobalDeleteAtom (LOWORD(COMCTL32_wSubclass));
193 TRACE("Subclassing atom deleted: %p\n", COMCTL32_wSubclass);
194 break;
197 return TRUE;
201 /***********************************************************************
202 * MenuHelp [COMCTL32.2]
204 * Handles the setting of status bar help messages when the user
205 * selects menu items.
207 * PARAMS
208 * uMsg [I] message (WM_MENUSELECT) (see NOTES)
209 * wParam [I] wParam of the message uMsg
210 * lParam [I] lParam of the message uMsg
211 * hMainMenu [I] handle to the application's main menu
212 * hInst [I] handle to the module that contains string resources
213 * hwndStatus [I] handle to the status bar window
214 * lpwIDs [I] pointer to an array of integers (see NOTES)
216 * RETURNS
217 * No return value
219 * NOTES
220 * The official documentation is incomplete!
221 * This is the correct documentation:
223 * uMsg:
224 * MenuHelp() does NOT handle WM_COMMAND messages! It only handles
225 * WM_MENUSELECT messages.
227 * lpwIDs:
228 * (will be written ...)
231 VOID WINAPI
232 MenuHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu,
233 HINSTANCE hInst, HWND hwndStatus, UINT* lpwIDs)
235 UINT uMenuID = 0;
237 if (!IsWindow (hwndStatus))
238 return;
240 switch (uMsg) {
241 case WM_MENUSELECT:
242 TRACE("WM_MENUSELECT wParam=0x%lX lParam=0x%lX\n",
243 wParam, lParam);
245 if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {
246 /* menu was closed */
247 TRACE("menu was closed!\n");
248 SendMessageW (hwndStatus, SB_SIMPLE, FALSE, 0);
250 else {
251 /* menu item was selected */
252 if (HIWORD(wParam) & MF_POPUP)
253 uMenuID = *(lpwIDs+1);
254 else
255 uMenuID = (UINT)LOWORD(wParam);
256 TRACE("uMenuID = %u\n", uMenuID);
258 if (uMenuID) {
259 WCHAR szText[256];
261 if (!LoadStringW (hInst, uMenuID, szText, sizeof(szText)/sizeof(szText[0])))
262 szText[0] = '\0';
264 SendMessageW (hwndStatus, SB_SETTEXTW,
265 255 | SBT_NOBORDERS, (LPARAM)szText);
266 SendMessageW (hwndStatus, SB_SIMPLE, TRUE, 0);
269 break;
271 case WM_COMMAND :
272 TRACE("WM_COMMAND wParam=0x%lX lParam=0x%lX\n",
273 wParam, lParam);
274 /* WM_COMMAND is not invalid since it is documented
275 * in the windows api reference. So don't output
276 * any FIXME for WM_COMMAND
278 WARN("We don't care about the WM_COMMAND\n");
279 break;
281 default:
282 FIXME("Invalid Message 0x%x!\n", uMsg);
283 break;
288 /***********************************************************************
289 * ShowHideMenuCtl [COMCTL32.3]
291 * Shows or hides controls and updates the corresponding menu item.
293 * PARAMS
294 * hwnd [I] handle to the client window.
295 * uFlags [I] menu command id.
296 * lpInfo [I] pointer to an array of integers. (See NOTES.)
298 * RETURNS
299 * Success: TRUE
300 * Failure: FALSE
302 * NOTES
303 * The official documentation is incomplete!
304 * This is the correct documentation:
306 * hwnd
307 * Handle to the window that contains the menu and controls.
309 * uFlags
310 * Identifier of the menu item to receive or lose a check mark.
312 * lpInfo
313 * The array of integers contains pairs of values. BOTH values of
314 * the first pair must be the handles to the application's main menu.
315 * Each subsequent pair consists of a menu id and control id.
318 BOOL WINAPI
319 ShowHideMenuCtl (HWND hwnd, UINT_PTR uFlags, LPINT lpInfo)
321 LPINT lpMenuId;
323 TRACE("%p, %lx, %p\n", hwnd, uFlags, lpInfo);
325 if (lpInfo == NULL)
326 return FALSE;
328 if (!(lpInfo[0]) || !(lpInfo[1]))
329 return FALSE;
331 /* search for control */
332 lpMenuId = &lpInfo[2];
333 while (*lpMenuId != uFlags)
334 lpMenuId += 2;
336 if (GetMenuState ((HMENU)(DWORD_PTR)lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) {
337 /* uncheck menu item */
338 CheckMenuItem ((HMENU)(DWORD_PTR)lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_UNCHECKED);
340 /* hide control */
341 lpMenuId++;
342 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
343 SWP_HIDEWINDOW);
345 else {
346 /* check menu item */
347 CheckMenuItem ((HMENU)(DWORD_PTR)lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_CHECKED);
349 /* show control */
350 lpMenuId++;
351 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
352 SWP_SHOWWINDOW);
355 return TRUE;
359 /***********************************************************************
360 * GetEffectiveClientRect [COMCTL32.4]
362 * Calculates the coordinates of a rectangle in the client area.
364 * PARAMS
365 * hwnd [I] handle to the client window.
366 * lpRect [O] pointer to the rectangle of the client window
367 * lpInfo [I] pointer to an array of integers (see NOTES)
369 * RETURNS
370 * No return value.
372 * NOTES
373 * The official documentation is incomplete!
374 * This is the correct documentation:
376 * lpInfo
377 * (will be written ...)
380 VOID WINAPI
381 GetEffectiveClientRect (HWND hwnd, LPRECT lpRect, const INT *lpInfo)
383 RECT rcCtrl;
384 const INT *lpRun;
385 HWND hwndCtrl;
387 TRACE("(%p %p %p)\n",
388 hwnd, lpRect, lpInfo);
390 GetClientRect (hwnd, lpRect);
391 lpRun = lpInfo;
393 do {
394 lpRun += 2;
395 if (*lpRun == 0)
396 return;
397 lpRun++;
398 hwndCtrl = GetDlgItem (hwnd, *lpRun);
399 if (GetWindowLongW (hwndCtrl, GWL_STYLE) & WS_VISIBLE) {
400 TRACE("control id 0x%x\n", *lpRun);
401 GetWindowRect (hwndCtrl, &rcCtrl);
402 MapWindowPoints (NULL, hwnd, (LPPOINT)&rcCtrl, 2);
403 SubtractRect (lpRect, lpRect, &rcCtrl);
405 lpRun++;
406 } while (*lpRun);
410 /***********************************************************************
411 * DrawStatusTextW [COMCTL32.@]
413 * Draws text with borders, like in a status bar.
415 * PARAMS
416 * hdc [I] handle to the window's display context
417 * lprc [I] pointer to a rectangle
418 * text [I] pointer to the text
419 * style [I] drawing style
421 * RETURNS
422 * No return value.
424 * NOTES
425 * The style variable can have one of the following values:
426 * (will be written ...)
429 void WINAPI DrawStatusTextW (HDC hdc, LPCRECT lprc, LPCWSTR text, UINT style)
431 RECT r = *lprc;
432 UINT border = BDR_SUNKENOUTER;
434 if (style & SBT_POPOUT)
435 border = BDR_RAISEDOUTER;
436 else if (style & SBT_NOBORDERS)
437 border = 0;
439 DrawEdge (hdc, &r, border, BF_RECT|BF_ADJUST);
441 /* now draw text */
442 if (text) {
443 int oldbkmode = SetBkMode (hdc, TRANSPARENT);
444 UINT align = DT_LEFT;
445 int strCnt = 0;
447 if (style & SBT_RTLREADING)
448 FIXME("Unsupported RTL style!\n");
449 r.left += 3;
450 do {
451 if (*text == '\t') {
452 if (strCnt) {
453 DrawTextW (hdc, text - strCnt, strCnt, &r, align|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX);
454 strCnt = 0;
456 if (align==DT_RIGHT) {
457 break;
459 align = (align==DT_LEFT ? DT_CENTER : DT_RIGHT);
460 } else {
461 strCnt++;
463 } while(*text++);
465 if (strCnt) DrawTextW (hdc, text - strCnt, -1, &r, align|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX);
466 SetBkMode(hdc, oldbkmode);
471 /***********************************************************************
472 * DrawStatusText [COMCTL32.@]
473 * DrawStatusTextA [COMCTL32.5]
475 * Draws text with borders, like in a status bar.
477 * PARAMS
478 * hdc [I] handle to the window's display context
479 * lprc [I] pointer to a rectangle
480 * text [I] pointer to the text
481 * style [I] drawing style
483 * RETURNS
484 * No return value.
487 void WINAPI DrawStatusTextA (HDC hdc, LPCRECT lprc, LPCSTR text, UINT style)
489 INT len;
490 LPWSTR textW = NULL;
492 if ( text ) {
493 if ( (len = MultiByteToWideChar( CP_ACP, 0, text, -1, NULL, 0 )) ) {
494 if ( (textW = Alloc( len * sizeof(WCHAR) )) )
495 MultiByteToWideChar( CP_ACP, 0, text, -1, textW, len );
498 DrawStatusTextW( hdc, lprc, textW, style );
499 Free( textW );
503 /***********************************************************************
504 * CreateStatusWindow [COMCTL32.@]
505 * CreateStatusWindowA [COMCTL32.6]
507 * Creates a status bar
509 * PARAMS
510 * style [I] window style
511 * text [I] pointer to the window text
512 * parent [I] handle to the parent window
513 * wid [I] control id of the status bar
515 * RETURNS
516 * Success: handle to the status window
517 * Failure: 0
520 HWND WINAPI
521 CreateStatusWindowA (LONG style, LPCSTR text, HWND parent, UINT wid)
523 return CreateWindowA(STATUSCLASSNAMEA, text, style,
524 CW_USEDEFAULT, CW_USEDEFAULT,
525 CW_USEDEFAULT, CW_USEDEFAULT,
526 parent, (HMENU)(DWORD_PTR)wid, 0, 0);
530 /***********************************************************************
531 * CreateStatusWindowW [COMCTL32.@]
533 * Creates a status bar control
535 * PARAMS
536 * style [I] window style
537 * text [I] pointer to the window text
538 * parent [I] handle to the parent window
539 * wid [I] control id of the status bar
541 * RETURNS
542 * Success: handle to the status window
543 * Failure: 0
546 HWND WINAPI
547 CreateStatusWindowW (LONG style, LPCWSTR text, HWND parent, UINT wid)
549 return CreateWindowW(STATUSCLASSNAMEW, text, style,
550 CW_USEDEFAULT, CW_USEDEFAULT,
551 CW_USEDEFAULT, CW_USEDEFAULT,
552 parent, (HMENU)(DWORD_PTR)wid, 0, 0);
556 /***********************************************************************
557 * CreateUpDownControl [COMCTL32.16]
559 * Creates an up-down control
561 * PARAMS
562 * style [I] window styles
563 * x [I] horizontal position of the control
564 * y [I] vertical position of the control
565 * cx [I] with of the control
566 * cy [I] height of the control
567 * parent [I] handle to the parent window
568 * id [I] the control's identifier
569 * inst [I] handle to the application's module instance
570 * buddy [I] handle to the buddy window, can be NULL
571 * maxVal [I] upper limit of the control
572 * minVal [I] lower limit of the control
573 * curVal [I] current value of the control
575 * RETURNS
576 * Success: handle to the updown control
577 * Failure: 0
580 HWND WINAPI
581 CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
582 HWND parent, INT id, HINSTANCE inst,
583 HWND buddy, INT maxVal, INT minVal, INT curVal)
585 HWND hUD =
586 CreateWindowW (UPDOWN_CLASSW, 0, style, x, y, cx, cy,
587 parent, (HMENU)(DWORD_PTR)id, inst, 0);
588 if (hUD) {
589 SendMessageW (hUD, UDM_SETBUDDY, (WPARAM)buddy, 0);
590 SendMessageW (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));
591 SendMessageW (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));
594 return hUD;
598 /***********************************************************************
599 * InitCommonControls [COMCTL32.17]
601 * Registers the common controls.
603 * PARAMS
604 * No parameters.
606 * RETURNS
607 * No return values.
609 * NOTES
610 * This function is just a dummy - all the controls are registered at
611 * the DLL initialization time. See InitCommonContolsEx for details.
614 VOID WINAPI
615 InitCommonControls (void)
620 /***********************************************************************
621 * InitCommonControlsEx [COMCTL32.@]
623 * Registers the common controls.
625 * PARAMS
626 * lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
628 * RETURNS
629 * Success: TRUE
630 * Failure: FALSE
632 * NOTES
633 * Probably all versions of comctl32 initializes the Win95 controls in DllMain
634 * during DLL initialization. Starting from comctl32 v5.82 all the controls
635 * are initialized there. We follow this behaviour and this function is just
636 * a dummy.
638 * Note: when writing programs under Windows, if you don't call any function
639 * from comctl32 the linker may not link this DLL. If InitCommonControlsEx
640 * was the only comctl32 function you were calling and you remove it you may
641 * have a false impression that InitCommonControlsEx actually did something.
644 BOOL WINAPI
645 InitCommonControlsEx (const INITCOMMONCONTROLSEX *lpInitCtrls)
647 if (!lpInitCtrls || lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
648 return FALSE;
650 TRACE("(0x%08x)\n", lpInitCtrls->dwICC);
651 return TRUE;
655 /***********************************************************************
656 * CreateToolbarEx [COMCTL32.@]
658 * Creates a toolbar window.
660 * PARAMS
661 * hwnd
662 * style
663 * wID
664 * nBitmaps
665 * hBMInst
666 * wBMID
667 * lpButtons
668 * iNumButtons
669 * dxButton
670 * dyButton
671 * dxBitmap
672 * dyBitmap
673 * uStructSize
675 * RETURNS
676 * Success: handle to the tool bar control
677 * Failure: 0
680 HWND WINAPI
681 CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
682 HINSTANCE hBMInst, UINT_PTR wBMID, LPCTBBUTTON lpButtons,
683 INT iNumButtons, INT dxButton, INT dyButton,
684 INT dxBitmap, INT dyBitmap, UINT uStructSize)
686 HWND hwndTB;
688 hwndTB =
689 CreateWindowExW(0, TOOLBARCLASSNAMEW, NULL, style|WS_CHILD, 0,0,100,30,
690 hwnd, (HMENU)(DWORD_PTR)wID, COMCTL32_hModule, NULL);
691 if(hwndTB) {
692 TBADDBITMAP tbab;
694 SendMessageW (hwndTB, TB_BUTTONSTRUCTSIZE, uStructSize, 0);
696 /* set bitmap and button size */
697 /*If CreateToolbarEx receives 0, windows sets default values*/
698 if (dxBitmap < 0)
699 dxBitmap = 16;
700 if (dyBitmap < 0)
701 dyBitmap = 16;
702 if (dxBitmap == 0 || dyBitmap == 0)
703 dxBitmap = dyBitmap = 16;
704 SendMessageW(hwndTB, TB_SETBITMAPSIZE, 0, MAKELPARAM(dxBitmap, dyBitmap));
706 if (dxButton < 0)
707 dxButton = dxBitmap;
708 if (dyButton < 0)
709 dyButton = dyBitmap;
710 /* TB_SETBUTTONSIZE -> TB_SETBITMAPSIZE bug introduced for Windows compatibility */
711 if (dxButton != 0 && dyButton != 0)
712 SendMessageW(hwndTB, TB_SETBITMAPSIZE, 0, MAKELPARAM(dxButton, dyButton));
715 /* add bitmaps */
716 if (nBitmaps > 0 || hBMInst == HINST_COMMCTRL)
718 tbab.hInst = hBMInst;
719 tbab.nID = wBMID;
721 SendMessageW (hwndTB, TB_ADDBITMAP, nBitmaps, (LPARAM)&tbab);
723 /* add buttons */
724 if(iNumButtons > 0)
725 SendMessageW (hwndTB, TB_ADDBUTTONSW, iNumButtons, (LPARAM)lpButtons);
728 return hwndTB;
732 /***********************************************************************
733 * CreateMappedBitmap [COMCTL32.8]
735 * Loads a bitmap resource using a colour map.
737 * PARAMS
738 * hInstance [I] Handle to the module containing the bitmap.
739 * idBitmap [I] The bitmap resource ID.
740 * wFlags [I] CMB_MASKED for using bitmap as a mask or 0 for normal.
741 * lpColorMap [I] Colour information needed for the bitmap or NULL (uses system colours).
742 * iNumMaps [I] Number of COLORMAP's pointed to by lpColorMap.
744 * RETURNS
745 * Success: handle to the new bitmap
746 * Failure: 0
749 HBITMAP WINAPI
750 CreateMappedBitmap (HINSTANCE hInstance, INT_PTR idBitmap, UINT wFlags,
751 LPCOLORMAP lpColorMap, INT iNumMaps)
753 HGLOBAL hglb;
754 HRSRC hRsrc;
755 const BITMAPINFOHEADER *lpBitmap;
756 LPBITMAPINFOHEADER lpBitmapInfo;
757 UINT nSize, nColorTableSize, iColor;
758 RGBQUAD *pColorTable;
759 INT i, iMaps, nWidth, nHeight;
760 HDC hdcScreen;
761 HBITMAP hbm;
762 LPCOLORMAP sysColorMap;
763 COLORREF cRef;
764 COLORMAP internalColorMap[4] =
765 {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
767 /* initialize pointer to colortable and default color table */
768 if (lpColorMap) {
769 iMaps = iNumMaps;
770 sysColorMap = lpColorMap;
772 else {
773 internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT);
774 internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW);
775 internalColorMap[2].to = GetSysColor (COLOR_BTNFACE);
776 internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT);
777 iMaps = 4;
778 sysColorMap = internalColorMap;
781 hRsrc = FindResourceW (hInstance, (LPWSTR)idBitmap, (LPWSTR)RT_BITMAP);
782 if (hRsrc == 0)
783 return 0;
784 hglb = LoadResource (hInstance, hRsrc);
785 if (hglb == 0)
786 return 0;
787 lpBitmap = LockResource (hglb);
788 if (lpBitmap == NULL)
789 return 0;
791 if (lpBitmap->biSize >= sizeof(BITMAPINFOHEADER) && lpBitmap->biClrUsed)
792 nColorTableSize = lpBitmap->biClrUsed;
793 else if (lpBitmap->biBitCount <= 8)
794 nColorTableSize = (1 << lpBitmap->biBitCount);
795 else
796 nColorTableSize = 0;
797 nSize = lpBitmap->biSize;
798 if (nSize == sizeof(BITMAPINFOHEADER) && lpBitmap->biCompression == BI_BITFIELDS)
799 nSize += 3 * sizeof(DWORD);
800 nSize += nColorTableSize * sizeof(RGBQUAD);
801 lpBitmapInfo = GlobalAlloc (GMEM_FIXED, nSize);
802 if (lpBitmapInfo == NULL)
803 return 0;
804 RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);
806 pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo) + lpBitmapInfo->biSize);
808 for (iColor = 0; iColor < nColorTableSize; iColor++) {
809 for (i = 0; i < iMaps; i++) {
810 cRef = RGB(pColorTable[iColor].rgbRed,
811 pColorTable[iColor].rgbGreen,
812 pColorTable[iColor].rgbBlue);
813 if ( cRef == sysColorMap[i].from) {
814 #if 0
815 if (wFlags & CBS_MASKED) {
816 if (sysColorMap[i].to != COLOR_BTNTEXT)
817 pColorTable[iColor] = RGB(255, 255, 255);
819 else
820 #endif
821 pColorTable[iColor].rgbBlue = GetBValue(sysColorMap[i].to);
822 pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);
823 pColorTable[iColor].rgbRed = GetRValue(sysColorMap[i].to);
824 break;
828 nWidth = lpBitmapInfo->biWidth;
829 nHeight = lpBitmapInfo->biHeight;
830 hdcScreen = GetDC (NULL);
831 hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
832 if (hbm) {
833 HDC hdcDst = CreateCompatibleDC (hdcScreen);
834 HBITMAP hbmOld = SelectObject (hdcDst, hbm);
835 const BYTE *lpBits = (const BYTE *)lpBitmap + nSize;
836 StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
837 lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
838 SRCCOPY);
839 SelectObject (hdcDst, hbmOld);
840 DeleteDC (hdcDst);
842 ReleaseDC (NULL, hdcScreen);
843 GlobalFree (lpBitmapInfo);
844 FreeResource (hglb);
846 return hbm;
850 /***********************************************************************
851 * CreateToolbar [COMCTL32.7]
853 * Creates a toolbar control.
855 * PARAMS
856 * hwnd
857 * style
858 * wID
859 * nBitmaps
860 * hBMInst
861 * wBMID
862 * lpButtons
863 * iNumButtons
865 * RETURNS
866 * Success: handle to the tool bar control
867 * Failure: 0
869 * NOTES
870 * Do not use this function anymore. Use CreateToolbarEx instead.
873 HWND WINAPI
874 CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
875 HINSTANCE hBMInst, UINT wBMID,
876 LPCTBBUTTON lpButtons,INT iNumButtons)
878 return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
879 hBMInst, wBMID, lpButtons,
880 iNumButtons, 0, 0, 0, 0, CCSIZEOF_STRUCT(TBBUTTON, dwData));
884 /***********************************************************************
885 * DllGetVersion [COMCTL32.@]
887 * Retrieves version information of the 'COMCTL32.DLL'
889 * PARAMS
890 * pdvi [O] pointer to version information structure.
892 * RETURNS
893 * Success: S_OK
894 * Failure: E_INVALIDARG
896 * NOTES
897 * Returns version of a comctl32.dll from IE4.01 SP1.
900 HRESULT WINAPI DllGetVersion (DLLVERSIONINFO *pdvi)
902 if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
903 WARN("wrong DLLVERSIONINFO size from app\n");
904 return E_INVALIDARG;
907 pdvi->dwMajorVersion = COMCTL32_VERSION;
908 pdvi->dwMinorVersion = COMCTL32_VERSION_MINOR;
909 pdvi->dwBuildNumber = 2919;
910 pdvi->dwPlatformID = 6304;
912 TRACE("%u.%u.%u.%u\n",
913 pdvi->dwMajorVersion, pdvi->dwMinorVersion,
914 pdvi->dwBuildNumber, pdvi->dwPlatformID);
916 return S_OK;
919 /***********************************************************************
920 * DllInstall (COMCTL32.@)
922 * Installs the ComCtl32 DLL.
924 * RETURNS
925 * Success: S_OK
926 * Failure: A HRESULT error
928 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
930 TRACE("(%u, %s): stub\n", bInstall, debugstr_w(cmdline));
931 return S_OK;
934 /***********************************************************************
935 * _TrackMouseEvent [COMCTL32.@]
937 * Requests notification of mouse events
939 * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
940 * to the hwnd specified in the ptme structure. After the event message
941 * is posted to the hwnd, the entry in the queue is removed.
943 * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
944 * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
945 * immediately and the TME_LEAVE flag being ignored.
947 * PARAMS
948 * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
950 * RETURNS
951 * Success: non-zero
952 * Failure: zero
954 * IMPLEMENTATION moved to USER32.TrackMouseEvent
958 BOOL WINAPI
959 _TrackMouseEvent (TRACKMOUSEEVENT *ptme)
961 return TrackMouseEvent (ptme);
964 /*************************************************************************
965 * GetMUILanguage [COMCTL32.@]
967 * Returns the user interface language in use by the current process.
969 * RETURNS
970 * Language ID in use by the current process.
972 LANGID WINAPI GetMUILanguage (VOID)
974 return COMCTL32_uiLang;
978 /*************************************************************************
979 * InitMUILanguage [COMCTL32.@]
981 * Sets the user interface language to be used by the current process.
983 * RETURNS
984 * Nothing.
986 VOID WINAPI InitMUILanguage (LANGID uiLang)
988 COMCTL32_uiLang = uiLang;
992 /***********************************************************************
993 * SetWindowSubclass [COMCTL32.410]
995 * Starts a window subclass
997 * PARAMS
998 * hWnd [in] handle to window subclass.
999 * pfnSubclass [in] Pointer to new window procedure.
1000 * uIDSubclass [in] Unique identifier of subclass together with pfnSubclass.
1001 * dwRef [in] Reference data to pass to window procedure.
1003 * RETURNS
1004 * Success: non-zero
1005 * Failure: zero
1007 * BUGS
1008 * If an application manually subclasses a window after subclassing it with
1009 * this API and then with this API again, then none of the previous
1010 * subclasses get called or the original window procedure.
1013 BOOL WINAPI SetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
1014 UINT_PTR uIDSubclass, DWORD_PTR dwRef)
1016 LPSUBCLASS_INFO stack;
1017 LPSUBCLASSPROCS proc;
1019 TRACE ("(%p, %p, %lx, %lx)\n", hWnd, pfnSubclass, uIDSubclass, dwRef);
1021 /* Since the window procedure that we set here has two additional arguments,
1022 * we can't simply set it as the new window procedure of the window. So we
1023 * set our own window procedure and then calculate the other two arguments
1024 * from there. */
1026 /* See if we have been called for this window */
1027 stack = GetPropW (hWnd, COMCTL32_wSubclass);
1028 if (!stack) {
1029 /* allocate stack */
1030 stack = Alloc (sizeof(SUBCLASS_INFO));
1031 if (!stack) {
1032 ERR ("Failed to allocate our Subclassing stack\n");
1033 return FALSE;
1035 SetPropW (hWnd, COMCTL32_wSubclass, stack);
1037 /* set window procedure to our own and save the current one */
1038 if (IsWindowUnicode (hWnd))
1039 stack->origproc = (WNDPROC)SetWindowLongPtrW (hWnd, GWLP_WNDPROC,
1040 (DWORD_PTR)COMCTL32_SubclassProc);
1041 else
1042 stack->origproc = (WNDPROC)SetWindowLongPtrA (hWnd, GWLP_WNDPROC,
1043 (DWORD_PTR)COMCTL32_SubclassProc);
1045 else {
1046 /* Check to see if we have called this function with the same uIDSubClass
1047 * and pfnSubclass */
1048 proc = stack->SubclassProcs;
1049 while (proc) {
1050 if ((proc->id == uIDSubclass) &&
1051 (proc->subproc == pfnSubclass)) {
1052 proc->ref = dwRef;
1053 return TRUE;
1055 proc = proc->next;
1059 proc = Alloc(sizeof(SUBCLASSPROCS));
1060 if (!proc) {
1061 ERR ("Failed to allocate subclass entry in stack\n");
1062 if (IsWindowUnicode (hWnd))
1063 SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1064 else
1065 SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1066 Free (stack);
1067 RemovePropW( hWnd, COMCTL32_wSubclass );
1068 return FALSE;
1071 proc->subproc = pfnSubclass;
1072 proc->ref = dwRef;
1073 proc->id = uIDSubclass;
1074 proc->next = stack->SubclassProcs;
1075 stack->SubclassProcs = proc;
1077 return TRUE;
1081 /***********************************************************************
1082 * GetWindowSubclass [COMCTL32.411]
1084 * Gets the Reference data from a subclass.
1086 * PARAMS
1087 * hWnd [in] Handle to window which were subclassing
1088 * pfnSubclass [in] Pointer to the subclass procedure
1089 * uID [in] Unique identifier of the subclassing procedure
1090 * pdwRef [out] Pointer to the reference data
1092 * RETURNS
1093 * Success: Non-zero
1094 * Failure: 0
1097 BOOL WINAPI GetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
1098 UINT_PTR uID, DWORD_PTR *pdwRef)
1100 const SUBCLASS_INFO *stack;
1101 const SUBCLASSPROCS *proc;
1103 TRACE ("(%p, %p, %lx, %p)\n", hWnd, pfnSubclass, uID, pdwRef);
1105 /* See if we have been called for this window */
1106 stack = GetPropW (hWnd, COMCTL32_wSubclass);
1107 if (!stack)
1108 return FALSE;
1110 proc = stack->SubclassProcs;
1111 while (proc) {
1112 if ((proc->id == uID) &&
1113 (proc->subproc == pfnSubclass)) {
1114 *pdwRef = proc->ref;
1115 return TRUE;
1117 proc = proc->next;
1120 return FALSE;
1124 /***********************************************************************
1125 * RemoveWindowSubclass [COMCTL32.412]
1127 * Removes a window subclass.
1129 * PARAMS
1130 * hWnd [in] Handle to the window were subclassing
1131 * pfnSubclass [in] Pointer to the subclass procedure
1132 * uID [in] Unique identifier of this subclass
1134 * RETURNS
1135 * Success: non-zero
1136 * Failure: zero
1139 BOOL WINAPI RemoveWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR uID)
1141 LPSUBCLASS_INFO stack;
1142 LPSUBCLASSPROCS prevproc = NULL;
1143 LPSUBCLASSPROCS proc;
1144 BOOL ret = FALSE;
1146 TRACE ("(%p, %p, %lx)\n", hWnd, pfnSubclass, uID);
1148 /* Find the Subclass to remove */
1149 stack = GetPropW (hWnd, COMCTL32_wSubclass);
1150 if (!stack)
1151 return FALSE;
1153 proc = stack->SubclassProcs;
1154 while (proc) {
1155 if ((proc->id == uID) &&
1156 (proc->subproc == pfnSubclass)) {
1158 if (!prevproc)
1159 stack->SubclassProcs = proc->next;
1160 else
1161 prevproc->next = proc->next;
1163 if (stack->stackpos == proc)
1164 stack->stackpos = stack->stackpos->next;
1166 Free (proc);
1167 ret = TRUE;
1168 break;
1170 prevproc = proc;
1171 proc = proc->next;
1174 if (!stack->SubclassProcs && !stack->running) {
1175 TRACE("Last Subclass removed, cleaning up\n");
1176 /* clean up our heap and reset the original window procedure */
1177 if (IsWindowUnicode (hWnd))
1178 SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1179 else
1180 SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1181 Free (stack);
1182 RemovePropW( hWnd, COMCTL32_wSubclass );
1185 return ret;
1188 /***********************************************************************
1189 * COMCTL32_SubclassProc (internal)
1191 * Window procedure for all subclassed windows.
1192 * Saves the current subclassing stack position to support nested messages
1194 static LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1196 LPSUBCLASS_INFO stack;
1197 LPSUBCLASSPROCS proc;
1198 LRESULT ret;
1200 TRACE ("(%p, 0x%08x, 0x%08lx, 0x%08lx)\n", hWnd, uMsg, wParam, lParam);
1202 stack = GetPropW (hWnd, COMCTL32_wSubclass);
1203 if (!stack) {
1204 ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
1205 return 0;
1208 /* Save our old stackpos to properly handle nested messages */
1209 proc = stack->stackpos;
1210 stack->stackpos = stack->SubclassProcs;
1211 stack->running++;
1212 ret = DefSubclassProc(hWnd, uMsg, wParam, lParam);
1213 stack->running--;
1214 stack->stackpos = proc;
1216 if (!stack->SubclassProcs && !stack->running) {
1217 TRACE("Last Subclass removed, cleaning up\n");
1218 /* clean up our heap and reset the original window procedure */
1219 if (IsWindowUnicode (hWnd))
1220 SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1221 else
1222 SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1223 Free (stack);
1224 RemovePropW( hWnd, COMCTL32_wSubclass );
1226 return ret;
1229 /***********************************************************************
1230 * DefSubclassProc [COMCTL32.413]
1232 * Calls the next window procedure (i.e. the one before this subclass)
1234 * PARAMS
1235 * hWnd [in] The window that we're subclassing
1236 * uMsg [in] Message
1237 * wParam [in] WPARAM
1238 * lParam [in] LPARAM
1240 * RETURNS
1241 * Success: non-zero
1242 * Failure: zero
1245 LRESULT WINAPI DefSubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1247 LPSUBCLASS_INFO stack;
1248 LRESULT ret;
1250 TRACE ("(%p, 0x%08x, 0x%08lx, 0x%08lx)\n", hWnd, uMsg, wParam, lParam);
1252 /* retrieve our little stack from the Properties */
1253 stack = GetPropW (hWnd, COMCTL32_wSubclass);
1254 if (!stack) {
1255 ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
1256 return 0;
1259 /* If we are at the end of stack then we have to call the original
1260 * window procedure */
1261 if (!stack->stackpos) {
1262 if (IsWindowUnicode (hWnd))
1263 ret = CallWindowProcW (stack->origproc, hWnd, uMsg, wParam, lParam);
1264 else
1265 ret = CallWindowProcA (stack->origproc, hWnd, uMsg, wParam, lParam);
1266 } else {
1267 const SUBCLASSPROCS *proc = stack->stackpos;
1268 stack->stackpos = stack->stackpos->next;
1269 /* call the Subclass procedure from the stack */
1270 ret = proc->subproc (hWnd, uMsg, wParam, lParam,
1271 proc->id, proc->ref);
1274 return ret;
1278 /***********************************************************************
1279 * COMCTL32_CreateToolTip [NOT AN API]
1281 * Creates a tooltip for the control specified in hwnd and does all
1282 * necessary setup and notifications.
1284 * PARAMS
1285 * hwndOwner [I] Handle to the window that will own the tool tip.
1287 * RETURNS
1288 * Success: Handle of tool tip window.
1289 * Failure: NULL
1292 HWND
1293 COMCTL32_CreateToolTip(HWND hwndOwner)
1295 HWND hwndToolTip;
1297 hwndToolTip = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, WS_POPUP,
1298 CW_USEDEFAULT, CW_USEDEFAULT,
1299 CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner,
1300 0, 0, 0);
1302 /* Send NM_TOOLTIPSCREATED notification */
1303 if (hwndToolTip)
1305 NMTOOLTIPSCREATED nmttc;
1306 /* true owner can be different if hwndOwner is a child window */
1307 HWND hwndTrueOwner = GetWindow(hwndToolTip, GW_OWNER);
1308 nmttc.hdr.hwndFrom = hwndTrueOwner;
1309 nmttc.hdr.idFrom = GetWindowLongPtrW(hwndTrueOwner, GWLP_ID);
1310 nmttc.hdr.code = NM_TOOLTIPSCREATED;
1311 nmttc.hwndToolTips = hwndToolTip;
1313 SendMessageW(GetParent(hwndTrueOwner), WM_NOTIFY,
1314 GetWindowLongPtrW(hwndTrueOwner, GWLP_ID), (LPARAM)&nmttc);
1317 return hwndToolTip;
1321 /***********************************************************************
1322 * COMCTL32_RefreshSysColors [NOT AN API]
1324 * Invoked on any control recognizing a WM_SYSCOLORCHANGE message to
1325 * refresh the color values in the color structure
1327 * PARAMS
1328 * none
1330 * RETURNS
1331 * none
1334 VOID
1335 COMCTL32_RefreshSysColors(void)
1337 comctl32_color.clrBtnHighlight = GetSysColor (COLOR_BTNHIGHLIGHT);
1338 comctl32_color.clrBtnShadow = GetSysColor (COLOR_BTNSHADOW);
1339 comctl32_color.clrBtnText = GetSysColor (COLOR_BTNTEXT);
1340 comctl32_color.clrBtnFace = GetSysColor (COLOR_BTNFACE);
1341 comctl32_color.clrHighlight = GetSysColor (COLOR_HIGHLIGHT);
1342 comctl32_color.clrHighlightText = GetSysColor (COLOR_HIGHLIGHTTEXT);
1343 comctl32_color.clrHotTrackingColor = GetSysColor (COLOR_HOTLIGHT);
1344 comctl32_color.clr3dHilight = GetSysColor (COLOR_3DHILIGHT);
1345 comctl32_color.clr3dShadow = GetSysColor (COLOR_3DSHADOW);
1346 comctl32_color.clr3dDkShadow = GetSysColor (COLOR_3DDKSHADOW);
1347 comctl32_color.clr3dFace = GetSysColor (COLOR_3DFACE);
1348 comctl32_color.clrWindow = GetSysColor (COLOR_WINDOW);
1349 comctl32_color.clrWindowText = GetSysColor (COLOR_WINDOWTEXT);
1350 comctl32_color.clrGrayText = GetSysColor (COLOR_GRAYTEXT);
1351 comctl32_color.clrActiveCaption = GetSysColor (COLOR_ACTIVECAPTION);
1352 comctl32_color.clrInfoBk = GetSysColor (COLOR_INFOBK);
1353 comctl32_color.clrInfoText = GetSysColor (COLOR_INFOTEXT);
1356 /***********************************************************************
1357 * COMCTL32_DrawInsertMark [NOT AN API]
1359 * Draws an insertion mark (which looks similar to an 'I').
1361 * PARAMS
1362 * hDC [I] Device context to draw onto.
1363 * lpRect [I] Co-ordinates of insertion mark.
1364 * clrInsertMark [I] Colour of the insertion mark.
1365 * bHorizontal [I] True if insert mark should be drawn horizontally,
1366 * vertical otherwise.
1368 * RETURNS
1369 * none
1371 * NOTES
1372 * Draws up to but not including the bottom co-ordinate when drawing
1373 * vertically or the right co-ordinate when horizontal.
1375 void COMCTL32_DrawInsertMark(HDC hDC, const RECT *lpRect, COLORREF clrInsertMark, BOOL bHorizontal)
1377 HPEN hPen = CreatePen(PS_SOLID, 1, clrInsertMark);
1378 HPEN hOldPen;
1379 static const DWORD adwPolyPoints[] = {4,4,4};
1380 LONG lCentre = (bHorizontal ?
1381 lpRect->top + (lpRect->bottom - lpRect->top)/2 :
1382 lpRect->left + (lpRect->right - lpRect->left)/2);
1383 LONG l1 = (bHorizontal ? lpRect->left : lpRect->top);
1384 LONG l2 = (bHorizontal ? lpRect->right : lpRect->bottom);
1385 const POINT aptInsertMark[] =
1387 /* top (V) or left (H) arrow */
1388 {lCentre , l1 + 2},
1389 {lCentre - 2, l1 },
1390 {lCentre + 3, l1 },
1391 {lCentre + 1, l1 + 2},
1392 /* middle line */
1393 {lCentre , l2 - 2},
1394 {lCentre , l1 - 1},
1395 {lCentre + 1, l1 - 1},
1396 {lCentre + 1, l2 - 2},
1397 /* bottom (V) or right (H) arrow */
1398 {lCentre , l2 - 3},
1399 {lCentre - 2, l2 - 1},
1400 {lCentre + 3, l2 - 1},
1401 {lCentre + 1, l2 - 3},
1403 hOldPen = SelectObject(hDC, hPen);
1404 PolyPolyline(hDC, aptInsertMark, adwPolyPoints, sizeof(adwPolyPoints)/sizeof(adwPolyPoints[0]));
1405 SelectObject(hDC, hOldPen);
1406 DeleteObject(hPen);
1409 /***********************************************************************
1410 * COMCTL32_EnsureBitmapSize [internal]
1412 * If needed, enlarge the bitmap so that the width is at least cxMinWidth and
1413 * the height is at least cyMinHeight. If the bitmap already has these
1414 * dimensions nothing changes.
1416 * PARAMS
1417 * hBitmap [I/O] Bitmap to modify. The handle may change
1418 * cxMinWidth [I] If the width of the bitmap is smaller, then it will
1419 * be enlarged to this value
1420 * cyMinHeight [I] If the height of the bitmap is smaller, then it will
1421 * be enlarged to this value
1422 * cyBackground [I] The color with which the new area will be filled
1424 * RETURNS
1425 * none
1427 void COMCTL32_EnsureBitmapSize(HBITMAP *pBitmap, int cxMinWidth, int cyMinHeight, COLORREF crBackground)
1429 int cxNew, cyNew;
1430 BITMAP bmp;
1431 HBITMAP hNewBitmap;
1432 HBITMAP hNewDCBitmap, hOldDCBitmap;
1433 HBRUSH hNewDCBrush;
1434 HDC hdcNew, hdcOld;
1436 if (!GetObjectW(*pBitmap, sizeof(BITMAP), &bmp))
1437 return;
1438 cxNew = (cxMinWidth > bmp.bmWidth ? cxMinWidth : bmp.bmWidth);
1439 cyNew = (cyMinHeight > bmp.bmHeight ? cyMinHeight : bmp.bmHeight);
1440 if (cxNew == bmp.bmWidth && cyNew == bmp.bmHeight)
1441 return;
1443 hdcNew = CreateCompatibleDC(NULL);
1444 hNewBitmap = CreateBitmap(cxNew, cyNew, bmp.bmPlanes, bmp.bmBitsPixel, NULL);
1445 hNewDCBitmap = SelectObject(hdcNew, hNewBitmap);
1446 hNewDCBrush = SelectObject(hdcNew, CreateSolidBrush(crBackground));
1448 hdcOld = CreateCompatibleDC(NULL);
1449 hOldDCBitmap = SelectObject(hdcOld, *pBitmap);
1451 BitBlt(hdcNew, 0, 0, bmp.bmWidth, bmp.bmHeight, hdcOld, 0, 0, SRCCOPY);
1452 if (bmp.bmWidth < cxMinWidth)
1453 PatBlt(hdcNew, bmp.bmWidth, 0, cxNew, bmp.bmHeight, PATCOPY);
1454 if (bmp.bmHeight < cyMinHeight)
1455 PatBlt(hdcNew, 0, bmp.bmHeight, bmp.bmWidth, cyNew, PATCOPY);
1456 if (bmp.bmWidth < cxMinWidth && bmp.bmHeight < cyMinHeight)
1457 PatBlt(hdcNew, bmp.bmWidth, bmp.bmHeight, cxNew, cyNew, PATCOPY);
1459 SelectObject(hdcNew, hNewDCBitmap);
1460 DeleteObject(SelectObject(hdcNew, hNewDCBrush));
1461 DeleteDC(hdcNew);
1462 SelectObject(hdcOld, hOldDCBitmap);
1463 DeleteDC(hdcOld);
1465 DeleteObject(*pBitmap);
1466 *pBitmap = hNewBitmap;
1467 return;
1470 void COMCTL32_GetFontMetrics(HFONT hFont, TEXTMETRICW *ptm)
1472 HDC hdc = GetDC(NULL);
1473 HFONT hOldFont;
1475 hOldFont = SelectObject(hdc, hFont);
1476 GetTextMetricsW(hdc, ptm);
1477 SelectObject(hdc, hOldFont);
1478 ReleaseDC(NULL, hdc);
1481 #ifndef OCM__BASE /* avoid including olectl.h */
1482 #define OCM__BASE (WM_USER+0x1c00)
1483 #endif
1485 /***********************************************************************
1486 * COMCTL32_IsReflectedMessage [internal]
1488 * Some parents reflect notify messages - for some messages sent by the child,
1489 * they send it back with the message code increased by OCM__BASE (0x2000).
1490 * This allows better subclassing of controls. We don't need to handle such
1491 * messages but we don't want to print ERRs for them, so this helper function
1492 * identifies them.
1494 * Some of the codes are in the CCM_FIRST..CCM_LAST range, but there is no
1495 * collision with defined CCM_ codes.
1497 BOOL COMCTL32_IsReflectedMessage(UINT uMsg)
1499 switch (uMsg)
1501 case OCM__BASE + WM_COMMAND:
1502 case OCM__BASE + WM_CTLCOLORBTN:
1503 case OCM__BASE + WM_CTLCOLOREDIT:
1504 case OCM__BASE + WM_CTLCOLORDLG:
1505 case OCM__BASE + WM_CTLCOLORLISTBOX:
1506 case OCM__BASE + WM_CTLCOLORMSGBOX:
1507 case OCM__BASE + WM_CTLCOLORSCROLLBAR:
1508 case OCM__BASE + WM_CTLCOLORSTATIC:
1509 case OCM__BASE + WM_DRAWITEM:
1510 case OCM__BASE + WM_MEASUREITEM:
1511 case OCM__BASE + WM_DELETEITEM:
1512 case OCM__BASE + WM_VKEYTOITEM:
1513 case OCM__BASE + WM_CHARTOITEM:
1514 case OCM__BASE + WM_COMPAREITEM:
1515 case OCM__BASE + WM_HSCROLL:
1516 case OCM__BASE + WM_VSCROLL:
1517 case OCM__BASE + WM_PARENTNOTIFY:
1518 case OCM__BASE + WM_NOTIFY:
1519 return TRUE;
1520 default:
1521 return FALSE;
1525 /***********************************************************************
1526 * MirrorIcon [COMCTL32.414]
1528 * Mirrors an icon so that it will appear correctly on a mirrored DC.
1530 * PARAMS
1531 * phicon1 [I/O] Icon.
1532 * phicon2 [I/O] Icon.
1534 * RETURNS
1535 * Success: TRUE.
1536 * Failure: FALSE.
1538 BOOL WINAPI MirrorIcon(HICON *phicon1, HICON *phicon2)
1540 FIXME("(%p, %p): stub\n", phicon1, phicon2);
1541 return FALSE;
1544 static inline BOOL IsDelimiter(WCHAR c)
1546 switch(c)
1548 case '/':
1549 case '\\':
1550 case '.':
1551 case ' ':
1552 return TRUE;
1554 return FALSE;
1557 static int CALLBACK PathWordBreakProc(LPCWSTR lpch, int ichCurrent, int cch, int code)
1559 if (code == WB_ISDELIMITER)
1560 return IsDelimiter(lpch[ichCurrent]);
1561 else
1563 int dir = (code == WB_LEFT) ? -1 : 1;
1564 for(; 0 <= ichCurrent && ichCurrent < cch; ichCurrent += dir)
1565 if (IsDelimiter(lpch[ichCurrent])) return ichCurrent;
1567 return ichCurrent;
1570 /***********************************************************************
1571 * SetPathWordBreakProc [COMCTL32.384]
1573 * Sets the word break procedure for an edit control to one that understands
1574 * paths so that the user can jump over directories.
1576 * PARAMS
1577 * hwnd [I] Handle to edit control.
1578 * bSet [I] If this is TRUE then the word break proc is set, otherwise it is removed.
1580 * RETURNS
1581 * Result from EM_SETWORDBREAKPROC message.
1583 LRESULT WINAPI SetPathWordBreakProc(HWND hwnd, BOOL bSet)
1585 return SendMessageW(hwnd, EM_SETWORDBREAKPROC, 0,
1586 (LPARAM)(bSet ? PathWordBreakProc : NULL));
1589 /***********************************************************************
1590 * DrawShadowText [COMCTL32.@]
1592 * Draw text with shadow.
1594 int WINAPI DrawShadowText(HDC hdc, LPCWSTR pszText, UINT cch, RECT *rect, DWORD dwFlags,
1595 COLORREF crText, COLORREF crShadow, int ixOffset, int iyOffset)
1597 FIXME("(%p, %s, %d, %p, %d, 0x%08x, 0x%08x, %d, %d): stub\n", hdc, debugstr_w(pszText), cch, rect, dwFlags,
1598 crText, crShadow, ixOffset, iyOffset);
1599 return DrawTextW(hdc, pszText, cch, rect, DT_LEFT);
1602 /***********************************************************************
1603 * TaskDialogIndirect [COMCTL32.@]
1605 HRESULT WINAPI TaskDialogIndirect(const TASKDIALOGCONFIG *pTaskConfig, int *pnButton,
1606 int *pnRadioButton, BOOL *pfVerificationFlagChecked)
1608 UINT uType = 0;
1609 INT ret;
1610 FIXME("%p, %p, %p, %p\n", pTaskConfig, pnButton, pnRadioButton, pfVerificationFlagChecked);
1612 if (pTaskConfig->dwCommonButtons & TDCBF_YES_BUTTON &&
1613 pTaskConfig->dwCommonButtons & TDCBF_NO_BUTTON &&
1614 pTaskConfig->dwCommonButtons & TDCBF_CANCEL_BUTTON)
1615 uType |= MB_YESNOCANCEL;
1616 else
1617 if (pTaskConfig->dwCommonButtons & TDCBF_YES_BUTTON &&
1618 pTaskConfig->dwCommonButtons & TDCBF_NO_BUTTON)
1619 uType |= MB_YESNO;
1620 else
1621 if (pTaskConfig->dwCommonButtons & TDCBF_RETRY_BUTTON &&
1622 pTaskConfig->dwCommonButtons & TDCBF_CANCEL_BUTTON)
1623 uType |= MB_RETRYCANCEL;
1624 else
1625 if (pTaskConfig->dwCommonButtons & TDCBF_OK_BUTTON &&
1626 pTaskConfig->dwCommonButtons & TDCBF_CANCEL_BUTTON)
1627 uType |= MB_OKCANCEL;
1628 else
1629 if (pTaskConfig->dwCommonButtons & TDCBF_OK_BUTTON)
1630 uType |= MB_OK;
1631 ret = MessageBoxW(pTaskConfig->hwndParent, pTaskConfig->pszMainInstruction,
1632 pTaskConfig->pszWindowTitle, uType);
1633 FIXME("dwCommonButtons=%x uType=%x ret=%x\n", pTaskConfig->dwCommonButtons, uType, ret);
1635 if (pnButton) *pnButton = ret;
1636 if (pnRadioButton) *pnRadioButton = pTaskConfig->nDefaultButton;
1637 if (pfVerificationFlagChecked) *pfVerificationFlagChecked = TRUE;
1638 return S_OK;