advapi32: Fix the failing QueryServiceConfig2 test on platforms win2k3 and vista.
[wine/multimedia.git] / dlls / comctl32 / commctrl.c
blob0e901977dfde131bce38276dae2d88ddeaf8ad25
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 #define NAME "microsoft.windows.common-controls"
76 #define FILE "comctl32.dll"
77 #define VERSION "6.0.2600.2982"
78 #define PUBLIC_KEY "6595b64144ccf1df"
80 #ifdef __i386__
81 #define ARCH "x86"
82 #elif defined __x86_64__
83 #define ARCH "amd64"
84 #else
85 #define ARCH "none"
86 #endif
88 static const char manifest[] =
89 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
90 "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\" manifestVersion=\"1.0\">\n"
91 " <assemblyIdentity type=\"win32\" name=\"" NAME "\" version=\"" VERSION "\" processorArchitecture=\"" ARCH "\" publicKeyToken=\"" PUBLIC_KEY "\"/>\n"
92 " <file name=\"" FILE "\">\n"
93 " <windowClass>Button</windowClass>\n"
94 " <windowClass>ButtonListBox</windowClass>\n"
95 " <windowClass>ComboBoxEx32</windowClass>\n"
96 " <windowClass>ComboLBox</windowClass>\n"
97 " <windowClass>Combobox</windowClass>\n"
98 " <windowClass>Edit</windowClass>\n"
99 " <windowClass>Listbox</windowClass>\n"
100 " <windowClass>NativeFontCtl</windowClass>\n"
101 " <windowClass>ReBarWindow32</windowClass>\n"
102 " <windowClass>ScrollBar</windowClass>\n"
103 " <windowClass>Static</windowClass>\n"
104 " <windowClass>SysAnimate32</windowClass>\n"
105 " <windowClass>SysDateTimePick32</windowClass>\n"
106 " <windowClass>SysHeader32</windowClass>\n"
107 " <windowClass>SysIPAddress32</windowClass>\n"
108 " <windowClass>SysLink</windowClass>\n"
109 " <windowClass>SysListView32</windowClass>\n"
110 " <windowClass>SysMonthCal32</windowClass>\n"
111 " <windowClass>SysPager</windowClass>\n"
112 " <windowClass>SysTabControl32</windowClass>\n"
113 " <windowClass>SysTreeView32</windowClass>\n"
114 " <windowClass>ToolbarWindow32</windowClass>\n"
115 " <windowClass>msctls_hotkey32</windowClass>\n"
116 " <windowClass>msctls_progress32</windowClass>\n"
117 " <windowClass>msctls_statusbar32</windowClass>\n"
118 " <windowClass>msctls_trackbar32</windowClass>\n"
119 " <windowClass>msctls_updown32</windowClass>\n"
120 " <windowClass>tooltips_class32</windowClass>\n"
121 " </file>\n"
122 "</assembly>\n";
124 static const char manifest_filename[] = ARCH "_" NAME "_" PUBLIC_KEY "_" VERSION "_none_deadbeef.manifest";
126 LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
128 LPWSTR COMCTL32_wSubclass = NULL;
129 HMODULE COMCTL32_hModule = 0;
130 LANGID COMCTL32_uiLang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
131 HBRUSH COMCTL32_hPattern55AABrush = NULL;
132 COMCTL32_SysColor comctl32_color;
134 static HBITMAP COMCTL32_hPattern55AABitmap = NULL;
136 static const WORD wPattern55AA[] =
138 0x5555, 0xaaaa, 0x5555, 0xaaaa,
139 0x5555, 0xaaaa, 0x5555, 0xaaaa
142 static const WCHAR strCC32SubclassInfo[] = {
143 'C','C','3','2','S','u','b','c','l','a','s','s','I','n','f','o',0
146 static BOOL create_manifest( BOOL install )
148 static const WCHAR winsxsW[] = {'\\','w','i','n','s','x','s',0};
149 static const WCHAR manifestsW[] = {'\\','m','a','n','i','f','e','s','t','s','\\',0};
151 DWORD len, written;
152 WCHAR *buffer;
153 HANDLE file;
154 BOOL ret = FALSE;
156 len = MultiByteToWideChar( CP_UTF8, 0, manifest_filename, sizeof(manifest_filename), NULL, 0 );
157 len += GetWindowsDirectoryW( NULL, 0 );
158 len += lstrlenW(winsxsW);
159 len += lstrlenW(manifestsW);
160 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) ))) return FALSE;
161 GetWindowsDirectoryW( buffer, len );
162 lstrcatW( buffer, winsxsW );
163 CreateDirectoryW( buffer, NULL );
164 lstrcatW( buffer, manifestsW );
165 CreateDirectoryW( buffer, NULL );
166 MultiByteToWideChar( CP_UTF8, 0, manifest_filename, sizeof(manifest_filename),
167 buffer + lstrlenW(buffer), len );
168 if (install)
170 file = CreateFileW( buffer, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL );
171 if (file != INVALID_HANDLE_VALUE)
173 ret = (WriteFile( file, manifest, sizeof(manifest)-1, &written, NULL ) &&
174 written == sizeof(manifest)-1);
175 CloseHandle( file );
176 if (!ret) DeleteFileW( buffer );
177 else TRACE("created %s\n", debugstr_w(buffer));
180 else ret = DeleteFileW( buffer );
182 HeapFree( GetProcessHeap(), 0, buffer );
183 return ret;
187 /***********************************************************************
188 * DllMain [Internal]
190 * Initializes the internal 'COMCTL32.DLL'.
192 * PARAMS
193 * hinstDLL [I] handle to the 'dlls' instance
194 * fdwReason [I]
195 * lpvReserved [I] reserverd, must be NULL
197 * RETURNS
198 * Success: TRUE
199 * Failure: FALSE
202 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
204 TRACE("%p,%x,%p\n", hinstDLL, fdwReason, lpvReserved);
206 switch (fdwReason) {
207 case DLL_PROCESS_ATTACH:
208 DisableThreadLibraryCalls(hinstDLL);
210 COMCTL32_hModule = hinstDLL;
212 /* add global subclassing atom (used by 'tooltip' and 'updown') */
213 COMCTL32_wSubclass = (LPWSTR)(DWORD_PTR)GlobalAddAtomW (strCC32SubclassInfo);
214 TRACE("Subclassing atom added: %p\n", COMCTL32_wSubclass);
216 /* create local pattern brush */
217 COMCTL32_hPattern55AABitmap = CreateBitmap (8, 8, 1, 1, wPattern55AA);
218 COMCTL32_hPattern55AABrush = CreatePatternBrush (COMCTL32_hPattern55AABitmap);
220 /* Get all the colors at DLL load */
221 COMCTL32_RefreshSysColors();
223 /* like comctl32 5.82+ register all the common control classes */
224 ANIMATE_Register ();
225 COMBOEX_Register ();
226 DATETIME_Register ();
227 FLATSB_Register ();
228 HEADER_Register ();
229 HOTKEY_Register ();
230 IPADDRESS_Register ();
231 LISTVIEW_Register ();
232 MONTHCAL_Register ();
233 NATIVEFONT_Register ();
234 PAGER_Register ();
235 PROGRESS_Register ();
236 REBAR_Register ();
237 STATUS_Register ();
238 SYSLINK_Register ();
239 TAB_Register ();
240 TOOLBAR_Register ();
241 TOOLTIPS_Register ();
242 TRACKBAR_Register ();
243 TREEVIEW_Register ();
244 UPDOWN_Register ();
246 /* subclass user32 controls */
247 THEMING_Initialize ();
248 break;
250 case DLL_PROCESS_DETACH:
251 /* clean up subclassing */
252 THEMING_Uninitialize();
254 /* unregister all common control classes */
255 ANIMATE_Unregister ();
256 COMBOEX_Unregister ();
257 DATETIME_Unregister ();
258 FLATSB_Unregister ();
259 HEADER_Unregister ();
260 HOTKEY_Unregister ();
261 IPADDRESS_Unregister ();
262 LISTVIEW_Unregister ();
263 MONTHCAL_Unregister ();
264 NATIVEFONT_Unregister ();
265 PAGER_Unregister ();
266 PROGRESS_Unregister ();
267 REBAR_Unregister ();
268 STATUS_Unregister ();
269 SYSLINK_Unregister ();
270 TAB_Unregister ();
271 TOOLBAR_Unregister ();
272 TOOLTIPS_Unregister ();
273 TRACKBAR_Unregister ();
274 TREEVIEW_Unregister ();
275 UPDOWN_Unregister ();
277 /* delete local pattern brush */
278 DeleteObject (COMCTL32_hPattern55AABrush);
279 COMCTL32_hPattern55AABrush = NULL;
280 DeleteObject (COMCTL32_hPattern55AABitmap);
281 COMCTL32_hPattern55AABitmap = NULL;
283 /* delete global subclassing atom */
284 GlobalDeleteAtom (LOWORD(COMCTL32_wSubclass));
285 TRACE("Subclassing atom deleted: %p\n", COMCTL32_wSubclass);
286 COMCTL32_wSubclass = NULL;
287 break;
290 return TRUE;
294 /***********************************************************************
295 * MenuHelp [COMCTL32.2]
297 * Handles the setting of status bar help messages when the user
298 * selects menu items.
300 * PARAMS
301 * uMsg [I] message (WM_MENUSELECT) (see NOTES)
302 * wParam [I] wParam of the message uMsg
303 * lParam [I] lParam of the message uMsg
304 * hMainMenu [I] handle to the application's main menu
305 * hInst [I] handle to the module that contains string resources
306 * hwndStatus [I] handle to the status bar window
307 * lpwIDs [I] pointer to an array of integers (see NOTES)
309 * RETURNS
310 * No return value
312 * NOTES
313 * The official documentation is incomplete!
314 * This is the correct documentation:
316 * uMsg:
317 * MenuHelp() does NOT handle WM_COMMAND messages! It only handles
318 * WM_MENUSELECT messages.
320 * lpwIDs:
321 * (will be written ...)
324 VOID WINAPI
325 MenuHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu,
326 HINSTANCE hInst, HWND hwndStatus, UINT* lpwIDs)
328 UINT uMenuID = 0;
330 if (!IsWindow (hwndStatus))
331 return;
333 switch (uMsg) {
334 case WM_MENUSELECT:
335 TRACE("WM_MENUSELECT wParam=0x%lX lParam=0x%lX\n",
336 wParam, lParam);
338 if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {
339 /* menu was closed */
340 TRACE("menu was closed!\n");
341 SendMessageW (hwndStatus, SB_SIMPLE, FALSE, 0);
343 else {
344 /* menu item was selected */
345 if (HIWORD(wParam) & MF_POPUP)
346 uMenuID = *(lpwIDs+1);
347 else
348 uMenuID = (UINT)LOWORD(wParam);
349 TRACE("uMenuID = %u\n", uMenuID);
351 if (uMenuID) {
352 WCHAR szText[256];
354 if (!LoadStringW (hInst, uMenuID, szText, sizeof(szText)/sizeof(szText[0])))
355 szText[0] = '\0';
357 SendMessageW (hwndStatus, SB_SETTEXTW,
358 255 | SBT_NOBORDERS, (LPARAM)szText);
359 SendMessageW (hwndStatus, SB_SIMPLE, TRUE, 0);
362 break;
364 case WM_COMMAND :
365 TRACE("WM_COMMAND wParam=0x%lX lParam=0x%lX\n",
366 wParam, lParam);
367 /* WM_COMMAND is not invalid since it is documented
368 * in the windows api reference. So don't output
369 * any FIXME for WM_COMMAND
371 WARN("We don't care about the WM_COMMAND\n");
372 break;
374 default:
375 FIXME("Invalid Message 0x%x!\n", uMsg);
376 break;
381 /***********************************************************************
382 * ShowHideMenuCtl [COMCTL32.3]
384 * Shows or hides controls and updates the corresponding menu item.
386 * PARAMS
387 * hwnd [I] handle to the client window.
388 * uFlags [I] menu command id.
389 * lpInfo [I] pointer to an array of integers. (See NOTES.)
391 * RETURNS
392 * Success: TRUE
393 * Failure: FALSE
395 * NOTES
396 * The official documentation is incomplete!
397 * This is the correct documentation:
399 * hwnd
400 * Handle to the window that contains the menu and controls.
402 * uFlags
403 * Identifier of the menu item to receive or lose a check mark.
405 * lpInfo
406 * The array of integers contains pairs of values. BOTH values of
407 * the first pair must be the handles to the application's main menu.
408 * Each subsequent pair consists of a menu id and control id.
411 BOOL WINAPI
412 ShowHideMenuCtl (HWND hwnd, UINT_PTR uFlags, LPINT lpInfo)
414 LPINT lpMenuId;
416 TRACE("%p, %lx, %p\n", hwnd, uFlags, lpInfo);
418 if (lpInfo == NULL)
419 return FALSE;
421 if (!(lpInfo[0]) || !(lpInfo[1]))
422 return FALSE;
424 /* search for control */
425 lpMenuId = &lpInfo[2];
426 while (*lpMenuId != uFlags)
427 lpMenuId += 2;
429 if (GetMenuState ((HMENU)(DWORD_PTR)lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) {
430 /* uncheck menu item */
431 CheckMenuItem ((HMENU)(DWORD_PTR)lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_UNCHECKED);
433 /* hide control */
434 lpMenuId++;
435 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
436 SWP_HIDEWINDOW);
438 else {
439 /* check menu item */
440 CheckMenuItem ((HMENU)(DWORD_PTR)lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_CHECKED);
442 /* show control */
443 lpMenuId++;
444 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
445 SWP_SHOWWINDOW);
448 return TRUE;
452 /***********************************************************************
453 * GetEffectiveClientRect [COMCTL32.4]
455 * Calculates the coordinates of a rectangle in the client area.
457 * PARAMS
458 * hwnd [I] handle to the client window.
459 * lpRect [O] pointer to the rectangle of the client window
460 * lpInfo [I] pointer to an array of integers (see NOTES)
462 * RETURNS
463 * No return value.
465 * NOTES
466 * The official documentation is incomplete!
467 * This is the correct documentation:
469 * lpInfo
470 * (will be written ...)
473 VOID WINAPI
474 GetEffectiveClientRect (HWND hwnd, LPRECT lpRect, const INT *lpInfo)
476 RECT rcCtrl;
477 const INT *lpRun;
478 HWND hwndCtrl;
480 TRACE("(%p %p %p)\n",
481 hwnd, lpRect, lpInfo);
483 GetClientRect (hwnd, lpRect);
484 lpRun = lpInfo;
486 do {
487 lpRun += 2;
488 if (*lpRun == 0)
489 return;
490 lpRun++;
491 hwndCtrl = GetDlgItem (hwnd, *lpRun);
492 if (GetWindowLongW (hwndCtrl, GWL_STYLE) & WS_VISIBLE) {
493 TRACE("control id 0x%x\n", *lpRun);
494 GetWindowRect (hwndCtrl, &rcCtrl);
495 MapWindowPoints (NULL, hwnd, (LPPOINT)&rcCtrl, 2);
496 SubtractRect (lpRect, lpRect, &rcCtrl);
498 lpRun++;
499 } while (*lpRun);
503 /***********************************************************************
504 * DrawStatusTextW [COMCTL32.@]
506 * Draws text with borders, like in a status bar.
508 * PARAMS
509 * hdc [I] handle to the window's display context
510 * lprc [I] pointer to a rectangle
511 * text [I] pointer to the text
512 * style [I] drawing style
514 * RETURNS
515 * No return value.
517 * NOTES
518 * The style variable can have one of the following values:
519 * (will be written ...)
522 void WINAPI DrawStatusTextW (HDC hdc, LPCRECT lprc, LPCWSTR text, UINT style)
524 RECT r = *lprc;
525 UINT border = BDR_SUNKENOUTER;
527 if (style & SBT_POPOUT)
528 border = BDR_RAISEDOUTER;
529 else if (style & SBT_NOBORDERS)
530 border = 0;
532 DrawEdge (hdc, &r, border, BF_RECT|BF_ADJUST);
534 /* now draw text */
535 if (text) {
536 int oldbkmode = SetBkMode (hdc, TRANSPARENT);
537 UINT align = DT_LEFT;
538 if (*text == '\t') {
539 text++;
540 align = DT_CENTER;
541 if (*text == '\t') {
542 text++;
543 align = DT_RIGHT;
546 r.left += 3;
547 if (style & SBT_RTLREADING)
548 FIXME("Unsupported RTL style!\n");
549 DrawTextW (hdc, text, -1, &r, align|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX);
550 SetBkMode(hdc, oldbkmode);
555 /***********************************************************************
556 * DrawStatusText [COMCTL32.@]
557 * DrawStatusTextA [COMCTL32.5]
559 * Draws text with borders, like in a status bar.
561 * PARAMS
562 * hdc [I] handle to the window's display context
563 * lprc [I] pointer to a rectangle
564 * text [I] pointer to the text
565 * style [I] drawing style
567 * RETURNS
568 * No return value.
571 void WINAPI DrawStatusTextA (HDC hdc, LPCRECT lprc, LPCSTR text, UINT style)
573 INT len;
574 LPWSTR textW = NULL;
576 if ( text ) {
577 if ( (len = MultiByteToWideChar( CP_ACP, 0, text, -1, NULL, 0 )) ) {
578 if ( (textW = Alloc( len * sizeof(WCHAR) )) )
579 MultiByteToWideChar( CP_ACP, 0, text, -1, textW, len );
582 DrawStatusTextW( hdc, lprc, textW, style );
583 Free( textW );
587 /***********************************************************************
588 * CreateStatusWindow [COMCTL32.@]
589 * CreateStatusWindowA [COMCTL32.6]
591 * Creates a status bar
593 * PARAMS
594 * style [I] window style
595 * text [I] pointer to the window text
596 * parent [I] handle to the parent window
597 * wid [I] control id of the status bar
599 * RETURNS
600 * Success: handle to the status window
601 * Failure: 0
604 HWND WINAPI
605 CreateStatusWindowA (LONG style, LPCSTR text, HWND parent, UINT wid)
607 return CreateWindowA(STATUSCLASSNAMEA, text, style,
608 CW_USEDEFAULT, CW_USEDEFAULT,
609 CW_USEDEFAULT, CW_USEDEFAULT,
610 parent, (HMENU)(DWORD_PTR)wid, 0, 0);
614 /***********************************************************************
615 * CreateStatusWindowW [COMCTL32.@]
617 * Creates a status bar control
619 * PARAMS
620 * style [I] window style
621 * text [I] pointer to the window text
622 * parent [I] handle to the parent window
623 * wid [I] control id of the status bar
625 * RETURNS
626 * Success: handle to the status window
627 * Failure: 0
630 HWND WINAPI
631 CreateStatusWindowW (LONG style, LPCWSTR text, HWND parent, UINT wid)
633 return CreateWindowW(STATUSCLASSNAMEW, text, style,
634 CW_USEDEFAULT, CW_USEDEFAULT,
635 CW_USEDEFAULT, CW_USEDEFAULT,
636 parent, (HMENU)(DWORD_PTR)wid, 0, 0);
640 /***********************************************************************
641 * CreateUpDownControl [COMCTL32.16]
643 * Creates an up-down control
645 * PARAMS
646 * style [I] window styles
647 * x [I] horizontal position of the control
648 * y [I] vertical position of the control
649 * cx [I] with of the control
650 * cy [I] height of the control
651 * parent [I] handle to the parent window
652 * id [I] the control's identifier
653 * inst [I] handle to the application's module instance
654 * buddy [I] handle to the buddy window, can be NULL
655 * maxVal [I] upper limit of the control
656 * minVal [I] lower limit of the control
657 * curVal [I] current value of the control
659 * RETURNS
660 * Success: handle to the updown control
661 * Failure: 0
664 HWND WINAPI
665 CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
666 HWND parent, INT id, HINSTANCE inst,
667 HWND buddy, INT maxVal, INT minVal, INT curVal)
669 HWND hUD =
670 CreateWindowW (UPDOWN_CLASSW, 0, style, x, y, cx, cy,
671 parent, (HMENU)(DWORD_PTR)id, inst, 0);
672 if (hUD) {
673 SendMessageW (hUD, UDM_SETBUDDY, (WPARAM)buddy, 0);
674 SendMessageW (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));
675 SendMessageW (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));
678 return hUD;
682 /***********************************************************************
683 * InitCommonControls [COMCTL32.17]
685 * Registers the common controls.
687 * PARAMS
688 * No parameters.
690 * RETURNS
691 * No return values.
693 * NOTES
694 * This function is just a dummy - all the controls are registered at
695 * the DLL's initialization. See InitCommonContolsEx for details.
698 VOID WINAPI
699 InitCommonControls (void)
704 /***********************************************************************
705 * InitCommonControlsEx [COMCTL32.@]
707 * Registers the common controls.
709 * PARAMS
710 * lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
712 * RETURNS
713 * Success: TRUE
714 * Failure: FALSE
716 * NOTES
717 * Probably all versions of comctl32 initializes the Win95 controls in DllMain
718 * during DLL initialization. Starting from comctl32 v5.82 all the controls
719 * are initialized there. We follow this behaviour and this function is just
720 * a dummy.
722 * Note: when writing programs under Windows, if you don't call any function
723 * from comctl32 the linker may not link this DLL. If InitCommonControlsEx
724 * was the only comctl32 function you were calling and you remove it you may
725 * have a false impression that InitCommonControlsEx actually did something.
728 BOOL WINAPI
729 InitCommonControlsEx (const INITCOMMONCONTROLSEX *lpInitCtrls)
731 if (!lpInitCtrls || lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
732 return FALSE;
734 TRACE("(0x%08x)\n", lpInitCtrls->dwICC);
735 return TRUE;
739 /***********************************************************************
740 * CreateToolbarEx [COMCTL32.@]
742 * Creates a toolbar window.
744 * PARAMS
745 * hwnd
746 * style
747 * wID
748 * nBitmaps
749 * hBMInst
750 * wBMID
751 * lpButtons
752 * iNumButtons
753 * dxButton
754 * dyButton
755 * dxBitmap
756 * dyBitmap
757 * uStructSize
759 * RETURNS
760 * Success: handle to the tool bar control
761 * Failure: 0
764 HWND WINAPI
765 CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
766 HINSTANCE hBMInst, UINT wBMID, LPCTBBUTTON lpButtons,
767 INT iNumButtons, INT dxButton, INT dyButton,
768 INT dxBitmap, INT dyBitmap, UINT uStructSize)
770 HWND hwndTB;
772 hwndTB =
773 CreateWindowExW(0, TOOLBARCLASSNAMEW, NULL, style|WS_CHILD, 0,0,100,30,
774 hwnd, (HMENU)(DWORD_PTR)wID, COMCTL32_hModule, NULL);
775 if(hwndTB) {
776 TBADDBITMAP tbab;
778 SendMessageW (hwndTB, TB_BUTTONSTRUCTSIZE, (WPARAM)uStructSize, 0);
780 /* set bitmap and button size */
781 /*If CreateToolbarEx receives 0, windows sets default values*/
782 if (dxBitmap < 0)
783 dxBitmap = 16;
784 if (dyBitmap < 0)
785 dyBitmap = 16;
786 if (dxBitmap == 0 || dyBitmap == 0)
787 dxBitmap = dyBitmap = 16;
788 SendMessageW(hwndTB, TB_SETBITMAPSIZE, 0, MAKELPARAM(dxBitmap, dyBitmap));
790 if (dxButton < 0)
791 dxButton = dxBitmap;
792 if (dyButton < 0)
793 dyButton = dyBitmap;
794 /* TB_SETBUTTONSIZE -> TB_SETBITMAPSIZE bug introduced for Windows compatibility */
795 if (dxButton != 0 && dyButton != 0)
796 SendMessageW(hwndTB, TB_SETBITMAPSIZE, 0, MAKELPARAM(dxButton, dyButton));
799 /* add bitmaps */
800 if (nBitmaps > 0 || hBMInst == HINST_COMMCTRL)
802 tbab.hInst = hBMInst;
803 tbab.nID = wBMID;
805 SendMessageW (hwndTB, TB_ADDBITMAP, (WPARAM)nBitmaps, (LPARAM)&tbab);
807 /* add buttons */
808 if(iNumButtons > 0)
809 SendMessageW (hwndTB, TB_ADDBUTTONSW,
810 (WPARAM)iNumButtons, (LPARAM)lpButtons);
813 return hwndTB;
817 /***********************************************************************
818 * CreateMappedBitmap [COMCTL32.8]
820 * Loads a bitmap resource using a colour map.
822 * PARAMS
823 * hInstance [I] Handle to the module containing the bitmap.
824 * idBitmap [I] The bitmap resource ID.
825 * wFlags [I] CMB_MASKED for using bitmap as a mask or 0 for normal.
826 * lpColorMap [I] Colour information needed for the bitmap or NULL (uses system colours).
827 * iNumMaps [I] Number of COLORMAP's pointed to by lpColorMap.
829 * RETURNS
830 * Success: handle to the new bitmap
831 * Failure: 0
834 HBITMAP WINAPI
835 CreateMappedBitmap (HINSTANCE hInstance, INT_PTR idBitmap, UINT wFlags,
836 LPCOLORMAP lpColorMap, INT iNumMaps)
838 HGLOBAL hglb;
839 HRSRC hRsrc;
840 const BITMAPINFOHEADER *lpBitmap;
841 LPBITMAPINFOHEADER lpBitmapInfo;
842 UINT nSize, nColorTableSize, iColor;
843 RGBQUAD *pColorTable;
844 INT i, iMaps, nWidth, nHeight;
845 HDC hdcScreen;
846 HBITMAP hbm;
847 LPCOLORMAP sysColorMap;
848 COLORREF cRef;
849 COLORMAP internalColorMap[4] =
850 {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
852 /* initialize pointer to colortable and default color table */
853 if (lpColorMap) {
854 iMaps = iNumMaps;
855 sysColorMap = lpColorMap;
857 else {
858 internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT);
859 internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW);
860 internalColorMap[2].to = GetSysColor (COLOR_BTNFACE);
861 internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT);
862 iMaps = 4;
863 sysColorMap = (LPCOLORMAP)internalColorMap;
866 hRsrc = FindResourceW (hInstance, (LPWSTR)idBitmap, (LPWSTR)RT_BITMAP);
867 if (hRsrc == 0)
868 return 0;
869 hglb = LoadResource (hInstance, hRsrc);
870 if (hglb == 0)
871 return 0;
872 lpBitmap = (LPBITMAPINFOHEADER)LockResource (hglb);
873 if (lpBitmap == NULL)
874 return 0;
876 if (lpBitmap->biSize >= sizeof(BITMAPINFOHEADER) && lpBitmap->biClrUsed)
877 nColorTableSize = lpBitmap->biClrUsed;
878 else if (lpBitmap->biBitCount <= 8)
879 nColorTableSize = (1 << lpBitmap->biBitCount);
880 else
881 nColorTableSize = 0;
882 nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
883 lpBitmapInfo = (LPBITMAPINFOHEADER)GlobalAlloc (GMEM_FIXED, nSize);
884 if (lpBitmapInfo == NULL)
885 return 0;
886 RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);
888 pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo) + lpBitmapInfo->biSize);
890 for (iColor = 0; iColor < nColorTableSize; iColor++) {
891 for (i = 0; i < iMaps; i++) {
892 cRef = RGB(pColorTable[iColor].rgbRed,
893 pColorTable[iColor].rgbGreen,
894 pColorTable[iColor].rgbBlue);
895 if ( cRef == sysColorMap[i].from) {
896 #if 0
897 if (wFlags & CBS_MASKED) {
898 if (sysColorMap[i].to != COLOR_BTNTEXT)
899 pColorTable[iColor] = RGB(255, 255, 255);
901 else
902 #endif
903 pColorTable[iColor].rgbBlue = GetBValue(sysColorMap[i].to);
904 pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);
905 pColorTable[iColor].rgbRed = GetRValue(sysColorMap[i].to);
906 break;
910 nWidth = lpBitmapInfo->biWidth;
911 nHeight = lpBitmapInfo->biHeight;
912 hdcScreen = GetDC (NULL);
913 hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
914 if (hbm) {
915 HDC hdcDst = CreateCompatibleDC (hdcScreen);
916 HBITMAP hbmOld = SelectObject (hdcDst, hbm);
917 const BYTE *lpBits = (const BYTE *)(lpBitmap + 1);
918 lpBits += nColorTableSize * sizeof(RGBQUAD);
919 StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
920 lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
921 SRCCOPY);
922 SelectObject (hdcDst, hbmOld);
923 DeleteDC (hdcDst);
925 ReleaseDC (NULL, hdcScreen);
926 GlobalFree ((HGLOBAL)lpBitmapInfo);
927 FreeResource (hglb);
929 return hbm;
933 /***********************************************************************
934 * CreateToolbar [COMCTL32.7]
936 * Creates a toolbar control.
938 * PARAMS
939 * hwnd
940 * style
941 * wID
942 * nBitmaps
943 * hBMInst
944 * wBMID
945 * lpButtons
946 * iNumButtons
948 * RETURNS
949 * Success: handle to the tool bar control
950 * Failure: 0
952 * NOTES
953 * Do not use this functions anymore. Use CreateToolbarEx instead.
956 HWND WINAPI
957 CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
958 HINSTANCE hBMInst, UINT wBMID,
959 LPCTBBUTTON lpButtons,INT iNumButtons)
961 return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
962 hBMInst, wBMID, lpButtons,
963 iNumButtons, 0, 0, 0, 0, CCSIZEOF_STRUCT(TBBUTTON, dwData));
967 /***********************************************************************
968 * DllGetVersion [COMCTL32.@]
970 * Retrieves version information of the 'COMCTL32.DLL'
972 * PARAMS
973 * pdvi [O] pointer to version information structure.
975 * RETURNS
976 * Success: S_OK
977 * Failure: E_INVALIDARG
979 * NOTES
980 * Returns version of a comctl32.dll from IE4.01 SP1.
983 HRESULT WINAPI DllGetVersion (DLLVERSIONINFO *pdvi)
985 if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
986 WARN("wrong DLLVERSIONINFO size from app\n");
987 return E_INVALIDARG;
990 pdvi->dwMajorVersion = COMCTL32_VERSION;
991 pdvi->dwMinorVersion = COMCTL32_VERSION_MINOR;
992 pdvi->dwBuildNumber = 2919;
993 pdvi->dwPlatformID = 6304;
995 TRACE("%u.%u.%u.%u\n",
996 pdvi->dwMajorVersion, pdvi->dwMinorVersion,
997 pdvi->dwBuildNumber, pdvi->dwPlatformID);
999 return S_OK;
1002 /***********************************************************************
1003 * DllInstall (COMCTL32.@)
1005 * Installs the ComCtl32 DLL.
1007 * RETURNS
1008 * Success: S_OK
1009 * Failure: A HRESULT error
1011 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
1013 TRACE("(%u, %s): stub\n", bInstall, debugstr_w(cmdline));
1014 if (!create_manifest( bInstall )) return HRESULT_FROM_WIN32(GetLastError());
1015 return S_OK;
1018 /***********************************************************************
1019 * _TrackMouseEvent [COMCTL32.@]
1021 * Requests notification of mouse events
1023 * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
1024 * to the hwnd specified in the ptme structure. After the event message
1025 * is posted to the hwnd, the entry in the queue is removed.
1027 * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
1028 * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
1029 * immediately and the TME_LEAVE flag being ignored.
1031 * PARAMS
1032 * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
1034 * RETURNS
1035 * Success: non-zero
1036 * Failure: zero
1038 * IMPLEMENTATION moved to USER32.TrackMouseEvent
1042 BOOL WINAPI
1043 _TrackMouseEvent (TRACKMOUSEEVENT *ptme)
1045 return TrackMouseEvent (ptme);
1048 /*************************************************************************
1049 * GetMUILanguage [COMCTL32.@]
1051 * Returns the user interface language in use by the current process.
1053 * RETURNS
1054 * Language ID in use by the current process.
1056 LANGID WINAPI GetMUILanguage (VOID)
1058 return COMCTL32_uiLang;
1062 /*************************************************************************
1063 * InitMUILanguage [COMCTL32.@]
1065 * Sets the user interface language to be used by the current process.
1067 * RETURNS
1068 * Nothing.
1070 VOID WINAPI InitMUILanguage (LANGID uiLang)
1072 COMCTL32_uiLang = uiLang;
1076 /***********************************************************************
1077 * SetWindowSubclass [COMCTL32.410]
1079 * Starts a window subclass
1081 * PARAMS
1082 * hWnd [in] handle to window subclass.
1083 * pfnSubclass [in] Pointer to new window procedure.
1084 * uIDSubclass [in] Unique identifier of sublass together with pfnSubclass.
1085 * dwRef [in] Reference data to pass to window procedure.
1087 * RETURNS
1088 * Success: non-zero
1089 * Failure: zero
1091 * BUGS
1092 * If an application manually subclasses a window after subclassing it with
1093 * this API and then with this API again, then none of the previous
1094 * subclasses get called or the original window procedure.
1097 BOOL WINAPI SetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
1098 UINT_PTR uIDSubclass, DWORD_PTR dwRef)
1100 LPSUBCLASS_INFO stack;
1101 LPSUBCLASSPROCS proc;
1103 TRACE ("(%p, %p, %lx, %lx)\n", hWnd, pfnSubclass, uIDSubclass, dwRef);
1105 /* Since the window procedure that we set here has two additional arguments,
1106 * we can't simply set it as the new window procedure of the window. So we
1107 * set our own window procedure and then calculate the other two arguments
1108 * from there. */
1110 /* See if we have been called for this window */
1111 stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
1112 if (!stack) {
1113 /* allocate stack */
1114 stack = Alloc (sizeof(SUBCLASS_INFO));
1115 if (!stack) {
1116 ERR ("Failed to allocate our Subclassing stack\n");
1117 return FALSE;
1119 SetPropW (hWnd, COMCTL32_wSubclass, (HANDLE)stack);
1121 /* set window procedure to our own and save the current one */
1122 if (IsWindowUnicode (hWnd))
1123 stack->origproc = (WNDPROC)SetWindowLongPtrW (hWnd, GWLP_WNDPROC,
1124 (DWORD_PTR)COMCTL32_SubclassProc);
1125 else
1126 stack->origproc = (WNDPROC)SetWindowLongPtrA (hWnd, GWLP_WNDPROC,
1127 (DWORD_PTR)COMCTL32_SubclassProc);
1129 else {
1130 /* Check to see if we have called this function with the same uIDSubClass
1131 * and pfnSubclass */
1132 proc = stack->SubclassProcs;
1133 while (proc) {
1134 if ((proc->id == uIDSubclass) &&
1135 (proc->subproc == pfnSubclass)) {
1136 proc->ref = dwRef;
1137 return TRUE;
1139 proc = proc->next;
1143 proc = Alloc(sizeof(SUBCLASSPROCS));
1144 if (!proc) {
1145 ERR ("Failed to allocate subclass entry in stack\n");
1146 if (IsWindowUnicode (hWnd))
1147 SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1148 else
1149 SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1150 Free (stack);
1151 RemovePropW( hWnd, COMCTL32_wSubclass );
1152 return FALSE;
1155 proc->subproc = pfnSubclass;
1156 proc->ref = dwRef;
1157 proc->id = uIDSubclass;
1158 proc->next = stack->SubclassProcs;
1159 stack->SubclassProcs = proc;
1161 return TRUE;
1165 /***********************************************************************
1166 * GetWindowSubclass [COMCTL32.411]
1168 * Gets the Reference data from a subclass.
1170 * PARAMS
1171 * hWnd [in] Handle to window which were subclassing
1172 * pfnSubclass [in] Pointer to the subclass procedure
1173 * uID [in] Unique indentifier of the subclassing procedure
1174 * pdwRef [out] Pointer to the reference data
1176 * RETURNS
1177 * Success: Non-zero
1178 * Failure: 0
1181 BOOL WINAPI GetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
1182 UINT_PTR uID, DWORD_PTR *pdwRef)
1184 const SUBCLASS_INFO *stack;
1185 const SUBCLASSPROCS *proc;
1187 TRACE ("(%p, %p, %lx, %p)\n", hWnd, pfnSubclass, uID, pdwRef);
1189 /* See if we have been called for this window */
1190 stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
1191 if (!stack)
1192 return FALSE;
1194 proc = stack->SubclassProcs;
1195 while (proc) {
1196 if ((proc->id == uID) &&
1197 (proc->subproc == pfnSubclass)) {
1198 *pdwRef = proc->ref;
1199 return TRUE;
1201 proc = proc->next;
1204 return FALSE;
1208 /***********************************************************************
1209 * RemoveWindowSubclass [COMCTL32.412]
1211 * Removes a window subclass.
1213 * PARAMS
1214 * hWnd [in] Handle to the window were subclassing
1215 * pfnSubclass [in] Pointer to the subclass procedure
1216 * uID [in] Unique identifier of this subclass
1218 * RETURNS
1219 * Success: non-zero
1220 * Failure: zero
1223 BOOL WINAPI RemoveWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR uID)
1225 LPSUBCLASS_INFO stack;
1226 LPSUBCLASSPROCS prevproc = NULL;
1227 LPSUBCLASSPROCS proc;
1228 BOOL ret = FALSE;
1230 TRACE ("(%p, %p, %lx)\n", hWnd, pfnSubclass, uID);
1232 /* Find the Subclass to remove */
1233 stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
1234 if (!stack)
1235 return FALSE;
1237 proc = stack->SubclassProcs;
1238 while (proc) {
1239 if ((proc->id == uID) &&
1240 (proc->subproc == pfnSubclass)) {
1242 if (!prevproc)
1243 stack->SubclassProcs = proc->next;
1244 else
1245 prevproc->next = proc->next;
1247 if (stack->stackpos == proc)
1248 stack->stackpos = stack->stackpos->next;
1250 Free (proc);
1251 ret = TRUE;
1252 break;
1254 prevproc = proc;
1255 proc = proc->next;
1258 if (!stack->SubclassProcs && !stack->running) {
1259 TRACE("Last Subclass removed, cleaning up\n");
1260 /* clean up our heap and reset the original window procedure */
1261 if (IsWindowUnicode (hWnd))
1262 SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1263 else
1264 SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1265 Free (stack);
1266 RemovePropW( hWnd, COMCTL32_wSubclass );
1269 return ret;
1272 /***********************************************************************
1273 * COMCTL32_SubclassProc (internal)
1275 * Window procedure for all subclassed windows.
1276 * Saves the current subclassing stack position to support nested messages
1278 LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1280 LPSUBCLASS_INFO stack;
1281 LPSUBCLASSPROCS proc;
1282 LRESULT ret;
1284 TRACE ("(%p, 0x%08x, 0x%08lx, 0x%08lx)\n", hWnd, uMsg, wParam, lParam);
1286 stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
1287 if (!stack) {
1288 ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
1289 return 0;
1292 /* Save our old stackpos to properly handle nested messages */
1293 proc = stack->stackpos;
1294 stack->stackpos = stack->SubclassProcs;
1295 stack->running++;
1296 ret = DefSubclassProc(hWnd, uMsg, wParam, lParam);
1297 stack->running--;
1298 stack->stackpos = proc;
1300 if (!stack->SubclassProcs && !stack->running) {
1301 TRACE("Last Subclass removed, cleaning up\n");
1302 /* clean up our heap and reset the original window procedure */
1303 if (IsWindowUnicode (hWnd))
1304 SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1305 else
1306 SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1307 Free (stack);
1308 RemovePropW( hWnd, COMCTL32_wSubclass );
1310 return ret;
1313 /***********************************************************************
1314 * DefSubclassProc [COMCTL32.413]
1316 * Calls the next window procedure (ie. the one before this subclass)
1318 * PARAMS
1319 * hWnd [in] The window that we're subclassing
1320 * uMsg [in] Message
1321 * wParam [in] WPARAM
1322 * lParam [in] LPARAM
1324 * RETURNS
1325 * Success: non-zero
1326 * Failure: zero
1329 LRESULT WINAPI DefSubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1331 LPSUBCLASS_INFO stack;
1332 LRESULT ret;
1334 TRACE ("(%p, 0x%08x, 0x%08lx, 0x%08lx)\n", hWnd, uMsg, wParam, lParam);
1336 /* retrieve our little stack from the Properties */
1337 stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
1338 if (!stack) {
1339 ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
1340 return 0;
1343 /* If we are at the end of stack then we have to call the original
1344 * window procedure */
1345 if (!stack->stackpos) {
1346 if (IsWindowUnicode (hWnd))
1347 ret = CallWindowProcW (stack->origproc, hWnd, uMsg, wParam, lParam);
1348 else
1349 ret = CallWindowProcA (stack->origproc, hWnd, uMsg, wParam, lParam);
1350 } else {
1351 const SUBCLASSPROCS *proc = stack->stackpos;
1352 stack->stackpos = stack->stackpos->next;
1353 /* call the Subclass procedure from the stack */
1354 ret = proc->subproc (hWnd, uMsg, wParam, lParam,
1355 proc->id, proc->ref);
1358 return ret;
1362 /***********************************************************************
1363 * COMCTL32_CreateToolTip [NOT AN API]
1365 * Creates a tooltip for the control specified in hwnd and does all
1366 * necessary setup and notifications.
1368 * PARAMS
1369 * hwndOwner [I] Handle to the window that will own the tool tip.
1371 * RETURNS
1372 * Success: Handle of tool tip window.
1373 * Failure: NULL
1376 HWND
1377 COMCTL32_CreateToolTip(HWND hwndOwner)
1379 HWND hwndToolTip;
1381 hwndToolTip = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, WS_POPUP,
1382 CW_USEDEFAULT, CW_USEDEFAULT,
1383 CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner,
1384 0, 0, 0);
1386 /* Send NM_TOOLTIPSCREATED notification */
1387 if (hwndToolTip)
1389 NMTOOLTIPSCREATED nmttc;
1390 /* true owner can be different if hwndOwner is a child window */
1391 HWND hwndTrueOwner = GetWindow(hwndToolTip, GW_OWNER);
1392 nmttc.hdr.hwndFrom = hwndTrueOwner;
1393 nmttc.hdr.idFrom = GetWindowLongPtrW(hwndTrueOwner, GWLP_ID);
1394 nmttc.hdr.code = NM_TOOLTIPSCREATED;
1395 nmttc.hwndToolTips = hwndToolTip;
1397 SendMessageW(GetParent(hwndTrueOwner), WM_NOTIFY,
1398 (WPARAM)GetWindowLongPtrW(hwndTrueOwner, GWLP_ID),
1399 (LPARAM)&nmttc);
1402 return hwndToolTip;
1406 /***********************************************************************
1407 * COMCTL32_RefreshSysColors [NOT AN API]
1409 * Invoked on any control recognizing a WM_SYSCOLORCHANGE message to
1410 * refresh the color values in the color structure
1412 * PARAMS
1413 * none
1415 * RETURNS
1416 * none
1419 VOID
1420 COMCTL32_RefreshSysColors(void)
1422 comctl32_color.clrBtnHighlight = GetSysColor (COLOR_BTNHIGHLIGHT);
1423 comctl32_color.clrBtnShadow = GetSysColor (COLOR_BTNSHADOW);
1424 comctl32_color.clrBtnText = GetSysColor (COLOR_BTNTEXT);
1425 comctl32_color.clrBtnFace = GetSysColor (COLOR_BTNFACE);
1426 comctl32_color.clrHighlight = GetSysColor (COLOR_HIGHLIGHT);
1427 comctl32_color.clrHighlightText = GetSysColor (COLOR_HIGHLIGHTTEXT);
1428 comctl32_color.clr3dHilight = GetSysColor (COLOR_3DHILIGHT);
1429 comctl32_color.clr3dShadow = GetSysColor (COLOR_3DSHADOW);
1430 comctl32_color.clr3dDkShadow = GetSysColor (COLOR_3DDKSHADOW);
1431 comctl32_color.clr3dFace = GetSysColor (COLOR_3DFACE);
1432 comctl32_color.clrWindow = GetSysColor (COLOR_WINDOW);
1433 comctl32_color.clrWindowText = GetSysColor (COLOR_WINDOWTEXT);
1434 comctl32_color.clrGrayText = GetSysColor (COLOR_GRAYTEXT);
1435 comctl32_color.clrActiveCaption = GetSysColor (COLOR_ACTIVECAPTION);
1436 comctl32_color.clrInfoBk = GetSysColor (COLOR_INFOBK);
1437 comctl32_color.clrInfoText = GetSysColor (COLOR_INFOTEXT);
1440 /***********************************************************************
1441 * COMCTL32_DrawInsertMark [NOT AN API]
1443 * Draws an insertion mark (which looks similar to an 'I').
1445 * PARAMS
1446 * hDC [I] Device context to draw onto.
1447 * lpRect [I] Co-ordinates of insertion mark.
1448 * clrInsertMark [I] Colour of the insertion mark.
1449 * bHorizontal [I] True if insert mark should be drawn horizontally,
1450 * vertical otherwise.
1452 * RETURNS
1453 * none
1455 * NOTES
1456 * Draws up to but not including the bottom co-ordinate when drawing
1457 * vertically or the right co-ordinate when horizontal.
1459 void COMCTL32_DrawInsertMark(HDC hDC, const RECT *lpRect, COLORREF clrInsertMark, BOOL bHorizontal)
1461 HPEN hPen = CreatePen(PS_SOLID, 1, clrInsertMark);
1462 HPEN hOldPen;
1463 static const DWORD adwPolyPoints[] = {4,4,4};
1464 LONG lCentre = (bHorizontal ?
1465 lpRect->top + (lpRect->bottom - lpRect->top)/2 :
1466 lpRect->left + (lpRect->right - lpRect->left)/2);
1467 LONG l1 = (bHorizontal ? lpRect->left : lpRect->top);
1468 LONG l2 = (bHorizontal ? lpRect->right : lpRect->bottom);
1469 const POINT aptInsertMark[] =
1471 /* top (V) or left (H) arrow */
1472 {lCentre , l1 + 2},
1473 {lCentre - 2, l1 },
1474 {lCentre + 3, l1 },
1475 {lCentre + 1, l1 + 2},
1476 /* middle line */
1477 {lCentre , l2 - 2},
1478 {lCentre , l1 - 1},
1479 {lCentre + 1, l1 - 1},
1480 {lCentre + 1, l2 - 2},
1481 /* bottom (V) or right (H) arrow */
1482 {lCentre , l2 - 3},
1483 {lCentre - 2, l2 - 1},
1484 {lCentre + 3, l2 - 1},
1485 {lCentre + 1, l2 - 3},
1487 hOldPen = SelectObject(hDC, hPen);
1488 PolyPolyline(hDC, aptInsertMark, adwPolyPoints, sizeof(adwPolyPoints)/sizeof(adwPolyPoints[0]));
1489 SelectObject(hDC, hOldPen);
1490 DeleteObject(hPen);
1493 /***********************************************************************
1494 * COMCTL32_EnsureBitmapSize [internal]
1496 * If needed, enlarge the bitmap so that the width is at least cxMinWidth and
1497 * the height is at least cyMinHeight. If the bitmap already has these
1498 * dimensions nothing changes.
1500 * PARAMS
1501 * hBitmap [I/O] Bitmap to modify. The handle may change
1502 * cxMinWidth [I] If the width of the bitmap is smaller, then it will
1503 * be enlarged to this value
1504 * cyMinHeight [I] If the height of the bitmap is smaller, then it will
1505 * be enlarged to this value
1506 * cyBackground [I] The color with which the new area will be filled
1508 * RETURNS
1509 * none
1511 void COMCTL32_EnsureBitmapSize(HBITMAP *pBitmap, int cxMinWidth, int cyMinHeight, COLORREF crBackground)
1513 int cxNew, cyNew;
1514 BITMAP bmp;
1515 HBITMAP hNewBitmap;
1516 HBITMAP hNewDCBitmap, hOldDCBitmap;
1517 HBRUSH hNewDCBrush;
1518 HDC hdcNew, hdcOld;
1520 if (!GetObjectW(*pBitmap, sizeof(BITMAP), &bmp))
1521 return;
1522 cxNew = (cxMinWidth > bmp.bmWidth ? cxMinWidth : bmp.bmWidth);
1523 cyNew = (cyMinHeight > bmp.bmHeight ? cyMinHeight : bmp.bmHeight);
1524 if (cxNew == bmp.bmWidth && cyNew == bmp.bmHeight)
1525 return;
1527 hdcNew = CreateCompatibleDC(NULL);
1528 hNewBitmap = CreateBitmap(cxNew, cyNew, bmp.bmPlanes, bmp.bmBitsPixel, NULL);
1529 hNewDCBitmap = SelectObject(hdcNew, hNewBitmap);
1530 hNewDCBrush = SelectObject(hdcNew, CreateSolidBrush(crBackground));
1532 hdcOld = CreateCompatibleDC(NULL);
1533 hOldDCBitmap = SelectObject(hdcOld, *pBitmap);
1535 BitBlt(hdcNew, 0, 0, bmp.bmWidth, bmp.bmHeight, hdcOld, 0, 0, SRCCOPY);
1536 if (bmp.bmWidth < cxMinWidth)
1537 PatBlt(hdcNew, bmp.bmWidth, 0, cxNew, bmp.bmHeight, PATCOPY);
1538 if (bmp.bmHeight < cyMinHeight)
1539 PatBlt(hdcNew, 0, bmp.bmHeight, bmp.bmWidth, cyNew, PATCOPY);
1540 if (bmp.bmWidth < cxMinWidth && bmp.bmHeight < cyMinHeight)
1541 PatBlt(hdcNew, bmp.bmWidth, bmp.bmHeight, cxNew, cyNew, PATCOPY);
1543 SelectObject(hdcNew, hNewDCBitmap);
1544 DeleteObject(SelectObject(hdcNew, hNewDCBrush));
1545 DeleteDC(hdcNew);
1546 SelectObject(hdcOld, hOldDCBitmap);
1547 DeleteDC(hdcOld);
1549 DeleteObject(*pBitmap);
1550 *pBitmap = hNewBitmap;
1551 return;
1554 /***********************************************************************
1555 * MirrorIcon [COMCTL32.414]
1557 * Mirrors an icon so that it will appear correctly on a mirrored DC.
1559 * PARAMS
1560 * phicon1 [I/O] Icon.
1561 * phicon2 [I/O] Icon.
1563 * RETURNS
1564 * Success: TRUE.
1565 * Failure: FALSE.
1567 BOOL WINAPI MirrorIcon(HICON *phicon1, HICON *phicon2)
1569 FIXME("(%p, %p): stub\n", phicon1, phicon2);
1570 return FALSE;
1573 static inline int IsDelimiter(WCHAR c)
1575 switch(c)
1577 case '/':
1578 case '\\':
1579 case '.':
1580 case ' ':
1581 return TRUE;
1583 return FALSE;
1586 static int CALLBACK PathWordBreakProc(LPCWSTR lpch, int ichCurrent, int cch, int code)
1588 if (code == WB_ISDELIMITER)
1589 return IsDelimiter(lpch[ichCurrent]);
1590 else
1592 int dir = (code == WB_LEFT) ? -1 : 1;
1593 for(; 0 <= ichCurrent && ichCurrent < cch; ichCurrent += dir)
1594 if (IsDelimiter(lpch[ichCurrent])) return ichCurrent;
1596 return ichCurrent;
1599 /***********************************************************************
1600 * SetPathWordBreakProc [COMCTL32.384]
1602 * Sets the word break procedure for an edit control to one that understands
1603 * paths so that the user can jump over directories.
1605 * PARAMS
1606 * hwnd [I] Handle to edit control.
1607 * bSet [I] If this is TRUE then the word break proc is set, otherwise it is removed.
1609 * RETURNS
1610 * Result from EM_SETWORDBREAKPROC message.
1612 LRESULT WINAPI SetPathWordBreakProc(HWND hwnd, BOOL bSet)
1614 return SendMessageW(hwnd, EM_SETWORDBREAKPROC, 0,
1615 (LPARAM)(bSet ? PathWordBreakProc : NULL));
1618 /***********************************************************************
1619 * DrawShadowText [COMCTL32.@]
1621 * Draw text with shadow.
1623 int WINAPI DrawShadowText(HDC hdc, LPCWSTR pszText, UINT cch, RECT *rect, DWORD dwFlags,
1624 COLORREF crText, COLORREF crShadow, int ixOffset, int iyOffset)
1626 FIXME("(%p, %s, %d, %p, %d, 0x%08x, 0x%08x, %d, %d): stub\n", hdc, debugstr_w(pszText), cch, rect, dwFlags,
1627 crText, crShadow, ixOffset, iyOffset);
1628 return DrawTextW(hdc, pszText, cch, rect, DT_LEFT);