Eliminate strncpy and correct some NameLen bugs.
[wine/testsucceed.git] / dlls / comctl32 / commctrl.c
blob1f35a26763a33ccb6a16df98bb5f7e5b297a5e6a
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 * -- LibMain => DLLMain ("DLLMain takes over the functionality of both the
33 * LibMain and the WEP function.", MSDN)
34 * -- finish NOTES for MenuHelp, GetEffectiveClientRect and GetStatusTextW
35 * -- FIXMEs + BUGS (search for them)
37 * Control Classes
38 * -- ICC_ANIMATE_CLASS
39 * -- ICC_BAR_CLASSES
40 * -- ICC_COOL_CLASSES
41 * -- ICC_DATE_CLASSES
42 * -- ICC_HOTKEY_CLASS
43 * -- ICC_INTERNET_CLASSES
44 * -- ICC_LINK_CLASS
45 * -- ICC_LISTVIEW_CLASSES
46 * -- ICC_NATIVEFNTCTL_CLASS
47 * -- ICC_PAGESCROLLER_CLASS
48 * -- ICC_PROGRESS_CLASS
49 * -- ICC_STANDARD_CLASSES (not yet implemented)
50 * -- ICC_TAB_CLASSES
51 * -- ICC_TREEVIEW_CLASSES
52 * -- ICC_UPDOWN_CLASS
53 * -- ICC_USEREX_CLASSES
54 * -- ICC_WIN95_CLASSES
57 #include <stdarg.h>
58 #include <string.h>
59 #include <stdlib.h>
61 #include "windef.h"
62 #include "winbase.h"
63 #include "wingdi.h"
64 #include "winuser.h"
65 #include "winnls.h"
66 #include "commctrl.h"
67 #include "winerror.h"
68 #include "winreg.h"
69 #define NO_SHLWAPI_STREAM
70 #include "shlwapi.h"
71 #include "comctl32.h"
72 #include "wine/debug.h"
74 WINE_DEFAULT_DEBUG_CHANNEL(commctrl);
76 extern void ANIMATE_Register(void);
77 extern void ANIMATE_Unregister(void);
78 extern void COMBOEX_Register(void);
79 extern void COMBOEX_Unregister(void);
80 extern void DATETIME_Register(void);
81 extern void DATETIME_Unregister(void);
82 extern void FLATSB_Register(void);
83 extern void FLATSB_Unregister(void);
84 extern void HEADER_Register(void);
85 extern void HEADER_Unregister(void);
86 extern void HOTKEY_Register(void);
87 extern void HOTKEY_Unregister(void);
88 extern void IPADDRESS_Register(void);
89 extern void IPADDRESS_Unregister(void);
90 extern void LISTVIEW_Register(void);
91 extern void LISTVIEW_Unregister(void);
92 extern void MONTHCAL_Register(void);
93 extern void MONTHCAL_Unregister(void);
94 extern void NATIVEFONT_Register(void);
95 extern void NATIVEFONT_Unregister(void);
96 extern void PAGER_Register(void);
97 extern void PAGER_Unregister(void);
98 extern void PROGRESS_Register(void);
99 extern void PROGRESS_Unregister(void);
100 extern void REBAR_Register(void);
101 extern void REBAR_Unregister(void);
102 extern void STATUS_Register(void);
103 extern void STATUS_Unregister(void);
104 extern void SYSLINK_Register(void);
105 extern void SYSLINK_Unregister(void);
106 extern void TAB_Register(void);
107 extern void TAB_Unregister(void);
108 extern void TOOLBAR_Register(void);
109 extern void TOOLBAR_Unregister(void);
110 extern void TOOLTIPS_Register(void);
111 extern void TOOLTIPS_Unregister(void);
112 extern void TRACKBAR_Register(void);
113 extern void TRACKBAR_Unregister(void);
114 extern void TREEVIEW_Register(void);
115 extern void TREEVIEW_Unregister(void);
116 extern void UPDOWN_Register(void);
117 extern void UPDOWN_Unregister(void);
119 LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
121 LPWSTR COMCTL32_wSubclass = NULL;
122 HMODULE COMCTL32_hModule = 0;
123 LANGID COMCTL32_uiLang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
124 HBRUSH COMCTL32_hPattern55AABrush = NULL;
125 COMCTL32_SysColor comctl32_color;
127 static HBITMAP COMCTL32_hPattern55AABitmap = NULL;
129 static const WORD wPattern55AA[] =
131 0x5555, 0xaaaa, 0x5555, 0xaaaa,
132 0x5555, 0xaaaa, 0x5555, 0xaaaa
135 static const WCHAR strCC32SubclassInfo[] = {
136 'C','C','3','2','S','u','b','c','l','a','s','s','I','n','f','o',0
139 /***********************************************************************
140 * DllMain [Internal]
142 * Initializes the internal 'COMCTL32.DLL'.
144 * PARAMS
145 * hinstDLL [I] handle to the 'dlls' instance
146 * fdwReason [I]
147 * lpvReserved [I] reserverd, must be NULL
149 * RETURNS
150 * Success: TRUE
151 * Failure: FALSE
154 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
156 TRACE("%p,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
158 switch (fdwReason) {
159 case DLL_PROCESS_ATTACH:
160 DisableThreadLibraryCalls(hinstDLL);
162 COMCTL32_hModule = (HMODULE)hinstDLL;
164 /* add global subclassing atom (used by 'tooltip' and 'updown') */
165 COMCTL32_wSubclass = (LPWSTR)(DWORD)GlobalAddAtomW (strCC32SubclassInfo);
166 TRACE("Subclassing atom added: %p\n", COMCTL32_wSubclass);
168 /* create local pattern brush */
169 COMCTL32_hPattern55AABitmap = CreateBitmap (8, 8, 1, 1, wPattern55AA);
170 COMCTL32_hPattern55AABrush = CreatePatternBrush (COMCTL32_hPattern55AABitmap);
172 /* Get all the colors at DLL load */
173 COMCTL32_RefreshSysColors();
175 /* register all Win95 common control classes */
176 ANIMATE_Register ();
177 FLATSB_Register ();
178 HEADER_Register ();
179 HOTKEY_Register ();
180 LISTVIEW_Register ();
181 PROGRESS_Register ();
182 STATUS_Register ();
183 SYSLINK_Register ();
184 TAB_Register ();
185 TOOLBAR_Register ();
186 TOOLTIPS_Register ();
187 TRACKBAR_Register ();
188 TREEVIEW_Register ();
189 UPDOWN_Register ();
190 break;
192 case DLL_PROCESS_DETACH:
193 /* unregister all common control classes */
194 ANIMATE_Unregister ();
195 COMBOEX_Unregister ();
196 DATETIME_Unregister ();
197 FLATSB_Unregister ();
198 HEADER_Unregister ();
199 HOTKEY_Unregister ();
200 IPADDRESS_Unregister ();
201 LISTVIEW_Unregister ();
202 MONTHCAL_Unregister ();
203 NATIVEFONT_Unregister ();
204 PAGER_Unregister ();
205 PROGRESS_Unregister ();
206 REBAR_Unregister ();
207 STATUS_Unregister ();
208 SYSLINK_Unregister ();
209 TAB_Unregister ();
210 TOOLBAR_Unregister ();
211 TOOLTIPS_Unregister ();
212 TRACKBAR_Unregister ();
213 TREEVIEW_Unregister ();
214 UPDOWN_Unregister ();
216 /* delete local pattern brush */
217 DeleteObject (COMCTL32_hPattern55AABrush);
218 COMCTL32_hPattern55AABrush = NULL;
219 DeleteObject (COMCTL32_hPattern55AABitmap);
220 COMCTL32_hPattern55AABitmap = NULL;
222 /* delete global subclassing atom */
223 GlobalDeleteAtom (LOWORD(COMCTL32_wSubclass));
224 TRACE("Subclassing atom deleted: %p\n", COMCTL32_wSubclass);
225 COMCTL32_wSubclass = NULL;
226 break;
229 return TRUE;
233 /***********************************************************************
234 * MenuHelp [COMCTL32.2]
236 * Handles the setting of status bar help messages when the user
237 * selects menu items.
239 * PARAMS
240 * uMsg [I] message (WM_MENUSELECT) (see NOTES)
241 * wParam [I] wParam of the message uMsg
242 * lParam [I] lParam of the message uMsg
243 * hMainMenu [I] handle to the application's main menu
244 * hInst [I] handle to the module that contains string resources
245 * hwndStatus [I] handle to the status bar window
246 * lpwIDs [I] pointer to an array of integers (see NOTES)
248 * RETURNS
249 * No return value
251 * NOTES
252 * The official documentation is incomplete!
253 * This is the correct documentation:
255 * uMsg:
256 * MenuHelp() does NOT handle WM_COMMAND messages! It only handles
257 * WM_MENUSELECT messages.
259 * lpwIDs:
260 * (will be written ...)
263 VOID WINAPI
264 MenuHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu,
265 HINSTANCE hInst, HWND hwndStatus, UINT* lpwIDs)
267 UINT uMenuID = 0;
269 if (!IsWindow (hwndStatus))
270 return;
272 switch (uMsg) {
273 case WM_MENUSELECT:
274 TRACE("WM_MENUSELECT wParam=0x%X lParam=0x%lX\n",
275 wParam, lParam);
277 if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {
278 /* menu was closed */
279 TRACE("menu was closed!\n");
280 SendMessageW (hwndStatus, SB_SIMPLE, FALSE, 0);
282 else {
283 /* menu item was selected */
284 if (HIWORD(wParam) & MF_POPUP)
285 uMenuID = (UINT)*(lpwIDs+1);
286 else
287 uMenuID = (UINT)LOWORD(wParam);
288 TRACE("uMenuID = %u\n", uMenuID);
290 if (uMenuID) {
291 WCHAR szText[256];
293 if (!LoadStringW (hInst, uMenuID, szText, sizeof(szText)/sizeof(szText[0])))
294 szText[0] = '\0';
296 SendMessageW (hwndStatus, SB_SETTEXTW,
297 255 | SBT_NOBORDERS, (LPARAM)szText);
298 SendMessageW (hwndStatus, SB_SIMPLE, TRUE, 0);
301 break;
303 case WM_COMMAND :
304 TRACE("WM_COMMAND wParam=0x%X lParam=0x%lX\n",
305 wParam, lParam);
306 /* WM_COMMAND is not invalid since it is documented
307 * in the windows api reference. So don't output
308 * any FIXME for WM_COMMAND
310 WARN("We don't care about the WM_COMMAND\n");
311 break;
313 default:
314 FIXME("Invalid Message 0x%x!\n", uMsg);
315 break;
320 /***********************************************************************
321 * ShowHideMenuCtl [COMCTL32.3]
323 * Shows or hides controls and updates the corresponding menu item.
325 * PARAMS
326 * hwnd [I] handle to the client window.
327 * uFlags [I] menu command id.
328 * lpInfo [I] pointer to an array of integers. (See NOTES.)
330 * RETURNS
331 * Success: TRUE
332 * Failure: FALSE
334 * NOTES
335 * The official documentation is incomplete!
336 * This is the correct documentation:
338 * hwnd
339 * Handle to the window that contains the menu and controls.
341 * uFlags
342 * Identifier of the menu item to receive or lose a check mark.
344 * lpInfo
345 * The array of integers contains pairs of values. BOTH values of
346 * the first pair must be the handles to the application's main menu.
347 * Each subsequent pair consists of a menu id and control id.
350 BOOL WINAPI
351 ShowHideMenuCtl (HWND hwnd, UINT uFlags, LPINT lpInfo)
353 LPINT lpMenuId;
355 TRACE("%p, %x, %p\n", hwnd, uFlags, lpInfo);
357 if (lpInfo == NULL)
358 return FALSE;
360 if (!(lpInfo[0]) || !(lpInfo[1]))
361 return FALSE;
363 /* search for control */
364 lpMenuId = &lpInfo[2];
365 while (*lpMenuId != uFlags)
366 lpMenuId += 2;
368 if (GetMenuState ((HMENU)lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) {
369 /* uncheck menu item */
370 CheckMenuItem ((HMENU)lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_UNCHECKED);
372 /* hide control */
373 lpMenuId++;
374 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
375 SWP_HIDEWINDOW);
377 else {
378 /* check menu item */
379 CheckMenuItem ((HMENU)lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_CHECKED);
381 /* show control */
382 lpMenuId++;
383 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
384 SWP_SHOWWINDOW);
387 return TRUE;
391 /***********************************************************************
392 * GetEffectiveClientRect [COMCTL32.4]
394 * Calculates the coordinates of a rectangle in the client area.
396 * PARAMS
397 * hwnd [I] handle to the client window.
398 * lpRect [O] pointer to the rectangle of the client window
399 * lpInfo [I] pointer to an array of integers (see NOTES)
401 * RETURNS
402 * No return value.
404 * NOTES
405 * The official documentation is incomplete!
406 * This is the correct documentation:
408 * lpInfo
409 * (will be written ...)
412 VOID WINAPI
413 GetEffectiveClientRect (HWND hwnd, LPRECT lpRect, LPINT lpInfo)
415 RECT rcCtrl;
416 INT *lpRun;
417 HWND hwndCtrl;
419 TRACE("(0x%08lx 0x%08lx 0x%08lx)\n",
420 (DWORD)hwnd, (DWORD)lpRect, (DWORD)lpInfo);
422 GetClientRect (hwnd, lpRect);
423 lpRun = lpInfo;
425 do {
426 lpRun += 2;
427 if (*lpRun == 0)
428 return;
429 lpRun++;
430 hwndCtrl = GetDlgItem (hwnd, *lpRun);
431 if (GetWindowLongW (hwndCtrl, GWL_STYLE) & WS_VISIBLE) {
432 TRACE("control id 0x%x\n", *lpRun);
433 GetWindowRect (hwndCtrl, &rcCtrl);
434 MapWindowPoints (NULL, hwnd, (LPPOINT)&rcCtrl, 2);
435 SubtractRect (lpRect, lpRect, &rcCtrl);
437 lpRun++;
438 } while (*lpRun);
442 /***********************************************************************
443 * DrawStatusTextW [COMCTL32.@]
445 * Draws text with borders, like in a status bar.
447 * PARAMS
448 * hdc [I] handle to the window's display context
449 * lprc [I] pointer to a rectangle
450 * text [I] pointer to the text
451 * style [I] drawing style
453 * RETURNS
454 * No return value.
456 * NOTES
457 * The style variable can have one of the following values:
458 * (will be written ...)
461 void WINAPI DrawStatusTextW (HDC hdc, LPRECT lprc, LPCWSTR text, UINT style)
463 RECT r = *lprc;
464 UINT border = BDR_SUNKENOUTER;
466 if (style & SBT_POPOUT)
467 border = BDR_RAISEDOUTER;
468 else if (style & SBT_NOBORDERS)
469 border = 0;
471 DrawEdge (hdc, &r, border, BF_RECT|BF_ADJUST);
473 /* now draw text */
474 if (text) {
475 int oldbkmode = SetBkMode (hdc, TRANSPARENT);
476 UINT align = DT_LEFT;
477 if (*text == L'\t') {
478 text++;
479 align = DT_CENTER;
480 if (*text == L'\t') {
481 text++;
482 align = DT_RIGHT;
485 r.left += 3;
486 if (style & SBT_RTLREADING)
487 FIXME("Unsupported RTL style!\n");
488 DrawTextW (hdc, text, -1, &r, align|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX);
489 SetBkMode(hdc, oldbkmode);
494 /***********************************************************************
495 * DrawStatusText [COMCTL32.@]
496 * DrawStatusTextA [COMCTL32.5]
498 * Draws text with borders, like in a status bar.
500 * PARAMS
501 * hdc [I] handle to the window's display context
502 * lprc [I] pointer to a rectangle
503 * text [I] pointer to the text
504 * style [I] drawing style
506 * RETURNS
507 * No return value.
510 void WINAPI DrawStatusTextA (HDC hdc, LPRECT lprc, LPCSTR text, UINT style)
512 INT len;
513 LPWSTR textW = NULL;
515 if ( text ) {
516 if ( (len = MultiByteToWideChar( CP_ACP, 0, text, -1, NULL, 0 )) ) {
517 if ( (textW = Alloc( len * sizeof(WCHAR) )) )
518 MultiByteToWideChar( CP_ACP, 0, text, -1, textW, len );
521 DrawStatusTextW( hdc, lprc, textW, style );
522 Free( textW );
526 /***********************************************************************
527 * CreateStatusWindow [COMCTL32.@]
528 * CreateStatusWindowA [COMCTL32.6]
530 * Creates a status bar
532 * PARAMS
533 * style [I] window style
534 * text [I] pointer to the window text
535 * parent [I] handle to the parent window
536 * wid [I] control id of the status bar
538 * RETURNS
539 * Success: handle to the status window
540 * Failure: 0
543 HWND WINAPI
544 CreateStatusWindowA (LONG style, LPCSTR text, HWND parent, UINT wid)
546 return CreateWindowA(STATUSCLASSNAMEA, text, style,
547 CW_USEDEFAULT, CW_USEDEFAULT,
548 CW_USEDEFAULT, CW_USEDEFAULT,
549 parent, (HMENU)wid, 0, 0);
553 /***********************************************************************
554 * CreateStatusWindowW [COMCTL32.@]
556 * Creates a status bar control
558 * PARAMS
559 * style [I] window style
560 * text [I] pointer to the window text
561 * parent [I] handle to the parent window
562 * wid [I] control id of the status bar
564 * RETURNS
565 * Success: handle to the status window
566 * Failure: 0
569 HWND WINAPI
570 CreateStatusWindowW (LONG style, LPCWSTR text, HWND parent, UINT wid)
572 return CreateWindowW(STATUSCLASSNAMEW, text, style,
573 CW_USEDEFAULT, CW_USEDEFAULT,
574 CW_USEDEFAULT, CW_USEDEFAULT,
575 parent, (HMENU)wid, 0, 0);
579 /***********************************************************************
580 * CreateUpDownControl [COMCTL32.16]
582 * Creates an up-down control
584 * PARAMS
585 * style [I] window styles
586 * x [I] horizontal position of the control
587 * y [I] vertical position of the control
588 * cx [I] with of the control
589 * cy [I] height of the control
590 * parent [I] handle to the parent window
591 * id [I] the control's identifier
592 * inst [I] handle to the application's module instance
593 * buddy [I] handle to the buddy window, can be NULL
594 * maxVal [I] upper limit of the control
595 * minVal [I] lower limit of the control
596 * curVal [I] current value of the control
598 * RETURNS
599 * Success: handle to the updown control
600 * Failure: 0
603 HWND WINAPI
604 CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
605 HWND parent, INT id, HINSTANCE inst,
606 HWND buddy, INT maxVal, INT minVal, INT curVal)
608 HWND hUD =
609 CreateWindowW (UPDOWN_CLASSW, 0, style, x, y, cx, cy,
610 parent, (HMENU)id, inst, 0);
611 if (hUD) {
612 SendMessageW (hUD, UDM_SETBUDDY, (WPARAM)buddy, 0);
613 SendMessageW (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));
614 SendMessageW (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));
617 return hUD;
621 /***********************************************************************
622 * InitCommonControls [COMCTL32.17]
624 * Registers the common controls.
626 * PARAMS
627 * No parameters.
629 * RETURNS
630 * No return values.
632 * NOTES
633 * This function is just a dummy.
634 * The Win95 controls are registered at the DLL's initialization.
635 * To register other controls InitCommonControlsEx() must be used.
638 VOID WINAPI
639 InitCommonControls (void)
644 /***********************************************************************
645 * InitCommonControlsEx [COMCTL32.@]
647 * Registers the common controls.
649 * PARAMS
650 * lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
652 * RETURNS
653 * Success: TRUE
654 * Failure: FALSE
656 * NOTES
657 * Only the additional common controls are registered by this function.
658 * The Win95 controls are registered at the DLL's initialization.
660 * FIXME
661 * implement the following control classes:
662 * ICC_LINK_CLASS
663 * ICC_STANDARD_CLASSES
666 BOOL WINAPI
667 InitCommonControlsEx (LPINITCOMMONCONTROLSEX lpInitCtrls)
669 INT cCount;
670 DWORD dwMask;
672 if (!lpInitCtrls)
673 return FALSE;
674 if (lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
675 return FALSE;
677 TRACE("(0x%08lx)\n", lpInitCtrls->dwICC);
679 for (cCount = 0; cCount < 32; cCount++) {
680 dwMask = 1 << cCount;
681 if (!(lpInitCtrls->dwICC & dwMask))
682 continue;
684 switch (lpInitCtrls->dwICC & dwMask) {
685 /* dummy initialization */
686 case ICC_ANIMATE_CLASS:
687 case ICC_BAR_CLASSES:
688 case ICC_LISTVIEW_CLASSES:
689 case ICC_TREEVIEW_CLASSES:
690 case ICC_TAB_CLASSES:
691 case ICC_UPDOWN_CLASS:
692 case ICC_PROGRESS_CLASS:
693 case ICC_HOTKEY_CLASS:
694 break;
696 /* advanced classes - not included in Win95 */
697 case ICC_DATE_CLASSES:
698 MONTHCAL_Register ();
699 DATETIME_Register ();
700 break;
702 case ICC_USEREX_CLASSES:
703 COMBOEX_Register ();
704 break;
706 case ICC_COOL_CLASSES:
707 REBAR_Register ();
708 break;
710 case ICC_INTERNET_CLASSES:
711 IPADDRESS_Register ();
712 break;
714 case ICC_PAGESCROLLER_CLASS:
715 PAGER_Register ();
716 break;
718 case ICC_NATIVEFNTCTL_CLASS:
719 NATIVEFONT_Register ();
720 break;
722 case ICC_LINK_CLASS:
723 SYSLINK_Register ();
724 break;
726 default:
727 FIXME("Unknown class! dwICC=0x%lX\n", dwMask);
728 break;
732 return TRUE;
736 /***********************************************************************
737 * CreateToolbarEx [COMCTL32.@]
739 * Creates a toolbar window.
741 * PARAMS
742 * hwnd
743 * style
744 * wID
745 * nBitmaps
746 * hBMInst
747 * wBMID
748 * lpButtons
749 * iNumButtons
750 * dxButton
751 * dyButton
752 * dxBitmap
753 * dyBitmap
754 * uStructSize
756 * RETURNS
757 * Success: handle to the tool bar control
758 * Failure: 0
761 HWND WINAPI
762 CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
763 HINSTANCE hBMInst, UINT wBMID, LPCTBBUTTON lpButtons,
764 INT iNumButtons, INT dxButton, INT dyButton,
765 INT dxBitmap, INT dyBitmap, UINT uStructSize)
767 HWND hwndTB;
769 hwndTB =
770 CreateWindowExW(0, TOOLBARCLASSNAMEW, NULL, style|WS_CHILD, 0,0,100,30,
771 hwnd, (HMENU)wID, COMCTL32_hModule, NULL);
772 if(hwndTB) {
773 TBADDBITMAP tbab;
775 SendMessageW (hwndTB, TB_BUTTONSTRUCTSIZE, (WPARAM)uStructSize, 0);
777 /* set bitmap and button size */
778 /*If CreateToolbarEx receives 0, windows sets default values*/
779 if (dxBitmap <= 0)
780 dxBitmap = 16;
781 if (dyBitmap <= 0)
782 dyBitmap = 15;
783 SendMessageW (hwndTB, TB_SETBITMAPSIZE, 0,
784 MAKELPARAM((WORD)dxBitmap, (WORD)dyBitmap));
786 if (dxButton <= 0)
787 dxButton = 24;
788 if (dyButton <= 0)
789 dyButton = 22;
790 SendMessageW (hwndTB, TB_SETBUTTONSIZE, 0,
791 MAKELPARAM((WORD)dxButton, (WORD)dyButton));
794 /* add bitmaps */
795 if (nBitmaps > 0)
797 tbab.hInst = hBMInst;
798 tbab.nID = wBMID;
800 SendMessageW (hwndTB, TB_ADDBITMAP, (WPARAM)nBitmaps, (LPARAM)&tbab);
802 /* add buttons */
803 if(iNumButtons > 0)
804 SendMessageW (hwndTB, TB_ADDBUTTONSW,
805 (WPARAM)iNumButtons, (LPARAM)lpButtons);
808 return hwndTB;
812 /***********************************************************************
813 * CreateMappedBitmap [COMCTL32.8]
815 * Loads a bitmap resource using a colour map.
817 * PARAMS
818 * hInstance [I] Handle to the module containing the bitmap.
819 * idBitmap [I] The bitmap resource ID.
820 * wFlags [I] CMB_MASKED for using bitmap as a mask or 0 for normal.
821 * lpColorMap [I] Colour information needed for the bitmap or NULL (uses system colours).
822 * iNumMaps [I] Number of COLORMAP's pointed to by lpColorMap.
824 * RETURNS
825 * Success: handle to the new bitmap
826 * Failure: 0
829 HBITMAP WINAPI
830 CreateMappedBitmap (HINSTANCE hInstance, INT idBitmap, UINT wFlags,
831 LPCOLORMAP lpColorMap, INT iNumMaps)
833 HGLOBAL hglb;
834 HRSRC hRsrc;
835 LPBITMAPINFOHEADER lpBitmap, lpBitmapInfo;
836 UINT nSize, nColorTableSize, iColor;
837 RGBQUAD *pColorTable;
838 INT i, iMaps, nWidth, nHeight;
839 HDC hdcScreen;
840 HBITMAP hbm;
841 LPCOLORMAP sysColorMap;
842 COLORREF cRef;
843 COLORMAP internalColorMap[4] =
844 {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
846 /* initialize pointer to colortable and default color table */
847 if (lpColorMap) {
848 iMaps = iNumMaps;
849 sysColorMap = lpColorMap;
851 else {
852 internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT);
853 internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW);
854 internalColorMap[2].to = GetSysColor (COLOR_BTNFACE);
855 internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT);
856 iMaps = 4;
857 sysColorMap = (LPCOLORMAP)internalColorMap;
860 hRsrc = FindResourceW (hInstance, (LPWSTR)idBitmap, (LPWSTR)RT_BITMAP);
861 if (hRsrc == 0)
862 return 0;
863 hglb = LoadResource (hInstance, hRsrc);
864 if (hglb == 0)
865 return 0;
866 lpBitmap = (LPBITMAPINFOHEADER)LockResource (hglb);
867 if (lpBitmap == NULL)
868 return 0;
870 if (lpBitmap->biSize >= sizeof(BITMAPINFOHEADER) && lpBitmap->biClrUsed)
871 nColorTableSize = lpBitmap->biClrUsed;
872 else if (lpBitmap->biBitCount <= 8)
873 nColorTableSize = (1 << lpBitmap->biBitCount);
874 else
875 nColorTableSize = 0;
876 nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
877 lpBitmapInfo = (LPBITMAPINFOHEADER)GlobalAlloc (GMEM_FIXED, nSize);
878 if (lpBitmapInfo == NULL)
879 return 0;
880 RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);
882 pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo)+(UINT)lpBitmapInfo->biSize);
884 for (iColor = 0; iColor < nColorTableSize; iColor++) {
885 for (i = 0; i < iMaps; i++) {
886 cRef = RGB(pColorTable[iColor].rgbRed,
887 pColorTable[iColor].rgbGreen,
888 pColorTable[iColor].rgbBlue);
889 if ( cRef == sysColorMap[i].from) {
890 #if 0
891 if (wFlags & CBS_MASKED) {
892 if (sysColorMap[i].to != COLOR_BTNTEXT)
893 pColorTable[iColor] = RGB(255, 255, 255);
895 else
896 #endif
897 pColorTable[iColor].rgbBlue = GetBValue(sysColorMap[i].to);
898 pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);
899 pColorTable[iColor].rgbRed = GetRValue(sysColorMap[i].to);
900 break;
904 nWidth = (INT)lpBitmapInfo->biWidth;
905 nHeight = (INT)lpBitmapInfo->biHeight;
906 hdcScreen = GetDC (NULL);
907 hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
908 if (hbm) {
909 HDC hdcDst = CreateCompatibleDC (hdcScreen);
910 HBITMAP hbmOld = SelectObject (hdcDst, hbm);
911 LPBYTE lpBits = (LPBYTE)(lpBitmap + 1);
912 lpBits += nColorTableSize * sizeof(RGBQUAD);
913 StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
914 lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
915 SRCCOPY);
916 SelectObject (hdcDst, hbmOld);
917 DeleteDC (hdcDst);
919 ReleaseDC (NULL, hdcScreen);
920 GlobalFree ((HGLOBAL)lpBitmapInfo);
921 FreeResource (hglb);
923 return hbm;
927 /***********************************************************************
928 * CreateToolbar [COMCTL32.7]
930 * Creates a toolbar control.
932 * PARAMS
933 * hwnd
934 * style
935 * wID
936 * nBitmaps
937 * hBMInst
938 * wBMID
939 * lpButtons
940 * iNumButtons
942 * RETURNS
943 * Success: handle to the tool bar control
944 * Failure: 0
946 * NOTES
947 * Do not use this functions anymore. Use CreateToolbarEx instead.
950 HWND WINAPI
951 CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
952 HINSTANCE hBMInst, UINT wBMID,
953 LPCTBBUTTON lpButtons,INT iNumButtons)
955 return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
956 hBMInst, wBMID, lpButtons,
957 iNumButtons, 0, 0, 0, 0, CCSIZEOF_STRUCT(TBBUTTON, dwData));
961 /***********************************************************************
962 * DllGetVersion [COMCTL32.@]
964 * Retrieves version information of the 'COMCTL32.DLL'
966 * PARAMS
967 * pdvi [O] pointer to version information structure.
969 * RETURNS
970 * Success: S_OK
971 * Failure: E_INVALIDARG
973 * NOTES
974 * Returns version of a comctl32.dll from IE4.01 SP1.
977 HRESULT WINAPI
978 COMCTL32_DllGetVersion (DLLVERSIONINFO *pdvi)
980 if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
981 WARN("wrong DLLVERSIONINFO size from app\n");
982 return E_INVALIDARG;
985 pdvi->dwMajorVersion = COMCTL32_VERSION;
986 pdvi->dwMinorVersion = COMCTL32_VERSION_MINOR;
987 pdvi->dwBuildNumber = 2919;
988 pdvi->dwPlatformID = 6304;
990 TRACE("%lu.%lu.%lu.%lu\n",
991 pdvi->dwMajorVersion, pdvi->dwMinorVersion,
992 pdvi->dwBuildNumber, pdvi->dwPlatformID);
994 return S_OK;
997 /***********************************************************************
998 * DllInstall (COMCTL32.@)
1000 * Installs the ComCtl32 DLL.
1002 * RETURNS
1003 * Success: S_OK
1004 * Failure: A HRESULT error
1006 HRESULT WINAPI COMCTL32_DllInstall(BOOL bInstall, LPCWSTR cmdline)
1008 FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
1009 debugstr_w(cmdline));
1011 return S_OK;
1014 /***********************************************************************
1015 * _TrackMouseEvent [COMCTL32.@]
1017 * Requests notification of mouse events
1019 * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
1020 * to the hwnd specified in the ptme structure. After the event message
1021 * is posted to the hwnd, the entry in the queue is removed.
1023 * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
1024 * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
1025 * immediately and the TME_LEAVE flag being ignored.
1027 * PARAMS
1028 * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
1030 * RETURNS
1031 * Success: non-zero
1032 * Failure: zero
1034 * IMPLEMENTATION moved to USER32.TrackMouseEvent
1038 BOOL WINAPI
1039 _TrackMouseEvent (TRACKMOUSEEVENT *ptme)
1041 return TrackMouseEvent (ptme);
1044 /*************************************************************************
1045 * GetMUILanguage [COMCTL32.@]
1047 * Returns the user interface language in use by the current process.
1049 * RETURNS
1050 * Language ID in use by the current process.
1052 LANGID WINAPI GetMUILanguage (VOID)
1054 return COMCTL32_uiLang;
1058 /*************************************************************************
1059 * InitMUILanguage [COMCTL32.@]
1061 * Sets the user interface language to be used by the current process.
1063 * RETURNS
1064 * Nothing.
1066 VOID WINAPI InitMUILanguage (LANGID uiLang)
1068 COMCTL32_uiLang = uiLang;
1072 /***********************************************************************
1073 * SetWindowSubclass [COMCTL32.410]
1075 * Starts a window subclass
1077 * PARAMS
1078 * hWnd [in] handle to window subclass.
1079 * pfnSubclass [in] Pointer to new window procedure.
1080 * uIDSubclass [in] Unique identifier of sublass together with pfnSubclass.
1081 * dwRef [in] Reference data to pass to window procedure.
1083 * RETURNS
1084 * Success: non-zero
1085 * Failure: zero
1087 * BUGS
1088 * If an application manually subclasses a window after subclassing it with
1089 * this API and then with this API again, then none of the previous
1090 * subclasses get called or the origional window procedure.
1093 BOOL WINAPI SetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
1094 UINT_PTR uIDSubclass, DWORD_PTR dwRef)
1096 LPSUBCLASS_INFO stack;
1097 LPSUBCLASSPROCS proc;
1099 TRACE ("(%p, %p, %x, %lx)\n", hWnd, pfnSubclass, uIDSubclass, dwRef);
1101 /* Since the window procedure that we set here has two additional arguments,
1102 * we can't simply set it as the new window procedure of the window. So we
1103 * set our own window procedure and then calculate the other two arguments
1104 * from there. */
1106 /* See if we have been called for this window */
1107 stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
1108 if (!stack) {
1109 /* allocate stack */
1110 stack = Alloc (sizeof(SUBCLASS_INFO));
1111 if (!stack) {
1112 ERR ("Failed to allocate our Subclassing stack\n");
1113 return FALSE;
1115 SetPropW (hWnd, COMCTL32_wSubclass, (HANDLE)stack);
1117 /* set window procedure to our own and save the current one */
1118 if (IsWindowUnicode (hWnd))
1119 stack->origproc = (WNDPROC)SetWindowLongPtrW (hWnd, GWLP_WNDPROC,
1120 (DWORD_PTR)COMCTL32_SubclassProc);
1121 else
1122 stack->origproc = (WNDPROC)SetWindowLongPtrA (hWnd, GWLP_WNDPROC,
1123 (DWORD_PTR)COMCTL32_SubclassProc);
1125 else {
1126 /* Check to see if we have called this function with the same uIDSubClass
1127 * and pfnSubclass */
1128 proc = stack->SubclassProcs;
1129 while (proc) {
1130 if ((proc->id == uIDSubclass) &&
1131 (proc->subproc == pfnSubclass)) {
1132 proc->ref = dwRef;
1133 return TRUE;
1135 proc = proc->next;
1139 proc = Alloc(sizeof(SUBCLASSPROCS));
1140 if (!proc) {
1141 ERR ("Failed to allocate subclass entry in stack\n");
1142 if (IsWindowUnicode (hWnd))
1143 SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1144 else
1145 SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1146 Free (stack);
1147 RemovePropW( hWnd, COMCTL32_wSubclass );
1148 return FALSE;
1151 proc->subproc = pfnSubclass;
1152 proc->ref = dwRef;
1153 proc->id = uIDSubclass;
1154 proc->next = stack->SubclassProcs;
1155 stack->SubclassProcs = proc;
1157 return TRUE;
1161 /***********************************************************************
1162 * GetWindowSubclass [COMCTL32.411]
1164 * Gets the Reference data from a subclass.
1166 * PARAMS
1167 * hWnd [in] Handle to window which were subclassing
1168 * pfnSubclass [in] Pointer to the subclass procedure
1169 * uID [in] Unique indentifier of the subclassing procedure
1170 * pdwRef [out] Pointer to the reference data
1172 * RETURNS
1173 * Success: Non-zero
1174 * Failure: 0
1177 BOOL WINAPI GetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
1178 UINT_PTR uID, DWORD_PTR *pdwRef)
1180 LPSUBCLASS_INFO stack;
1181 LPSUBCLASSPROCS proc;
1183 TRACE ("(%p, %p, %x, %p)\n", hWnd, pfnSubclass, uID, pdwRef);
1185 /* See if we have been called for this window */
1186 stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
1187 if (!stack)
1188 return FALSE;
1190 proc = stack->SubclassProcs;
1191 while (proc) {
1192 if ((proc->id == uID) &&
1193 (proc->subproc == pfnSubclass)) {
1194 *pdwRef = proc->ref;
1195 return TRUE;
1197 proc = proc->next;
1200 return FALSE;
1204 /***********************************************************************
1205 * RemoveWindowSubclass [COMCTL32.412]
1207 * Removes a window subclass.
1209 * PARAMS
1210 * hWnd [in] Handle to the window were subclassing
1211 * pfnSubclass [in] Pointer to the subclass procedure
1212 * uID [in] Unique identifier of this subclass
1214 * RETURNS
1215 * Success: non-zero
1216 * Failure: zero
1219 BOOL WINAPI RemoveWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR uID)
1221 LPSUBCLASS_INFO stack;
1222 LPSUBCLASSPROCS prevproc = NULL;
1223 LPSUBCLASSPROCS proc;
1224 BOOL ret = FALSE;
1226 TRACE ("(%p, %p, %x)\n", hWnd, pfnSubclass, uID);
1228 /* Find the Subclass to remove */
1229 stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
1230 if (!stack)
1231 return FALSE;
1233 proc = stack->SubclassProcs;
1234 while (proc) {
1235 if ((proc->id == uID) &&
1236 (proc->subproc == pfnSubclass)) {
1238 if (!prevproc)
1239 stack->SubclassProcs = proc->next;
1240 else
1241 prevproc->next = proc->next;
1243 if (stack->stackpos == proc)
1244 stack->stackpos = stack->stackpos->next;
1246 Free (proc);
1247 ret = TRUE;
1248 break;
1250 prevproc = proc;
1251 proc = proc->next;
1254 if (!stack->SubclassProcs && !stack->running) {
1255 TRACE("Last Subclass removed, cleaning up\n");
1256 /* clean up our heap and reset the origional window procedure */
1257 if (IsWindowUnicode (hWnd))
1258 SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1259 else
1260 SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1261 Free (stack);
1262 RemovePropW( hWnd, COMCTL32_wSubclass );
1265 return ret;
1268 /***********************************************************************
1269 * COMCTL32_SubclassProc (internal)
1271 * Window procedure for all subclassed windows.
1272 * Saves the current subclassing stack position to support nested messages
1274 LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1276 LPSUBCLASS_INFO stack;
1277 LPSUBCLASSPROCS proc;
1278 LRESULT ret;
1280 TRACE ("(%p, 0x%08x, 0x%08x, 0x%08lx)\n", hWnd, uMsg, wParam, lParam);
1282 stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
1283 if (!stack) {
1284 ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
1285 return 0;
1288 /* Save our old stackpos to properly handle nested messages */
1289 proc = stack->stackpos;
1290 stack->stackpos = stack->SubclassProcs;
1291 stack->running++;
1292 ret = DefSubclassProc(hWnd, uMsg, wParam, lParam);
1293 stack->running--;
1294 stack->stackpos = proc;
1296 if (!stack->SubclassProcs && !stack->running) {
1297 TRACE("Last Subclass removed, cleaning up\n");
1298 /* clean up our heap and reset the origional window procedure */
1299 if (IsWindowUnicode (hWnd))
1300 SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1301 else
1302 SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1303 Free (stack);
1304 RemovePropW( hWnd, COMCTL32_wSubclass );
1306 return ret;
1309 /***********************************************************************
1310 * DefSubclassProc [COMCTL32.413]
1312 * Calls the next window procedure (ie. the one before this subclass)
1314 * PARAMS
1315 * hWnd [in] The window that we're subclassing
1316 * uMsg [in] Message
1317 * wParam [in] WPARAM
1318 * lParam [in] LPARAM
1320 * RETURNS
1321 * Success: non-zero
1322 * Failure: zero
1325 LRESULT WINAPI DefSubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1327 LPSUBCLASS_INFO stack;
1328 LRESULT ret;
1330 TRACE ("(%p, 0x%08x, 0x%08x, 0x%08lx)\n", hWnd, uMsg, wParam, lParam);
1332 /* retrieve our little stack from the Properties */
1333 stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
1334 if (!stack) {
1335 ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
1336 return 0;
1339 /* If we are at the end of stack then we have to call the original
1340 * window procedure */
1341 if (!stack->stackpos) {
1342 if (IsWindowUnicode (hWnd))
1343 ret = CallWindowProcW (stack->origproc, hWnd, uMsg, wParam, lParam);
1344 else
1345 ret = CallWindowProcA (stack->origproc, hWnd, uMsg, wParam, lParam);
1346 } else {
1347 LPSUBCLASSPROCS proc = stack->stackpos;
1348 stack->stackpos = stack->stackpos->next;
1349 /* call the Subclass procedure from the stack */
1350 ret = proc->subproc (hWnd, uMsg, wParam, lParam,
1351 proc->id, proc->ref);
1354 return ret;
1358 /***********************************************************************
1359 * COMCTL32_CreateToolTip [NOT AN API]
1361 * Creates a tooltip for the control specified in hwnd and does all
1362 * necessary setup and notifications.
1364 * PARAMS
1365 * hwndOwner [I] Handle to the window that will own the tool tip.
1367 * RETURNS
1368 * Success: Handle of tool tip window.
1369 * Failure: NULL
1372 HWND
1373 COMCTL32_CreateToolTip(HWND hwndOwner)
1375 HWND hwndToolTip;
1377 hwndToolTip = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, 0,
1378 CW_USEDEFAULT, CW_USEDEFAULT,
1379 CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner,
1380 0, 0, 0);
1382 /* Send NM_TOOLTIPSCREATED notification */
1383 if (hwndToolTip)
1385 NMTOOLTIPSCREATED nmttc;
1386 /* true owner can be different if hwndOwner is a child window */
1387 HWND hwndTrueOwner = GetWindow(hwndToolTip, GW_OWNER);
1388 nmttc.hdr.hwndFrom = hwndTrueOwner;
1389 nmttc.hdr.idFrom = GetWindowLongPtrW(hwndTrueOwner, GWLP_ID);
1390 nmttc.hdr.code = NM_TOOLTIPSCREATED;
1391 nmttc.hwndToolTips = hwndToolTip;
1393 SendMessageW(GetParent(hwndTrueOwner), WM_NOTIFY,
1394 (WPARAM)GetWindowLongPtrW(hwndTrueOwner, GWLP_ID),
1395 (LPARAM)&nmttc);
1398 return hwndToolTip;
1402 /***********************************************************************
1403 * COMCTL32_RefreshSysColors [NOT AN API]
1405 * Invoked on any control recognizing a WM_SYSCOLORCHANGE message to
1406 * refresh the color values in the color structure
1408 * PARAMS
1409 * none
1411 * RETURNS
1412 * none
1415 VOID
1416 COMCTL32_RefreshSysColors(void)
1418 comctl32_color.clrBtnHighlight = GetSysColor (COLOR_BTNHIGHLIGHT);
1419 comctl32_color.clrBtnShadow = GetSysColor (COLOR_BTNSHADOW);
1420 comctl32_color.clrBtnText = GetSysColor (COLOR_BTNTEXT);
1421 comctl32_color.clrBtnFace = GetSysColor (COLOR_BTNFACE);
1422 comctl32_color.clrHighlight = GetSysColor (COLOR_HIGHLIGHT);
1423 comctl32_color.clrHighlightText = GetSysColor (COLOR_HIGHLIGHTTEXT);
1424 comctl32_color.clr3dHilight = GetSysColor (COLOR_3DHILIGHT);
1425 comctl32_color.clr3dShadow = GetSysColor (COLOR_3DSHADOW);
1426 comctl32_color.clr3dDkShadow = GetSysColor (COLOR_3DDKSHADOW);
1427 comctl32_color.clr3dFace = GetSysColor (COLOR_3DFACE);
1428 comctl32_color.clrWindow = GetSysColor (COLOR_WINDOW);
1429 comctl32_color.clrWindowText = GetSysColor (COLOR_WINDOWTEXT);
1430 comctl32_color.clrGrayText = GetSysColor (COLOR_GRAYTEXT);
1431 comctl32_color.clrActiveCaption = GetSysColor (COLOR_ACTIVECAPTION);
1432 comctl32_color.clrInfoBk = GetSysColor (COLOR_INFOBK);
1433 comctl32_color.clrInfoText = GetSysColor (COLOR_INFOTEXT);
1436 /***********************************************************************
1437 * COMCTL32_DrawInsertMark [NOT AN API]
1439 * Draws an insertion mark (which looks similar to an 'I').
1441 * PARAMS
1442 * hDC [I] Device context to draw onto.
1443 * lpRect [I] Co-ordinates of insertion mark.
1444 * clrInsertMark [I] Colour of the insertion mark.
1445 * bHorizontal [I] True if insert mark should be drawn horizontally,
1446 * vertical otherwise.
1448 * RETURNS
1449 * none
1451 * NOTES
1452 * Draws up to but not including the bottom co-ordinate when drawing
1453 * vertically or the right co-ordinate when horizontal.
1455 void COMCTL32_DrawInsertMark(HDC hDC, const RECT *lpRect, COLORREF clrInsertMark, BOOL bHorizontal)
1457 HPEN hPen = CreatePen(PS_SOLID, 1, clrInsertMark);
1458 HPEN hOldPen;
1459 static const DWORD adwPolyPoints[] = {4,4,4};
1460 LONG lCentre = (bHorizontal ?
1461 lpRect->top + (lpRect->bottom - lpRect->top)/2 :
1462 lpRect->left + (lpRect->right - lpRect->left)/2);
1463 LONG l1 = (bHorizontal ? lpRect->left : lpRect->top);
1464 LONG l2 = (bHorizontal ? lpRect->right : lpRect->bottom);
1465 const POINT aptInsertMark[] =
1467 /* top (V) or left (H) arrow */
1468 {lCentre , l1 + 2},
1469 {lCentre - 2, l1 },
1470 {lCentre + 3, l1 },
1471 {lCentre + 1, l1 + 2},
1472 /* middle line */
1473 {lCentre , l2 - 2},
1474 {lCentre , l1 - 1},
1475 {lCentre + 1, l1 - 1},
1476 {lCentre + 1, l2 - 2},
1477 /* bottom (V) or right (H) arrow */
1478 {lCentre , l2 - 3},
1479 {lCentre - 2, l2 - 1},
1480 {lCentre + 3, l2 - 1},
1481 {lCentre + 1, l2 - 3},
1483 hOldPen = SelectObject(hDC, hPen);
1484 PolyPolyline(hDC, aptInsertMark, adwPolyPoints, sizeof(adwPolyPoints)/sizeof(adwPolyPoints[0]));
1485 SelectObject(hDC, hOldPen);
1486 DeleteObject(hPen);
1489 /***********************************************************************
1490 * MirrorIcon [COMCTL32.414]
1492 * Mirrors an icon so that it will appear correctly on a mirrored DC.
1494 * PARAMS
1495 * phicon1 [I/O] Icon.
1496 * phicon2 [I/O] Icon.
1498 * RETURNS
1499 * Success: TRUE.
1500 * Failure: FALSE.
1502 BOOL WINAPI MirrorIcon(HICON *phicon1, HICON *phicon2)
1504 FIXME("(%p, %p): stub\n", phicon1, phicon2);
1505 return FALSE;
1508 static inline int IsDelimiter(WCHAR c)
1510 switch(c)
1512 case '/':
1513 case '\\':
1514 case '.':
1515 case ' ':
1516 return TRUE;
1518 return FALSE;
1521 static int CALLBACK PathWordBreakProc(LPWSTR lpch, int ichCurrent, int cch, int code)
1523 if (code == WB_ISDELIMITER)
1524 return IsDelimiter(lpch[ichCurrent]);
1525 else
1527 int dir = (code == WB_LEFT) ? -1 : 1;
1528 for(; 0 <= ichCurrent && ichCurrent < cch; ichCurrent += dir)
1529 if (IsDelimiter(lpch[ichCurrent])) return ichCurrent;
1531 return ichCurrent;
1534 /***********************************************************************
1535 * SetPathWordBreakProc [COMCTL32.384]
1537 * Sets the word break procedure for an edit control to one that understands
1538 * paths so that the user can jump over directories.
1540 * PARAMS
1541 * hwnd [I] Handle to edit control.
1542 * bSet [I] If this is TRUE then the word break proc is set, otherwise it is removed.
1544 * RETURNS
1545 * Result from EM_SETWORDBREAKPROC message.
1547 LRESULT WINAPI SetPathWordBreakProc(HWND hwnd, BOOL bSet)
1549 return SendMessageW(hwnd, EM_SETWORDBREAKPROC, 0,
1550 (LPARAM)(bSet ? PathWordBreakProc : NULL));