kernel32: Use the correct access rights when opening named pipes.
[wine/hacks.git] / dlls / comctl32 / commctrl.c
bloba5796f39127ff7a9319484eef3cd999d57974c46
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);
74 LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
76 LPWSTR COMCTL32_wSubclass = NULL;
77 HMODULE COMCTL32_hModule = 0;
78 LANGID COMCTL32_uiLang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
79 HBRUSH COMCTL32_hPattern55AABrush = NULL;
80 COMCTL32_SysColor comctl32_color;
82 static HBITMAP COMCTL32_hPattern55AABitmap = NULL;
84 static const WORD wPattern55AA[] =
86 0x5555, 0xaaaa, 0x5555, 0xaaaa,
87 0x5555, 0xaaaa, 0x5555, 0xaaaa
90 static const WCHAR strCC32SubclassInfo[] = {
91 'C','C','3','2','S','u','b','c','l','a','s','s','I','n','f','o',0
94 /***********************************************************************
95 * DllMain [Internal]
97 * Initializes the internal 'COMCTL32.DLL'.
99 * PARAMS
100 * hinstDLL [I] handle to the 'dlls' instance
101 * fdwReason [I]
102 * lpvReserved [I] reserverd, must be NULL
104 * RETURNS
105 * Success: TRUE
106 * Failure: FALSE
109 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
111 TRACE("%p,%x,%p\n", hinstDLL, fdwReason, lpvReserved);
113 switch (fdwReason) {
114 case DLL_PROCESS_ATTACH:
115 DisableThreadLibraryCalls(hinstDLL);
117 COMCTL32_hModule = (HMODULE)hinstDLL;
119 /* add global subclassing atom (used by 'tooltip' and 'updown') */
120 COMCTL32_wSubclass = (LPWSTR)(DWORD_PTR)GlobalAddAtomW (strCC32SubclassInfo);
121 TRACE("Subclassing atom added: %p\n", COMCTL32_wSubclass);
123 /* create local pattern brush */
124 COMCTL32_hPattern55AABitmap = CreateBitmap (8, 8, 1, 1, wPattern55AA);
125 COMCTL32_hPattern55AABrush = CreatePatternBrush (COMCTL32_hPattern55AABitmap);
127 /* Get all the colors at DLL load */
128 COMCTL32_RefreshSysColors();
130 /* like comctl32 5.82+ register all the common control classes */
131 ANIMATE_Register ();
132 COMBOEX_Register ();
133 DATETIME_Register ();
134 FLATSB_Register ();
135 HEADER_Register ();
136 HOTKEY_Register ();
137 IPADDRESS_Register ();
138 LISTVIEW_Register ();
139 MONTHCAL_Register ();
140 NATIVEFONT_Register ();
141 PAGER_Register ();
142 PROGRESS_Register ();
143 REBAR_Register ();
144 STATUS_Register ();
145 SYSLINK_Register ();
146 TAB_Register ();
147 TOOLBAR_Register ();
148 TOOLTIPS_Register ();
149 TRACKBAR_Register ();
150 TREEVIEW_Register ();
151 UPDOWN_Register ();
153 /* subclass user32 controls */
154 THEMING_Initialize ();
155 break;
157 case DLL_PROCESS_DETACH:
158 /* clean up subclassing */
159 THEMING_Uninitialize();
161 /* unregister all common control classes */
162 ANIMATE_Unregister ();
163 COMBOEX_Unregister ();
164 DATETIME_Unregister ();
165 FLATSB_Unregister ();
166 HEADER_Unregister ();
167 HOTKEY_Unregister ();
168 IPADDRESS_Unregister ();
169 LISTVIEW_Unregister ();
170 MONTHCAL_Unregister ();
171 NATIVEFONT_Unregister ();
172 PAGER_Unregister ();
173 PROGRESS_Unregister ();
174 REBAR_Unregister ();
175 STATUS_Unregister ();
176 SYSLINK_Unregister ();
177 TAB_Unregister ();
178 TOOLBAR_Unregister ();
179 TOOLTIPS_Unregister ();
180 TRACKBAR_Unregister ();
181 TREEVIEW_Unregister ();
182 UPDOWN_Unregister ();
184 /* delete local pattern brush */
185 DeleteObject (COMCTL32_hPattern55AABrush);
186 COMCTL32_hPattern55AABrush = NULL;
187 DeleteObject (COMCTL32_hPattern55AABitmap);
188 COMCTL32_hPattern55AABitmap = NULL;
190 /* delete global subclassing atom */
191 GlobalDeleteAtom (LOWORD(COMCTL32_wSubclass));
192 TRACE("Subclassing atom deleted: %p\n", COMCTL32_wSubclass);
193 COMCTL32_wSubclass = NULL;
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%X 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 = (UINT)*(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%X 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, %x, %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 if (*text == L'\t') {
446 text++;
447 align = DT_CENTER;
448 if (*text == L'\t') {
449 text++;
450 align = DT_RIGHT;
453 r.left += 3;
454 if (style & SBT_RTLREADING)
455 FIXME("Unsupported RTL style!\n");
456 DrawTextW (hdc, text, -1, &r, align|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX);
457 SetBkMode(hdc, oldbkmode);
462 /***********************************************************************
463 * DrawStatusText [COMCTL32.@]
464 * DrawStatusTextA [COMCTL32.5]
466 * Draws text with borders, like in a status bar.
468 * PARAMS
469 * hdc [I] handle to the window's display context
470 * lprc [I] pointer to a rectangle
471 * text [I] pointer to the text
472 * style [I] drawing style
474 * RETURNS
475 * No return value.
478 void WINAPI DrawStatusTextA (HDC hdc, LPCRECT lprc, LPCSTR text, UINT style)
480 INT len;
481 LPWSTR textW = NULL;
483 if ( text ) {
484 if ( (len = MultiByteToWideChar( CP_ACP, 0, text, -1, NULL, 0 )) ) {
485 if ( (textW = Alloc( len * sizeof(WCHAR) )) )
486 MultiByteToWideChar( CP_ACP, 0, text, -1, textW, len );
489 DrawStatusTextW( hdc, lprc, textW, style );
490 Free( textW );
494 /***********************************************************************
495 * CreateStatusWindow [COMCTL32.@]
496 * CreateStatusWindowA [COMCTL32.6]
498 * Creates a status bar
500 * PARAMS
501 * style [I] window style
502 * text [I] pointer to the window text
503 * parent [I] handle to the parent window
504 * wid [I] control id of the status bar
506 * RETURNS
507 * Success: handle to the status window
508 * Failure: 0
511 HWND WINAPI
512 CreateStatusWindowA (LONG style, LPCSTR text, HWND parent, UINT wid)
514 return CreateWindowA(STATUSCLASSNAMEA, text, style,
515 CW_USEDEFAULT, CW_USEDEFAULT,
516 CW_USEDEFAULT, CW_USEDEFAULT,
517 parent, (HMENU)(DWORD_PTR)wid, 0, 0);
521 /***********************************************************************
522 * CreateStatusWindowW [COMCTL32.@]
524 * Creates a status bar control
526 * PARAMS
527 * style [I] window style
528 * text [I] pointer to the window text
529 * parent [I] handle to the parent window
530 * wid [I] control id of the status bar
532 * RETURNS
533 * Success: handle to the status window
534 * Failure: 0
537 HWND WINAPI
538 CreateStatusWindowW (LONG style, LPCWSTR text, HWND parent, UINT wid)
540 return CreateWindowW(STATUSCLASSNAMEW, text, style,
541 CW_USEDEFAULT, CW_USEDEFAULT,
542 CW_USEDEFAULT, CW_USEDEFAULT,
543 parent, (HMENU)(DWORD_PTR)wid, 0, 0);
547 /***********************************************************************
548 * CreateUpDownControl [COMCTL32.16]
550 * Creates an up-down control
552 * PARAMS
553 * style [I] window styles
554 * x [I] horizontal position of the control
555 * y [I] vertical position of the control
556 * cx [I] with of the control
557 * cy [I] height of the control
558 * parent [I] handle to the parent window
559 * id [I] the control's identifier
560 * inst [I] handle to the application's module instance
561 * buddy [I] handle to the buddy window, can be NULL
562 * maxVal [I] upper limit of the control
563 * minVal [I] lower limit of the control
564 * curVal [I] current value of the control
566 * RETURNS
567 * Success: handle to the updown control
568 * Failure: 0
571 HWND WINAPI
572 CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
573 HWND parent, INT id, HINSTANCE inst,
574 HWND buddy, INT maxVal, INT minVal, INT curVal)
576 HWND hUD =
577 CreateWindowW (UPDOWN_CLASSW, 0, style, x, y, cx, cy,
578 parent, (HMENU)(DWORD_PTR)id, inst, 0);
579 if (hUD) {
580 SendMessageW (hUD, UDM_SETBUDDY, (WPARAM)buddy, 0);
581 SendMessageW (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));
582 SendMessageW (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));
585 return hUD;
589 /***********************************************************************
590 * InitCommonControls [COMCTL32.17]
592 * Registers the common controls.
594 * PARAMS
595 * No parameters.
597 * RETURNS
598 * No return values.
600 * NOTES
601 * This function is just a dummy - all the controls are registered at
602 * the DLL's initialization. See InitCommonContolsEx for details.
605 VOID WINAPI
606 InitCommonControls (void)
611 /***********************************************************************
612 * InitCommonControlsEx [COMCTL32.@]
614 * Registers the common controls.
616 * PARAMS
617 * lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
619 * RETURNS
620 * Success: TRUE
621 * Failure: FALSE
623 * NOTES
624 * Probaly all versions of comctl32 initializes the Win95 controls in DllMain
625 * during DLL initializaiton. Starting from comctl32 v5.82 all the controls
626 * are initialized there. We follow this behaviour and this function is just
627 * a dummy.
629 * Note: when writing programs under Windows, if you don't call any function
630 * from comctl32 the linker may not link this DLL. If InitCommonControlsEx
631 * was the only comctl32 function you were calling and you remove it you may
632 * have a false impression that InitCommonControlsEx actually did something.
635 BOOL WINAPI
636 InitCommonControlsEx (const INITCOMMONCONTROLSEX *lpInitCtrls)
638 if (!lpInitCtrls || lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
639 return FALSE;
641 TRACE("(0x%08x)\n", lpInitCtrls->dwICC);
642 return TRUE;
646 /***********************************************************************
647 * CreateToolbarEx [COMCTL32.@]
649 * Creates a toolbar window.
651 * PARAMS
652 * hwnd
653 * style
654 * wID
655 * nBitmaps
656 * hBMInst
657 * wBMID
658 * lpButtons
659 * iNumButtons
660 * dxButton
661 * dyButton
662 * dxBitmap
663 * dyBitmap
664 * uStructSize
666 * RETURNS
667 * Success: handle to the tool bar control
668 * Failure: 0
671 HWND WINAPI
672 CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
673 HINSTANCE hBMInst, UINT wBMID, LPCTBBUTTON lpButtons,
674 INT iNumButtons, INT dxButton, INT dyButton,
675 INT dxBitmap, INT dyBitmap, UINT uStructSize)
677 HWND hwndTB;
679 hwndTB =
680 CreateWindowExW(0, TOOLBARCLASSNAMEW, NULL, style|WS_CHILD, 0,0,100,30,
681 hwnd, (HMENU)(DWORD_PTR)wID, COMCTL32_hModule, NULL);
682 if(hwndTB) {
683 TBADDBITMAP tbab;
685 SendMessageW (hwndTB, TB_BUTTONSTRUCTSIZE, (WPARAM)uStructSize, 0);
687 /* set bitmap and button size */
688 /*If CreateToolbarEx receives 0, windows sets default values*/
689 if (dxBitmap <= 0)
690 dxBitmap = 16;
691 if (dyBitmap <= 0)
692 dyBitmap = 15;
693 SendMessageW (hwndTB, TB_SETBITMAPSIZE, 0,
694 MAKELPARAM((WORD)dxBitmap, (WORD)dyBitmap));
696 if (dxButton < 0)
697 dxButton = dxBitmap;
698 if (dyButton < 0)
699 dyButton = dyBitmap;
700 /* TB_SETBUTTONSIZE -> TB_SETBITMAPSIZE bug introduced for Windows compatibility */
701 if (dxButton != 0 && dyButton != 0)
702 SendMessageW(hwndTB, TB_SETBITMAPSIZE, 0, MAKELPARAM(dxButton, dyButton));
705 /* add bitmaps */
706 if (nBitmaps > 0)
708 tbab.hInst = hBMInst;
709 tbab.nID = wBMID;
711 SendMessageW (hwndTB, TB_ADDBITMAP, (WPARAM)nBitmaps, (LPARAM)&tbab);
713 /* add buttons */
714 if(iNumButtons > 0)
715 SendMessageW (hwndTB, TB_ADDBUTTONSW,
716 (WPARAM)iNumButtons, (LPARAM)lpButtons);
719 return hwndTB;
723 /***********************************************************************
724 * CreateMappedBitmap [COMCTL32.8]
726 * Loads a bitmap resource using a colour map.
728 * PARAMS
729 * hInstance [I] Handle to the module containing the bitmap.
730 * idBitmap [I] The bitmap resource ID.
731 * wFlags [I] CMB_MASKED for using bitmap as a mask or 0 for normal.
732 * lpColorMap [I] Colour information needed for the bitmap or NULL (uses system colours).
733 * iNumMaps [I] Number of COLORMAP's pointed to by lpColorMap.
735 * RETURNS
736 * Success: handle to the new bitmap
737 * Failure: 0
740 HBITMAP WINAPI
741 CreateMappedBitmap (HINSTANCE hInstance, INT_PTR idBitmap, UINT wFlags,
742 LPCOLORMAP lpColorMap, INT iNumMaps)
744 HGLOBAL hglb;
745 HRSRC hRsrc;
746 const BITMAPINFOHEADER *lpBitmap;
747 LPBITMAPINFOHEADER lpBitmapInfo;
748 UINT nSize, nColorTableSize, iColor;
749 RGBQUAD *pColorTable;
750 INT i, iMaps, nWidth, nHeight;
751 HDC hdcScreen;
752 HBITMAP hbm;
753 LPCOLORMAP sysColorMap;
754 COLORREF cRef;
755 COLORMAP internalColorMap[4] =
756 {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
758 /* initialize pointer to colortable and default color table */
759 if (lpColorMap) {
760 iMaps = iNumMaps;
761 sysColorMap = lpColorMap;
763 else {
764 internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT);
765 internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW);
766 internalColorMap[2].to = GetSysColor (COLOR_BTNFACE);
767 internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT);
768 iMaps = 4;
769 sysColorMap = (LPCOLORMAP)internalColorMap;
772 hRsrc = FindResourceW (hInstance, (LPWSTR)idBitmap, (LPWSTR)RT_BITMAP);
773 if (hRsrc == 0)
774 return 0;
775 hglb = LoadResource (hInstance, hRsrc);
776 if (hglb == 0)
777 return 0;
778 lpBitmap = (LPBITMAPINFOHEADER)LockResource (hglb);
779 if (lpBitmap == NULL)
780 return 0;
782 if (lpBitmap->biSize >= sizeof(BITMAPINFOHEADER) && lpBitmap->biClrUsed)
783 nColorTableSize = lpBitmap->biClrUsed;
784 else if (lpBitmap->biBitCount <= 8)
785 nColorTableSize = (1 << lpBitmap->biBitCount);
786 else
787 nColorTableSize = 0;
788 nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
789 lpBitmapInfo = (LPBITMAPINFOHEADER)GlobalAlloc (GMEM_FIXED, nSize);
790 if (lpBitmapInfo == NULL)
791 return 0;
792 RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);
794 pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo)+(UINT)lpBitmapInfo->biSize);
796 for (iColor = 0; iColor < nColorTableSize; iColor++) {
797 for (i = 0; i < iMaps; i++) {
798 cRef = RGB(pColorTable[iColor].rgbRed,
799 pColorTable[iColor].rgbGreen,
800 pColorTable[iColor].rgbBlue);
801 if ( cRef == sysColorMap[i].from) {
802 #if 0
803 if (wFlags & CBS_MASKED) {
804 if (sysColorMap[i].to != COLOR_BTNTEXT)
805 pColorTable[iColor] = RGB(255, 255, 255);
807 else
808 #endif
809 pColorTable[iColor].rgbBlue = GetBValue(sysColorMap[i].to);
810 pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);
811 pColorTable[iColor].rgbRed = GetRValue(sysColorMap[i].to);
812 break;
816 nWidth = (INT)lpBitmapInfo->biWidth;
817 nHeight = (INT)lpBitmapInfo->biHeight;
818 hdcScreen = GetDC (NULL);
819 hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
820 if (hbm) {
821 HDC hdcDst = CreateCompatibleDC (hdcScreen);
822 HBITMAP hbmOld = SelectObject (hdcDst, hbm);
823 const BYTE *lpBits = (const BYTE *)(lpBitmap + 1);
824 lpBits += nColorTableSize * sizeof(RGBQUAD);
825 StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
826 lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
827 SRCCOPY);
828 SelectObject (hdcDst, hbmOld);
829 DeleteDC (hdcDst);
831 ReleaseDC (NULL, hdcScreen);
832 GlobalFree ((HGLOBAL)lpBitmapInfo);
833 FreeResource (hglb);
835 return hbm;
839 /***********************************************************************
840 * CreateToolbar [COMCTL32.7]
842 * Creates a toolbar control.
844 * PARAMS
845 * hwnd
846 * style
847 * wID
848 * nBitmaps
849 * hBMInst
850 * wBMID
851 * lpButtons
852 * iNumButtons
854 * RETURNS
855 * Success: handle to the tool bar control
856 * Failure: 0
858 * NOTES
859 * Do not use this functions anymore. Use CreateToolbarEx instead.
862 HWND WINAPI
863 CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
864 HINSTANCE hBMInst, UINT wBMID,
865 LPCTBBUTTON lpButtons,INT iNumButtons)
867 return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
868 hBMInst, wBMID, lpButtons,
869 iNumButtons, 0, 0, 0, 0, CCSIZEOF_STRUCT(TBBUTTON, dwData));
873 /***********************************************************************
874 * DllGetVersion [COMCTL32.@]
876 * Retrieves version information of the 'COMCTL32.DLL'
878 * PARAMS
879 * pdvi [O] pointer to version information structure.
881 * RETURNS
882 * Success: S_OK
883 * Failure: E_INVALIDARG
885 * NOTES
886 * Returns version of a comctl32.dll from IE4.01 SP1.
889 HRESULT WINAPI DllGetVersion (DLLVERSIONINFO *pdvi)
891 if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
892 WARN("wrong DLLVERSIONINFO size from app\n");
893 return E_INVALIDARG;
896 pdvi->dwMajorVersion = COMCTL32_VERSION;
897 pdvi->dwMinorVersion = COMCTL32_VERSION_MINOR;
898 pdvi->dwBuildNumber = 2919;
899 pdvi->dwPlatformID = 6304;
901 TRACE("%u.%u.%u.%u\n",
902 pdvi->dwMajorVersion, pdvi->dwMinorVersion,
903 pdvi->dwBuildNumber, pdvi->dwPlatformID);
905 return S_OK;
908 /***********************************************************************
909 * DllInstall (COMCTL32.@)
911 * Installs the ComCtl32 DLL.
913 * RETURNS
914 * Success: S_OK
915 * Failure: A HRESULT error
917 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
919 FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
920 debugstr_w(cmdline));
922 return S_OK;
925 /***********************************************************************
926 * _TrackMouseEvent [COMCTL32.@]
928 * Requests notification of mouse events
930 * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
931 * to the hwnd specified in the ptme structure. After the event message
932 * is posted to the hwnd, the entry in the queue is removed.
934 * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
935 * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
936 * immediately and the TME_LEAVE flag being ignored.
938 * PARAMS
939 * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
941 * RETURNS
942 * Success: non-zero
943 * Failure: zero
945 * IMPLEMENTATION moved to USER32.TrackMouseEvent
949 BOOL WINAPI
950 _TrackMouseEvent (TRACKMOUSEEVENT *ptme)
952 return TrackMouseEvent (ptme);
955 /*************************************************************************
956 * GetMUILanguage [COMCTL32.@]
958 * Returns the user interface language in use by the current process.
960 * RETURNS
961 * Language ID in use by the current process.
963 LANGID WINAPI GetMUILanguage (VOID)
965 return COMCTL32_uiLang;
969 /*************************************************************************
970 * InitMUILanguage [COMCTL32.@]
972 * Sets the user interface language to be used by the current process.
974 * RETURNS
975 * Nothing.
977 VOID WINAPI InitMUILanguage (LANGID uiLang)
979 COMCTL32_uiLang = uiLang;
983 /***********************************************************************
984 * SetWindowSubclass [COMCTL32.410]
986 * Starts a window subclass
988 * PARAMS
989 * hWnd [in] handle to window subclass.
990 * pfnSubclass [in] Pointer to new window procedure.
991 * uIDSubclass [in] Unique identifier of sublass together with pfnSubclass.
992 * dwRef [in] Reference data to pass to window procedure.
994 * RETURNS
995 * Success: non-zero
996 * Failure: zero
998 * BUGS
999 * If an application manually subclasses a window after subclassing it with
1000 * this API and then with this API again, then none of the previous
1001 * subclasses get called or the origional window procedure.
1004 BOOL WINAPI SetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
1005 UINT_PTR uIDSubclass, DWORD_PTR dwRef)
1007 LPSUBCLASS_INFO stack;
1008 LPSUBCLASSPROCS proc;
1010 TRACE ("(%p, %p, %x, %lx)\n", hWnd, pfnSubclass, uIDSubclass, dwRef);
1012 /* Since the window procedure that we set here has two additional arguments,
1013 * we can't simply set it as the new window procedure of the window. So we
1014 * set our own window procedure and then calculate the other two arguments
1015 * from there. */
1017 /* See if we have been called for this window */
1018 stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
1019 if (!stack) {
1020 /* allocate stack */
1021 stack = Alloc (sizeof(SUBCLASS_INFO));
1022 if (!stack) {
1023 ERR ("Failed to allocate our Subclassing stack\n");
1024 return FALSE;
1026 SetPropW (hWnd, COMCTL32_wSubclass, (HANDLE)stack);
1028 /* set window procedure to our own and save the current one */
1029 if (IsWindowUnicode (hWnd))
1030 stack->origproc = (WNDPROC)SetWindowLongPtrW (hWnd, GWLP_WNDPROC,
1031 (DWORD_PTR)COMCTL32_SubclassProc);
1032 else
1033 stack->origproc = (WNDPROC)SetWindowLongPtrA (hWnd, GWLP_WNDPROC,
1034 (DWORD_PTR)COMCTL32_SubclassProc);
1036 else {
1037 /* Check to see if we have called this function with the same uIDSubClass
1038 * and pfnSubclass */
1039 proc = stack->SubclassProcs;
1040 while (proc) {
1041 if ((proc->id == uIDSubclass) &&
1042 (proc->subproc == pfnSubclass)) {
1043 proc->ref = dwRef;
1044 return TRUE;
1046 proc = proc->next;
1050 proc = Alloc(sizeof(SUBCLASSPROCS));
1051 if (!proc) {
1052 ERR ("Failed to allocate subclass entry in stack\n");
1053 if (IsWindowUnicode (hWnd))
1054 SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1055 else
1056 SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1057 Free (stack);
1058 RemovePropW( hWnd, COMCTL32_wSubclass );
1059 return FALSE;
1062 proc->subproc = pfnSubclass;
1063 proc->ref = dwRef;
1064 proc->id = uIDSubclass;
1065 proc->next = stack->SubclassProcs;
1066 stack->SubclassProcs = proc;
1068 return TRUE;
1072 /***********************************************************************
1073 * GetWindowSubclass [COMCTL32.411]
1075 * Gets the Reference data from a subclass.
1077 * PARAMS
1078 * hWnd [in] Handle to window which were subclassing
1079 * pfnSubclass [in] Pointer to the subclass procedure
1080 * uID [in] Unique indentifier of the subclassing procedure
1081 * pdwRef [out] Pointer to the reference data
1083 * RETURNS
1084 * Success: Non-zero
1085 * Failure: 0
1088 BOOL WINAPI GetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
1089 UINT_PTR uID, DWORD_PTR *pdwRef)
1091 const SUBCLASS_INFO *stack;
1092 const SUBCLASSPROCS *proc;
1094 TRACE ("(%p, %p, %x, %p)\n", hWnd, pfnSubclass, uID, pdwRef);
1096 /* See if we have been called for this window */
1097 stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
1098 if (!stack)
1099 return FALSE;
1101 proc = stack->SubclassProcs;
1102 while (proc) {
1103 if ((proc->id == uID) &&
1104 (proc->subproc == pfnSubclass)) {
1105 *pdwRef = proc->ref;
1106 return TRUE;
1108 proc = proc->next;
1111 return FALSE;
1115 /***********************************************************************
1116 * RemoveWindowSubclass [COMCTL32.412]
1118 * Removes a window subclass.
1120 * PARAMS
1121 * hWnd [in] Handle to the window were subclassing
1122 * pfnSubclass [in] Pointer to the subclass procedure
1123 * uID [in] Unique identifier of this subclass
1125 * RETURNS
1126 * Success: non-zero
1127 * Failure: zero
1130 BOOL WINAPI RemoveWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR uID)
1132 LPSUBCLASS_INFO stack;
1133 LPSUBCLASSPROCS prevproc = NULL;
1134 LPSUBCLASSPROCS proc;
1135 BOOL ret = FALSE;
1137 TRACE ("(%p, %p, %x)\n", hWnd, pfnSubclass, uID);
1139 /* Find the Subclass to remove */
1140 stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
1141 if (!stack)
1142 return FALSE;
1144 proc = stack->SubclassProcs;
1145 while (proc) {
1146 if ((proc->id == uID) &&
1147 (proc->subproc == pfnSubclass)) {
1149 if (!prevproc)
1150 stack->SubclassProcs = proc->next;
1151 else
1152 prevproc->next = proc->next;
1154 if (stack->stackpos == proc)
1155 stack->stackpos = stack->stackpos->next;
1157 Free (proc);
1158 ret = TRUE;
1159 break;
1161 prevproc = proc;
1162 proc = proc->next;
1165 if (!stack->SubclassProcs && !stack->running) {
1166 TRACE("Last Subclass removed, cleaning up\n");
1167 /* clean up our heap and reset the origional window procedure */
1168 if (IsWindowUnicode (hWnd))
1169 SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1170 else
1171 SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1172 Free (stack);
1173 RemovePropW( hWnd, COMCTL32_wSubclass );
1176 return ret;
1179 /***********************************************************************
1180 * COMCTL32_SubclassProc (internal)
1182 * Window procedure for all subclassed windows.
1183 * Saves the current subclassing stack position to support nested messages
1185 LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1187 LPSUBCLASS_INFO stack;
1188 LPSUBCLASSPROCS proc;
1189 LRESULT ret;
1191 TRACE ("(%p, 0x%08x, 0x%08x, 0x%08lx)\n", hWnd, uMsg, wParam, lParam);
1193 stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
1194 if (!stack) {
1195 ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
1196 return 0;
1199 /* Save our old stackpos to properly handle nested messages */
1200 proc = stack->stackpos;
1201 stack->stackpos = stack->SubclassProcs;
1202 stack->running++;
1203 ret = DefSubclassProc(hWnd, uMsg, wParam, lParam);
1204 stack->running--;
1205 stack->stackpos = proc;
1207 if (!stack->SubclassProcs && !stack->running) {
1208 TRACE("Last Subclass removed, cleaning up\n");
1209 /* clean up our heap and reset the origional window procedure */
1210 if (IsWindowUnicode (hWnd))
1211 SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1212 else
1213 SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1214 Free (stack);
1215 RemovePropW( hWnd, COMCTL32_wSubclass );
1217 return ret;
1220 /***********************************************************************
1221 * DefSubclassProc [COMCTL32.413]
1223 * Calls the next window procedure (ie. the one before this subclass)
1225 * PARAMS
1226 * hWnd [in] The window that we're subclassing
1227 * uMsg [in] Message
1228 * wParam [in] WPARAM
1229 * lParam [in] LPARAM
1231 * RETURNS
1232 * Success: non-zero
1233 * Failure: zero
1236 LRESULT WINAPI DefSubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1238 LPSUBCLASS_INFO stack;
1239 LRESULT ret;
1241 TRACE ("(%p, 0x%08x, 0x%08x, 0x%08lx)\n", hWnd, uMsg, wParam, lParam);
1243 /* retrieve our little stack from the Properties */
1244 stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
1245 if (!stack) {
1246 ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
1247 return 0;
1250 /* If we are at the end of stack then we have to call the original
1251 * window procedure */
1252 if (!stack->stackpos) {
1253 if (IsWindowUnicode (hWnd))
1254 ret = CallWindowProcW (stack->origproc, hWnd, uMsg, wParam, lParam);
1255 else
1256 ret = CallWindowProcA (stack->origproc, hWnd, uMsg, wParam, lParam);
1257 } else {
1258 const SUBCLASSPROCS *proc = stack->stackpos;
1259 stack->stackpos = stack->stackpos->next;
1260 /* call the Subclass procedure from the stack */
1261 ret = proc->subproc (hWnd, uMsg, wParam, lParam,
1262 proc->id, proc->ref);
1265 return ret;
1269 /***********************************************************************
1270 * COMCTL32_CreateToolTip [NOT AN API]
1272 * Creates a tooltip for the control specified in hwnd and does all
1273 * necessary setup and notifications.
1275 * PARAMS
1276 * hwndOwner [I] Handle to the window that will own the tool tip.
1278 * RETURNS
1279 * Success: Handle of tool tip window.
1280 * Failure: NULL
1283 HWND
1284 COMCTL32_CreateToolTip(HWND hwndOwner)
1286 HWND hwndToolTip;
1288 hwndToolTip = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, WS_POPUP,
1289 CW_USEDEFAULT, CW_USEDEFAULT,
1290 CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner,
1291 0, 0, 0);
1293 /* Send NM_TOOLTIPSCREATED notification */
1294 if (hwndToolTip)
1296 NMTOOLTIPSCREATED nmttc;
1297 /* true owner can be different if hwndOwner is a child window */
1298 HWND hwndTrueOwner = GetWindow(hwndToolTip, GW_OWNER);
1299 nmttc.hdr.hwndFrom = hwndTrueOwner;
1300 nmttc.hdr.idFrom = GetWindowLongPtrW(hwndTrueOwner, GWLP_ID);
1301 nmttc.hdr.code = NM_TOOLTIPSCREATED;
1302 nmttc.hwndToolTips = hwndToolTip;
1304 SendMessageW(GetParent(hwndTrueOwner), WM_NOTIFY,
1305 (WPARAM)GetWindowLongPtrW(hwndTrueOwner, GWLP_ID),
1306 (LPARAM)&nmttc);
1309 return hwndToolTip;
1313 /***********************************************************************
1314 * COMCTL32_RefreshSysColors [NOT AN API]
1316 * Invoked on any control recognizing a WM_SYSCOLORCHANGE message to
1317 * refresh the color values in the color structure
1319 * PARAMS
1320 * none
1322 * RETURNS
1323 * none
1326 VOID
1327 COMCTL32_RefreshSysColors(void)
1329 comctl32_color.clrBtnHighlight = GetSysColor (COLOR_BTNHIGHLIGHT);
1330 comctl32_color.clrBtnShadow = GetSysColor (COLOR_BTNSHADOW);
1331 comctl32_color.clrBtnText = GetSysColor (COLOR_BTNTEXT);
1332 comctl32_color.clrBtnFace = GetSysColor (COLOR_BTNFACE);
1333 comctl32_color.clrHighlight = GetSysColor (COLOR_HIGHLIGHT);
1334 comctl32_color.clrHighlightText = GetSysColor (COLOR_HIGHLIGHTTEXT);
1335 comctl32_color.clr3dHilight = GetSysColor (COLOR_3DHILIGHT);
1336 comctl32_color.clr3dShadow = GetSysColor (COLOR_3DSHADOW);
1337 comctl32_color.clr3dDkShadow = GetSysColor (COLOR_3DDKSHADOW);
1338 comctl32_color.clr3dFace = GetSysColor (COLOR_3DFACE);
1339 comctl32_color.clrWindow = GetSysColor (COLOR_WINDOW);
1340 comctl32_color.clrWindowText = GetSysColor (COLOR_WINDOWTEXT);
1341 comctl32_color.clrGrayText = GetSysColor (COLOR_GRAYTEXT);
1342 comctl32_color.clrActiveCaption = GetSysColor (COLOR_ACTIVECAPTION);
1343 comctl32_color.clrInfoBk = GetSysColor (COLOR_INFOBK);
1344 comctl32_color.clrInfoText = GetSysColor (COLOR_INFOTEXT);
1347 /***********************************************************************
1348 * COMCTL32_DrawInsertMark [NOT AN API]
1350 * Draws an insertion mark (which looks similar to an 'I').
1352 * PARAMS
1353 * hDC [I] Device context to draw onto.
1354 * lpRect [I] Co-ordinates of insertion mark.
1355 * clrInsertMark [I] Colour of the insertion mark.
1356 * bHorizontal [I] True if insert mark should be drawn horizontally,
1357 * vertical otherwise.
1359 * RETURNS
1360 * none
1362 * NOTES
1363 * Draws up to but not including the bottom co-ordinate when drawing
1364 * vertically or the right co-ordinate when horizontal.
1366 void COMCTL32_DrawInsertMark(HDC hDC, const RECT *lpRect, COLORREF clrInsertMark, BOOL bHorizontal)
1368 HPEN hPen = CreatePen(PS_SOLID, 1, clrInsertMark);
1369 HPEN hOldPen;
1370 static const DWORD adwPolyPoints[] = {4,4,4};
1371 LONG lCentre = (bHorizontal ?
1372 lpRect->top + (lpRect->bottom - lpRect->top)/2 :
1373 lpRect->left + (lpRect->right - lpRect->left)/2);
1374 LONG l1 = (bHorizontal ? lpRect->left : lpRect->top);
1375 LONG l2 = (bHorizontal ? lpRect->right : lpRect->bottom);
1376 const POINT aptInsertMark[] =
1378 /* top (V) or left (H) arrow */
1379 {lCentre , l1 + 2},
1380 {lCentre - 2, l1 },
1381 {lCentre + 3, l1 },
1382 {lCentre + 1, l1 + 2},
1383 /* middle line */
1384 {lCentre , l2 - 2},
1385 {lCentre , l1 - 1},
1386 {lCentre + 1, l1 - 1},
1387 {lCentre + 1, l2 - 2},
1388 /* bottom (V) or right (H) arrow */
1389 {lCentre , l2 - 3},
1390 {lCentre - 2, l2 - 1},
1391 {lCentre + 3, l2 - 1},
1392 {lCentre + 1, l2 - 3},
1394 hOldPen = SelectObject(hDC, hPen);
1395 PolyPolyline(hDC, aptInsertMark, adwPolyPoints, sizeof(adwPolyPoints)/sizeof(adwPolyPoints[0]));
1396 SelectObject(hDC, hOldPen);
1397 DeleteObject(hPen);
1400 /***********************************************************************
1401 * COMCTL32_EnsureBitmapSize [internal]
1403 * If needed enlarge the bitmap so that the width is at least cxMinWidth
1404 * the height is at least cyMinHeight. If the bitmap already have these
1405 * dimensions nothing changes.
1407 * PARAMS
1408 * hBitmap [I/O] Bitmap to modify. The handle may change
1409 * cxMinWidth [I] If the width of the bitmap is smaller then it will
1410 * be enlarged to this value
1411 * cyMinHeight [I] If the height of the bitmap is smaller then it will
1412 * be enlarged to this value
1413 * cyBackground [I] The color with which the new area will be filled
1415 * RETURNS
1416 * none
1418 void COMCTL32_EnsureBitmapSize(HBITMAP *pBitmap, int cxMinWidth, int cyMinHeight, COLORREF crBackground)
1420 int cxNew, cyNew;
1421 BITMAP bmp;
1422 HBITMAP hNewBitmap;
1423 HBITMAP hNewDCBitmap, hOldDCBitmap;
1424 HBRUSH hNewDCBrush;
1425 HDC hdcNew, hdcOld;
1427 if (!GetObjectW(*pBitmap, sizeof(BITMAP), &bmp))
1428 return;
1429 cxNew = (cxMinWidth > bmp.bmWidth ? cxMinWidth : bmp.bmWidth);
1430 cyNew = (cyMinHeight > bmp.bmHeight ? cyMinHeight : bmp.bmHeight);
1431 if (cxNew == bmp.bmWidth && cyNew == bmp.bmHeight)
1432 return;
1434 hdcNew = CreateCompatibleDC(NULL);
1435 hNewBitmap = CreateBitmap(cxNew, cyNew, bmp.bmPlanes, bmp.bmBitsPixel, NULL);
1436 hNewDCBitmap = SelectObject(hdcNew, hNewBitmap);
1437 hNewDCBrush = SelectObject(hdcNew, CreateSolidBrush(crBackground));
1439 hdcOld = CreateCompatibleDC(NULL);
1440 hOldDCBitmap = SelectObject(hdcOld, *pBitmap);
1442 BitBlt(hdcNew, 0, 0, bmp.bmWidth, bmp.bmHeight, hdcOld, 0, 0, SRCCOPY);
1443 if (bmp.bmWidth < cxMinWidth)
1444 PatBlt(hdcNew, bmp.bmWidth, 0, cxNew, bmp.bmHeight, PATCOPY);
1445 if (bmp.bmHeight < cyMinHeight)
1446 PatBlt(hdcNew, 0, bmp.bmHeight, bmp.bmWidth, cyNew, PATCOPY);
1447 if (bmp.bmWidth < cxMinWidth && bmp.bmHeight < cyMinHeight)
1448 PatBlt(hdcNew, bmp.bmWidth, bmp.bmHeight, cxNew, cyNew, PATCOPY);
1450 SelectObject(hdcNew, hNewDCBitmap);
1451 DeleteObject(SelectObject(hdcNew, hNewDCBrush));
1452 DeleteDC(hdcNew);
1453 SelectObject(hdcOld, hOldDCBitmap);
1454 DeleteDC(hdcOld);
1456 DeleteObject(*pBitmap);
1457 *pBitmap = hNewBitmap;
1458 return;
1461 /***********************************************************************
1462 * MirrorIcon [COMCTL32.414]
1464 * Mirrors an icon so that it will appear correctly on a mirrored DC.
1466 * PARAMS
1467 * phicon1 [I/O] Icon.
1468 * phicon2 [I/O] Icon.
1470 * RETURNS
1471 * Success: TRUE.
1472 * Failure: FALSE.
1474 BOOL WINAPI MirrorIcon(HICON *phicon1, HICON *phicon2)
1476 FIXME("(%p, %p): stub\n", phicon1, phicon2);
1477 return FALSE;
1480 static inline int IsDelimiter(WCHAR c)
1482 switch(c)
1484 case '/':
1485 case '\\':
1486 case '.':
1487 case ' ':
1488 return TRUE;
1490 return FALSE;
1493 static int CALLBACK PathWordBreakProc(LPCWSTR lpch, int ichCurrent, int cch, int code)
1495 if (code == WB_ISDELIMITER)
1496 return IsDelimiter(lpch[ichCurrent]);
1497 else
1499 int dir = (code == WB_LEFT) ? -1 : 1;
1500 for(; 0 <= ichCurrent && ichCurrent < cch; ichCurrent += dir)
1501 if (IsDelimiter(lpch[ichCurrent])) return ichCurrent;
1503 return ichCurrent;
1506 /***********************************************************************
1507 * SetPathWordBreakProc [COMCTL32.384]
1509 * Sets the word break procedure for an edit control to one that understands
1510 * paths so that the user can jump over directories.
1512 * PARAMS
1513 * hwnd [I] Handle to edit control.
1514 * bSet [I] If this is TRUE then the word break proc is set, otherwise it is removed.
1516 * RETURNS
1517 * Result from EM_SETWORDBREAKPROC message.
1519 LRESULT WINAPI SetPathWordBreakProc(HWND hwnd, BOOL bSet)
1521 return SendMessageW(hwnd, EM_SETWORDBREAKPROC, 0,
1522 (LPARAM)(bSet ? PathWordBreakProc : NULL));