push c22b4aa826b27f0c6bc5101b378e6e68716a85d9
[wine/hacks.git] / dlls / comctl32 / commctrl.c
blob949b62af75bf4bc030ef2f3aa0ba054ccaf0a711
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 static LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
128 static LPWSTR COMCTL32_wSubclass = NULL;
129 HMODULE COMCTL32_hModule = 0;
130 static 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 int strCnt = 0;
540 if (style & SBT_RTLREADING)
541 FIXME("Unsupported RTL style!\n");
542 r.left += 3;
543 do {
544 if (*text == '\t') {
545 if (strCnt) {
546 DrawTextW (hdc, text - strCnt, strCnt, &r, align|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX);
547 strCnt = 0;
549 if (align==DT_RIGHT) {
550 break;
552 align = (align==DT_LEFT ? DT_CENTER : DT_RIGHT);
553 } else {
554 strCnt++;
556 } while(*text++);
558 if (strCnt) DrawTextW (hdc, text - strCnt, -1, &r, align|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX);
559 SetBkMode(hdc, oldbkmode);
564 /***********************************************************************
565 * DrawStatusText [COMCTL32.@]
566 * DrawStatusTextA [COMCTL32.5]
568 * Draws text with borders, like in a status bar.
570 * PARAMS
571 * hdc [I] handle to the window's display context
572 * lprc [I] pointer to a rectangle
573 * text [I] pointer to the text
574 * style [I] drawing style
576 * RETURNS
577 * No return value.
580 void WINAPI DrawStatusTextA (HDC hdc, LPCRECT lprc, LPCSTR text, UINT style)
582 INT len;
583 LPWSTR textW = NULL;
585 if ( text ) {
586 if ( (len = MultiByteToWideChar( CP_ACP, 0, text, -1, NULL, 0 )) ) {
587 if ( (textW = Alloc( len * sizeof(WCHAR) )) )
588 MultiByteToWideChar( CP_ACP, 0, text, -1, textW, len );
591 DrawStatusTextW( hdc, lprc, textW, style );
592 Free( textW );
596 /***********************************************************************
597 * CreateStatusWindow [COMCTL32.@]
598 * CreateStatusWindowA [COMCTL32.6]
600 * Creates a status bar
602 * PARAMS
603 * style [I] window style
604 * text [I] pointer to the window text
605 * parent [I] handle to the parent window
606 * wid [I] control id of the status bar
608 * RETURNS
609 * Success: handle to the status window
610 * Failure: 0
613 HWND WINAPI
614 CreateStatusWindowA (LONG style, LPCSTR text, HWND parent, UINT wid)
616 return CreateWindowA(STATUSCLASSNAMEA, text, style,
617 CW_USEDEFAULT, CW_USEDEFAULT,
618 CW_USEDEFAULT, CW_USEDEFAULT,
619 parent, (HMENU)(DWORD_PTR)wid, 0, 0);
623 /***********************************************************************
624 * CreateStatusWindowW [COMCTL32.@]
626 * Creates a status bar control
628 * PARAMS
629 * style [I] window style
630 * text [I] pointer to the window text
631 * parent [I] handle to the parent window
632 * wid [I] control id of the status bar
634 * RETURNS
635 * Success: handle to the status window
636 * Failure: 0
639 HWND WINAPI
640 CreateStatusWindowW (LONG style, LPCWSTR text, HWND parent, UINT wid)
642 return CreateWindowW(STATUSCLASSNAMEW, text, style,
643 CW_USEDEFAULT, CW_USEDEFAULT,
644 CW_USEDEFAULT, CW_USEDEFAULT,
645 parent, (HMENU)(DWORD_PTR)wid, 0, 0);
649 /***********************************************************************
650 * CreateUpDownControl [COMCTL32.16]
652 * Creates an up-down control
654 * PARAMS
655 * style [I] window styles
656 * x [I] horizontal position of the control
657 * y [I] vertical position of the control
658 * cx [I] with of the control
659 * cy [I] height of the control
660 * parent [I] handle to the parent window
661 * id [I] the control's identifier
662 * inst [I] handle to the application's module instance
663 * buddy [I] handle to the buddy window, can be NULL
664 * maxVal [I] upper limit of the control
665 * minVal [I] lower limit of the control
666 * curVal [I] current value of the control
668 * RETURNS
669 * Success: handle to the updown control
670 * Failure: 0
673 HWND WINAPI
674 CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
675 HWND parent, INT id, HINSTANCE inst,
676 HWND buddy, INT maxVal, INT minVal, INT curVal)
678 HWND hUD =
679 CreateWindowW (UPDOWN_CLASSW, 0, style, x, y, cx, cy,
680 parent, (HMENU)(DWORD_PTR)id, inst, 0);
681 if (hUD) {
682 SendMessageW (hUD, UDM_SETBUDDY, (WPARAM)buddy, 0);
683 SendMessageW (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));
684 SendMessageW (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));
687 return hUD;
691 /***********************************************************************
692 * InitCommonControls [COMCTL32.17]
694 * Registers the common controls.
696 * PARAMS
697 * No parameters.
699 * RETURNS
700 * No return values.
702 * NOTES
703 * This function is just a dummy - all the controls are registered at
704 * the DLL's initialization. See InitCommonContolsEx for details.
707 VOID WINAPI
708 InitCommonControls (void)
713 /***********************************************************************
714 * InitCommonControlsEx [COMCTL32.@]
716 * Registers the common controls.
718 * PARAMS
719 * lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
721 * RETURNS
722 * Success: TRUE
723 * Failure: FALSE
725 * NOTES
726 * Probably all versions of comctl32 initializes the Win95 controls in DllMain
727 * during DLL initialization. Starting from comctl32 v5.82 all the controls
728 * are initialized there. We follow this behaviour and this function is just
729 * a dummy.
731 * Note: when writing programs under Windows, if you don't call any function
732 * from comctl32 the linker may not link this DLL. If InitCommonControlsEx
733 * was the only comctl32 function you were calling and you remove it you may
734 * have a false impression that InitCommonControlsEx actually did something.
737 BOOL WINAPI
738 InitCommonControlsEx (const INITCOMMONCONTROLSEX *lpInitCtrls)
740 if (!lpInitCtrls || lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
741 return FALSE;
743 TRACE("(0x%08x)\n", lpInitCtrls->dwICC);
744 return TRUE;
748 /***********************************************************************
749 * CreateToolbarEx [COMCTL32.@]
751 * Creates a toolbar window.
753 * PARAMS
754 * hwnd
755 * style
756 * wID
757 * nBitmaps
758 * hBMInst
759 * wBMID
760 * lpButtons
761 * iNumButtons
762 * dxButton
763 * dyButton
764 * dxBitmap
765 * dyBitmap
766 * uStructSize
768 * RETURNS
769 * Success: handle to the tool bar control
770 * Failure: 0
773 HWND WINAPI
774 CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
775 HINSTANCE hBMInst, UINT wBMID, LPCTBBUTTON lpButtons,
776 INT iNumButtons, INT dxButton, INT dyButton,
777 INT dxBitmap, INT dyBitmap, UINT uStructSize)
779 HWND hwndTB;
781 hwndTB =
782 CreateWindowExW(0, TOOLBARCLASSNAMEW, NULL, style|WS_CHILD, 0,0,100,30,
783 hwnd, (HMENU)(DWORD_PTR)wID, COMCTL32_hModule, NULL);
784 if(hwndTB) {
785 TBADDBITMAP tbab;
787 SendMessageW (hwndTB, TB_BUTTONSTRUCTSIZE, (WPARAM)uStructSize, 0);
789 /* set bitmap and button size */
790 /*If CreateToolbarEx receives 0, windows sets default values*/
791 if (dxBitmap < 0)
792 dxBitmap = 16;
793 if (dyBitmap < 0)
794 dyBitmap = 16;
795 if (dxBitmap == 0 || dyBitmap == 0)
796 dxBitmap = dyBitmap = 16;
797 SendMessageW(hwndTB, TB_SETBITMAPSIZE, 0, MAKELPARAM(dxBitmap, dyBitmap));
799 if (dxButton < 0)
800 dxButton = dxBitmap;
801 if (dyButton < 0)
802 dyButton = dyBitmap;
803 /* TB_SETBUTTONSIZE -> TB_SETBITMAPSIZE bug introduced for Windows compatibility */
804 if (dxButton != 0 && dyButton != 0)
805 SendMessageW(hwndTB, TB_SETBITMAPSIZE, 0, MAKELPARAM(dxButton, dyButton));
808 /* add bitmaps */
809 if (nBitmaps > 0 || hBMInst == HINST_COMMCTRL)
811 tbab.hInst = hBMInst;
812 tbab.nID = wBMID;
814 SendMessageW (hwndTB, TB_ADDBITMAP, (WPARAM)nBitmaps, (LPARAM)&tbab);
816 /* add buttons */
817 if(iNumButtons > 0)
818 SendMessageW (hwndTB, TB_ADDBUTTONSW,
819 (WPARAM)iNumButtons, (LPARAM)lpButtons);
822 return hwndTB;
826 /***********************************************************************
827 * CreateMappedBitmap [COMCTL32.8]
829 * Loads a bitmap resource using a colour map.
831 * PARAMS
832 * hInstance [I] Handle to the module containing the bitmap.
833 * idBitmap [I] The bitmap resource ID.
834 * wFlags [I] CMB_MASKED for using bitmap as a mask or 0 for normal.
835 * lpColorMap [I] Colour information needed for the bitmap or NULL (uses system colours).
836 * iNumMaps [I] Number of COLORMAP's pointed to by lpColorMap.
838 * RETURNS
839 * Success: handle to the new bitmap
840 * Failure: 0
843 HBITMAP WINAPI
844 CreateMappedBitmap (HINSTANCE hInstance, INT_PTR idBitmap, UINT wFlags,
845 LPCOLORMAP lpColorMap, INT iNumMaps)
847 HGLOBAL hglb;
848 HRSRC hRsrc;
849 const BITMAPINFOHEADER *lpBitmap;
850 LPBITMAPINFOHEADER lpBitmapInfo;
851 UINT nSize, nColorTableSize, iColor;
852 RGBQUAD *pColorTable;
853 INT i, iMaps, nWidth, nHeight;
854 HDC hdcScreen;
855 HBITMAP hbm;
856 LPCOLORMAP sysColorMap;
857 COLORREF cRef;
858 COLORMAP internalColorMap[4] =
859 {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
861 /* initialize pointer to colortable and default color table */
862 if (lpColorMap) {
863 iMaps = iNumMaps;
864 sysColorMap = lpColorMap;
866 else {
867 internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT);
868 internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW);
869 internalColorMap[2].to = GetSysColor (COLOR_BTNFACE);
870 internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT);
871 iMaps = 4;
872 sysColorMap = (LPCOLORMAP)internalColorMap;
875 hRsrc = FindResourceW (hInstance, (LPWSTR)idBitmap, (LPWSTR)RT_BITMAP);
876 if (hRsrc == 0)
877 return 0;
878 hglb = LoadResource (hInstance, hRsrc);
879 if (hglb == 0)
880 return 0;
881 lpBitmap = LockResource (hglb);
882 if (lpBitmap == NULL)
883 return 0;
885 if (lpBitmap->biSize >= sizeof(BITMAPINFOHEADER) && lpBitmap->biClrUsed)
886 nColorTableSize = lpBitmap->biClrUsed;
887 else if (lpBitmap->biBitCount <= 8)
888 nColorTableSize = (1 << lpBitmap->biBitCount);
889 else
890 nColorTableSize = 0;
891 nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
892 lpBitmapInfo = GlobalAlloc (GMEM_FIXED, nSize);
893 if (lpBitmapInfo == NULL)
894 return 0;
895 RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);
897 pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo) + lpBitmapInfo->biSize);
899 for (iColor = 0; iColor < nColorTableSize; iColor++) {
900 for (i = 0; i < iMaps; i++) {
901 cRef = RGB(pColorTable[iColor].rgbRed,
902 pColorTable[iColor].rgbGreen,
903 pColorTable[iColor].rgbBlue);
904 if ( cRef == sysColorMap[i].from) {
905 #if 0
906 if (wFlags & CBS_MASKED) {
907 if (sysColorMap[i].to != COLOR_BTNTEXT)
908 pColorTable[iColor] = RGB(255, 255, 255);
910 else
911 #endif
912 pColorTable[iColor].rgbBlue = GetBValue(sysColorMap[i].to);
913 pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);
914 pColorTable[iColor].rgbRed = GetRValue(sysColorMap[i].to);
915 break;
919 nWidth = lpBitmapInfo->biWidth;
920 nHeight = lpBitmapInfo->biHeight;
921 hdcScreen = GetDC (NULL);
922 hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
923 if (hbm) {
924 HDC hdcDst = CreateCompatibleDC (hdcScreen);
925 HBITMAP hbmOld = SelectObject (hdcDst, hbm);
926 const BYTE *lpBits = (const BYTE *)(lpBitmap + 1);
927 lpBits += nColorTableSize * sizeof(RGBQUAD);
928 StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
929 lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
930 SRCCOPY);
931 SelectObject (hdcDst, hbmOld);
932 DeleteDC (hdcDst);
934 ReleaseDC (NULL, hdcScreen);
935 GlobalFree (lpBitmapInfo);
936 FreeResource (hglb);
938 return hbm;
942 /***********************************************************************
943 * CreateToolbar [COMCTL32.7]
945 * Creates a toolbar control.
947 * PARAMS
948 * hwnd
949 * style
950 * wID
951 * nBitmaps
952 * hBMInst
953 * wBMID
954 * lpButtons
955 * iNumButtons
957 * RETURNS
958 * Success: handle to the tool bar control
959 * Failure: 0
961 * NOTES
962 * Do not use this functions anymore. Use CreateToolbarEx instead.
965 HWND WINAPI
966 CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
967 HINSTANCE hBMInst, UINT wBMID,
968 LPCTBBUTTON lpButtons,INT iNumButtons)
970 return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
971 hBMInst, wBMID, lpButtons,
972 iNumButtons, 0, 0, 0, 0, CCSIZEOF_STRUCT(TBBUTTON, dwData));
976 /***********************************************************************
977 * DllGetVersion [COMCTL32.@]
979 * Retrieves version information of the 'COMCTL32.DLL'
981 * PARAMS
982 * pdvi [O] pointer to version information structure.
984 * RETURNS
985 * Success: S_OK
986 * Failure: E_INVALIDARG
988 * NOTES
989 * Returns version of a comctl32.dll from IE4.01 SP1.
992 HRESULT WINAPI DllGetVersion (DLLVERSIONINFO *pdvi)
994 if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
995 WARN("wrong DLLVERSIONINFO size from app\n");
996 return E_INVALIDARG;
999 pdvi->dwMajorVersion = COMCTL32_VERSION;
1000 pdvi->dwMinorVersion = COMCTL32_VERSION_MINOR;
1001 pdvi->dwBuildNumber = 2919;
1002 pdvi->dwPlatformID = 6304;
1004 TRACE("%u.%u.%u.%u\n",
1005 pdvi->dwMajorVersion, pdvi->dwMinorVersion,
1006 pdvi->dwBuildNumber, pdvi->dwPlatformID);
1008 return S_OK;
1011 /***********************************************************************
1012 * DllInstall (COMCTL32.@)
1014 * Installs the ComCtl32 DLL.
1016 * RETURNS
1017 * Success: S_OK
1018 * Failure: A HRESULT error
1020 HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline)
1022 TRACE("(%u, %s): stub\n", bInstall, debugstr_w(cmdline));
1023 if (!create_manifest( bInstall )) return HRESULT_FROM_WIN32(GetLastError());
1024 return S_OK;
1027 /***********************************************************************
1028 * _TrackMouseEvent [COMCTL32.@]
1030 * Requests notification of mouse events
1032 * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
1033 * to the hwnd specified in the ptme structure. After the event message
1034 * is posted to the hwnd, the entry in the queue is removed.
1036 * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
1037 * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
1038 * immediately and the TME_LEAVE flag being ignored.
1040 * PARAMS
1041 * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
1043 * RETURNS
1044 * Success: non-zero
1045 * Failure: zero
1047 * IMPLEMENTATION moved to USER32.TrackMouseEvent
1051 BOOL WINAPI
1052 _TrackMouseEvent (TRACKMOUSEEVENT *ptme)
1054 return TrackMouseEvent (ptme);
1057 /*************************************************************************
1058 * GetMUILanguage [COMCTL32.@]
1060 * Returns the user interface language in use by the current process.
1062 * RETURNS
1063 * Language ID in use by the current process.
1065 LANGID WINAPI GetMUILanguage (VOID)
1067 return COMCTL32_uiLang;
1071 /*************************************************************************
1072 * InitMUILanguage [COMCTL32.@]
1074 * Sets the user interface language to be used by the current process.
1076 * RETURNS
1077 * Nothing.
1079 VOID WINAPI InitMUILanguage (LANGID uiLang)
1081 COMCTL32_uiLang = uiLang;
1085 /***********************************************************************
1086 * SetWindowSubclass [COMCTL32.410]
1088 * Starts a window subclass
1090 * PARAMS
1091 * hWnd [in] handle to window subclass.
1092 * pfnSubclass [in] Pointer to new window procedure.
1093 * uIDSubclass [in] Unique identifier of sublass together with pfnSubclass.
1094 * dwRef [in] Reference data to pass to window procedure.
1096 * RETURNS
1097 * Success: non-zero
1098 * Failure: zero
1100 * BUGS
1101 * If an application manually subclasses a window after subclassing it with
1102 * this API and then with this API again, then none of the previous
1103 * subclasses get called or the original window procedure.
1106 BOOL WINAPI SetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
1107 UINT_PTR uIDSubclass, DWORD_PTR dwRef)
1109 LPSUBCLASS_INFO stack;
1110 LPSUBCLASSPROCS proc;
1112 TRACE ("(%p, %p, %lx, %lx)\n", hWnd, pfnSubclass, uIDSubclass, dwRef);
1114 /* Since the window procedure that we set here has two additional arguments,
1115 * we can't simply set it as the new window procedure of the window. So we
1116 * set our own window procedure and then calculate the other two arguments
1117 * from there. */
1119 /* See if we have been called for this window */
1120 stack = GetPropW (hWnd, COMCTL32_wSubclass);
1121 if (!stack) {
1122 /* allocate stack */
1123 stack = Alloc (sizeof(SUBCLASS_INFO));
1124 if (!stack) {
1125 ERR ("Failed to allocate our Subclassing stack\n");
1126 return FALSE;
1128 SetPropW (hWnd, COMCTL32_wSubclass, (HANDLE)stack);
1130 /* set window procedure to our own and save the current one */
1131 if (IsWindowUnicode (hWnd))
1132 stack->origproc = (WNDPROC)SetWindowLongPtrW (hWnd, GWLP_WNDPROC,
1133 (DWORD_PTR)COMCTL32_SubclassProc);
1134 else
1135 stack->origproc = (WNDPROC)SetWindowLongPtrA (hWnd, GWLP_WNDPROC,
1136 (DWORD_PTR)COMCTL32_SubclassProc);
1138 else {
1139 /* Check to see if we have called this function with the same uIDSubClass
1140 * and pfnSubclass */
1141 proc = stack->SubclassProcs;
1142 while (proc) {
1143 if ((proc->id == uIDSubclass) &&
1144 (proc->subproc == pfnSubclass)) {
1145 proc->ref = dwRef;
1146 return TRUE;
1148 proc = proc->next;
1152 proc = Alloc(sizeof(SUBCLASSPROCS));
1153 if (!proc) {
1154 ERR ("Failed to allocate subclass entry in stack\n");
1155 if (IsWindowUnicode (hWnd))
1156 SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1157 else
1158 SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1159 Free (stack);
1160 RemovePropW( hWnd, COMCTL32_wSubclass );
1161 return FALSE;
1164 proc->subproc = pfnSubclass;
1165 proc->ref = dwRef;
1166 proc->id = uIDSubclass;
1167 proc->next = stack->SubclassProcs;
1168 stack->SubclassProcs = proc;
1170 return TRUE;
1174 /***********************************************************************
1175 * GetWindowSubclass [COMCTL32.411]
1177 * Gets the Reference data from a subclass.
1179 * PARAMS
1180 * hWnd [in] Handle to window which were subclassing
1181 * pfnSubclass [in] Pointer to the subclass procedure
1182 * uID [in] Unique indentifier of the subclassing procedure
1183 * pdwRef [out] Pointer to the reference data
1185 * RETURNS
1186 * Success: Non-zero
1187 * Failure: 0
1190 BOOL WINAPI GetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
1191 UINT_PTR uID, DWORD_PTR *pdwRef)
1193 const SUBCLASS_INFO *stack;
1194 const SUBCLASSPROCS *proc;
1196 TRACE ("(%p, %p, %lx, %p)\n", hWnd, pfnSubclass, uID, pdwRef);
1198 /* See if we have been called for this window */
1199 stack = GetPropW (hWnd, COMCTL32_wSubclass);
1200 if (!stack)
1201 return FALSE;
1203 proc = stack->SubclassProcs;
1204 while (proc) {
1205 if ((proc->id == uID) &&
1206 (proc->subproc == pfnSubclass)) {
1207 *pdwRef = proc->ref;
1208 return TRUE;
1210 proc = proc->next;
1213 return FALSE;
1217 /***********************************************************************
1218 * RemoveWindowSubclass [COMCTL32.412]
1220 * Removes a window subclass.
1222 * PARAMS
1223 * hWnd [in] Handle to the window were subclassing
1224 * pfnSubclass [in] Pointer to the subclass procedure
1225 * uID [in] Unique identifier of this subclass
1227 * RETURNS
1228 * Success: non-zero
1229 * Failure: zero
1232 BOOL WINAPI RemoveWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR uID)
1234 LPSUBCLASS_INFO stack;
1235 LPSUBCLASSPROCS prevproc = NULL;
1236 LPSUBCLASSPROCS proc;
1237 BOOL ret = FALSE;
1239 TRACE ("(%p, %p, %lx)\n", hWnd, pfnSubclass, uID);
1241 /* Find the Subclass to remove */
1242 stack = GetPropW (hWnd, COMCTL32_wSubclass);
1243 if (!stack)
1244 return FALSE;
1246 proc = stack->SubclassProcs;
1247 while (proc) {
1248 if ((proc->id == uID) &&
1249 (proc->subproc == pfnSubclass)) {
1251 if (!prevproc)
1252 stack->SubclassProcs = proc->next;
1253 else
1254 prevproc->next = proc->next;
1256 if (stack->stackpos == proc)
1257 stack->stackpos = stack->stackpos->next;
1259 Free (proc);
1260 ret = TRUE;
1261 break;
1263 prevproc = proc;
1264 proc = proc->next;
1267 if (!stack->SubclassProcs && !stack->running) {
1268 TRACE("Last Subclass removed, cleaning up\n");
1269 /* clean up our heap and reset the original window procedure */
1270 if (IsWindowUnicode (hWnd))
1271 SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1272 else
1273 SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1274 Free (stack);
1275 RemovePropW( hWnd, COMCTL32_wSubclass );
1278 return ret;
1281 /***********************************************************************
1282 * COMCTL32_SubclassProc (internal)
1284 * Window procedure for all subclassed windows.
1285 * Saves the current subclassing stack position to support nested messages
1287 static LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1289 LPSUBCLASS_INFO stack;
1290 LPSUBCLASSPROCS proc;
1291 LRESULT ret;
1293 TRACE ("(%p, 0x%08x, 0x%08lx, 0x%08lx)\n", hWnd, uMsg, wParam, lParam);
1295 stack = GetPropW (hWnd, COMCTL32_wSubclass);
1296 if (!stack) {
1297 ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
1298 return 0;
1301 /* Save our old stackpos to properly handle nested messages */
1302 proc = stack->stackpos;
1303 stack->stackpos = stack->SubclassProcs;
1304 stack->running++;
1305 ret = DefSubclassProc(hWnd, uMsg, wParam, lParam);
1306 stack->running--;
1307 stack->stackpos = proc;
1309 if (!stack->SubclassProcs && !stack->running) {
1310 TRACE("Last Subclass removed, cleaning up\n");
1311 /* clean up our heap and reset the original window procedure */
1312 if (IsWindowUnicode (hWnd))
1313 SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1314 else
1315 SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
1316 Free (stack);
1317 RemovePropW( hWnd, COMCTL32_wSubclass );
1319 return ret;
1322 /***********************************************************************
1323 * DefSubclassProc [COMCTL32.413]
1325 * Calls the next window procedure (ie. the one before this subclass)
1327 * PARAMS
1328 * hWnd [in] The window that we're subclassing
1329 * uMsg [in] Message
1330 * wParam [in] WPARAM
1331 * lParam [in] LPARAM
1333 * RETURNS
1334 * Success: non-zero
1335 * Failure: zero
1338 LRESULT WINAPI DefSubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1340 LPSUBCLASS_INFO stack;
1341 LRESULT ret;
1343 TRACE ("(%p, 0x%08x, 0x%08lx, 0x%08lx)\n", hWnd, uMsg, wParam, lParam);
1345 /* retrieve our little stack from the Properties */
1346 stack = GetPropW (hWnd, COMCTL32_wSubclass);
1347 if (!stack) {
1348 ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
1349 return 0;
1352 /* If we are at the end of stack then we have to call the original
1353 * window procedure */
1354 if (!stack->stackpos) {
1355 if (IsWindowUnicode (hWnd))
1356 ret = CallWindowProcW (stack->origproc, hWnd, uMsg, wParam, lParam);
1357 else
1358 ret = CallWindowProcA (stack->origproc, hWnd, uMsg, wParam, lParam);
1359 } else {
1360 const SUBCLASSPROCS *proc = stack->stackpos;
1361 stack->stackpos = stack->stackpos->next;
1362 /* call the Subclass procedure from the stack */
1363 ret = proc->subproc (hWnd, uMsg, wParam, lParam,
1364 proc->id, proc->ref);
1367 return ret;
1371 /***********************************************************************
1372 * COMCTL32_CreateToolTip [NOT AN API]
1374 * Creates a tooltip for the control specified in hwnd and does all
1375 * necessary setup and notifications.
1377 * PARAMS
1378 * hwndOwner [I] Handle to the window that will own the tool tip.
1380 * RETURNS
1381 * Success: Handle of tool tip window.
1382 * Failure: NULL
1385 HWND
1386 COMCTL32_CreateToolTip(HWND hwndOwner)
1388 HWND hwndToolTip;
1390 hwndToolTip = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, WS_POPUP,
1391 CW_USEDEFAULT, CW_USEDEFAULT,
1392 CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner,
1393 0, 0, 0);
1395 /* Send NM_TOOLTIPSCREATED notification */
1396 if (hwndToolTip)
1398 NMTOOLTIPSCREATED nmttc;
1399 /* true owner can be different if hwndOwner is a child window */
1400 HWND hwndTrueOwner = GetWindow(hwndToolTip, GW_OWNER);
1401 nmttc.hdr.hwndFrom = hwndTrueOwner;
1402 nmttc.hdr.idFrom = GetWindowLongPtrW(hwndTrueOwner, GWLP_ID);
1403 nmttc.hdr.code = NM_TOOLTIPSCREATED;
1404 nmttc.hwndToolTips = hwndToolTip;
1406 SendMessageW(GetParent(hwndTrueOwner), WM_NOTIFY,
1407 (WPARAM)GetWindowLongPtrW(hwndTrueOwner, GWLP_ID),
1408 (LPARAM)&nmttc);
1411 return hwndToolTip;
1415 /***********************************************************************
1416 * COMCTL32_RefreshSysColors [NOT AN API]
1418 * Invoked on any control recognizing a WM_SYSCOLORCHANGE message to
1419 * refresh the color values in the color structure
1421 * PARAMS
1422 * none
1424 * RETURNS
1425 * none
1428 VOID
1429 COMCTL32_RefreshSysColors(void)
1431 comctl32_color.clrBtnHighlight = GetSysColor (COLOR_BTNHIGHLIGHT);
1432 comctl32_color.clrBtnShadow = GetSysColor (COLOR_BTNSHADOW);
1433 comctl32_color.clrBtnText = GetSysColor (COLOR_BTNTEXT);
1434 comctl32_color.clrBtnFace = GetSysColor (COLOR_BTNFACE);
1435 comctl32_color.clrHighlight = GetSysColor (COLOR_HIGHLIGHT);
1436 comctl32_color.clrHighlightText = GetSysColor (COLOR_HIGHLIGHTTEXT);
1437 comctl32_color.clrHotTrackingColor = GetSysColor (COLOR_HOTLIGHT);
1438 comctl32_color.clr3dHilight = GetSysColor (COLOR_3DHILIGHT);
1439 comctl32_color.clr3dShadow = GetSysColor (COLOR_3DSHADOW);
1440 comctl32_color.clr3dDkShadow = GetSysColor (COLOR_3DDKSHADOW);
1441 comctl32_color.clr3dFace = GetSysColor (COLOR_3DFACE);
1442 comctl32_color.clrWindow = GetSysColor (COLOR_WINDOW);
1443 comctl32_color.clrWindowText = GetSysColor (COLOR_WINDOWTEXT);
1444 comctl32_color.clrGrayText = GetSysColor (COLOR_GRAYTEXT);
1445 comctl32_color.clrActiveCaption = GetSysColor (COLOR_ACTIVECAPTION);
1446 comctl32_color.clrInfoBk = GetSysColor (COLOR_INFOBK);
1447 comctl32_color.clrInfoText = GetSysColor (COLOR_INFOTEXT);
1450 /***********************************************************************
1451 * COMCTL32_DrawInsertMark [NOT AN API]
1453 * Draws an insertion mark (which looks similar to an 'I').
1455 * PARAMS
1456 * hDC [I] Device context to draw onto.
1457 * lpRect [I] Co-ordinates of insertion mark.
1458 * clrInsertMark [I] Colour of the insertion mark.
1459 * bHorizontal [I] True if insert mark should be drawn horizontally,
1460 * vertical otherwise.
1462 * RETURNS
1463 * none
1465 * NOTES
1466 * Draws up to but not including the bottom co-ordinate when drawing
1467 * vertically or the right co-ordinate when horizontal.
1469 void COMCTL32_DrawInsertMark(HDC hDC, const RECT *lpRect, COLORREF clrInsertMark, BOOL bHorizontal)
1471 HPEN hPen = CreatePen(PS_SOLID, 1, clrInsertMark);
1472 HPEN hOldPen;
1473 static const DWORD adwPolyPoints[] = {4,4,4};
1474 LONG lCentre = (bHorizontal ?
1475 lpRect->top + (lpRect->bottom - lpRect->top)/2 :
1476 lpRect->left + (lpRect->right - lpRect->left)/2);
1477 LONG l1 = (bHorizontal ? lpRect->left : lpRect->top);
1478 LONG l2 = (bHorizontal ? lpRect->right : lpRect->bottom);
1479 const POINT aptInsertMark[] =
1481 /* top (V) or left (H) arrow */
1482 {lCentre , l1 + 2},
1483 {lCentre - 2, l1 },
1484 {lCentre + 3, l1 },
1485 {lCentre + 1, l1 + 2},
1486 /* middle line */
1487 {lCentre , l2 - 2},
1488 {lCentre , l1 - 1},
1489 {lCentre + 1, l1 - 1},
1490 {lCentre + 1, l2 - 2},
1491 /* bottom (V) or right (H) arrow */
1492 {lCentre , l2 - 3},
1493 {lCentre - 2, l2 - 1},
1494 {lCentre + 3, l2 - 1},
1495 {lCentre + 1, l2 - 3},
1497 hOldPen = SelectObject(hDC, hPen);
1498 PolyPolyline(hDC, aptInsertMark, adwPolyPoints, sizeof(adwPolyPoints)/sizeof(adwPolyPoints[0]));
1499 SelectObject(hDC, hOldPen);
1500 DeleteObject(hPen);
1503 /***********************************************************************
1504 * COMCTL32_EnsureBitmapSize [internal]
1506 * If needed, enlarge the bitmap so that the width is at least cxMinWidth and
1507 * the height is at least cyMinHeight. If the bitmap already has these
1508 * dimensions nothing changes.
1510 * PARAMS
1511 * hBitmap [I/O] Bitmap to modify. The handle may change
1512 * cxMinWidth [I] If the width of the bitmap is smaller, then it will
1513 * be enlarged to this value
1514 * cyMinHeight [I] If the height of the bitmap is smaller, then it will
1515 * be enlarged to this value
1516 * cyBackground [I] The color with which the new area will be filled
1518 * RETURNS
1519 * none
1521 void COMCTL32_EnsureBitmapSize(HBITMAP *pBitmap, int cxMinWidth, int cyMinHeight, COLORREF crBackground)
1523 int cxNew, cyNew;
1524 BITMAP bmp;
1525 HBITMAP hNewBitmap;
1526 HBITMAP hNewDCBitmap, hOldDCBitmap;
1527 HBRUSH hNewDCBrush;
1528 HDC hdcNew, hdcOld;
1530 if (!GetObjectW(*pBitmap, sizeof(BITMAP), &bmp))
1531 return;
1532 cxNew = (cxMinWidth > bmp.bmWidth ? cxMinWidth : bmp.bmWidth);
1533 cyNew = (cyMinHeight > bmp.bmHeight ? cyMinHeight : bmp.bmHeight);
1534 if (cxNew == bmp.bmWidth && cyNew == bmp.bmHeight)
1535 return;
1537 hdcNew = CreateCompatibleDC(NULL);
1538 hNewBitmap = CreateBitmap(cxNew, cyNew, bmp.bmPlanes, bmp.bmBitsPixel, NULL);
1539 hNewDCBitmap = SelectObject(hdcNew, hNewBitmap);
1540 hNewDCBrush = SelectObject(hdcNew, CreateSolidBrush(crBackground));
1542 hdcOld = CreateCompatibleDC(NULL);
1543 hOldDCBitmap = SelectObject(hdcOld, *pBitmap);
1545 BitBlt(hdcNew, 0, 0, bmp.bmWidth, bmp.bmHeight, hdcOld, 0, 0, SRCCOPY);
1546 if (bmp.bmWidth < cxMinWidth)
1547 PatBlt(hdcNew, bmp.bmWidth, 0, cxNew, bmp.bmHeight, PATCOPY);
1548 if (bmp.bmHeight < cyMinHeight)
1549 PatBlt(hdcNew, 0, bmp.bmHeight, bmp.bmWidth, cyNew, PATCOPY);
1550 if (bmp.bmWidth < cxMinWidth && bmp.bmHeight < cyMinHeight)
1551 PatBlt(hdcNew, bmp.bmWidth, bmp.bmHeight, cxNew, cyNew, PATCOPY);
1553 SelectObject(hdcNew, hNewDCBitmap);
1554 DeleteObject(SelectObject(hdcNew, hNewDCBrush));
1555 DeleteDC(hdcNew);
1556 SelectObject(hdcOld, hOldDCBitmap);
1557 DeleteDC(hdcOld);
1559 DeleteObject(*pBitmap);
1560 *pBitmap = hNewBitmap;
1561 return;
1564 void COMCTL32_GetFontMetrics(HFONT hFont, TEXTMETRICW *ptm)
1566 HDC hdc = GetDC(NULL);
1567 HFONT hOldFont;
1569 hOldFont = SelectObject(hdc, hFont);
1570 GetTextMetricsW(hdc, ptm);
1571 SelectObject(hdc, hOldFont);
1572 ReleaseDC(NULL, hdc);
1575 #ifndef OCM__BASE /* avoid including olectl.h */
1576 #define OCM__BASE (WM_USER+0x1c00)
1577 #endif
1579 /***********************************************************************
1580 * COMCTL32_IsReflectedMessage [internal]
1582 * Some parents reflect notify messages - for some messages sent by the child,
1583 * they send it back with the message code increased by OCM__BASE (0x2000).
1584 * This allows better subclassing of controls. We don't need to handle such
1585 * messages but we don't want to print ERRs for them, so this helper function
1586 * identifies them.
1588 * Some of the codes are in the CCM_FIRST..CCM_LAST range, but there is no
1589 * colision with defined CCM_ codes.
1591 BOOL COMCTL32_IsReflectedMessage(UINT uMsg)
1593 switch (uMsg)
1595 case OCM__BASE + WM_COMMAND:
1596 case OCM__BASE + WM_CTLCOLORBTN:
1597 case OCM__BASE + WM_CTLCOLOREDIT:
1598 case OCM__BASE + WM_CTLCOLORDLG:
1599 case OCM__BASE + WM_CTLCOLORLISTBOX:
1600 case OCM__BASE + WM_CTLCOLORMSGBOX:
1601 case OCM__BASE + WM_CTLCOLORSCROLLBAR:
1602 case OCM__BASE + WM_CTLCOLORSTATIC:
1603 case OCM__BASE + WM_DRAWITEM:
1604 case OCM__BASE + WM_MEASUREITEM:
1605 case OCM__BASE + WM_DELETEITEM:
1606 case OCM__BASE + WM_VKEYTOITEM:
1607 case OCM__BASE + WM_CHARTOITEM:
1608 case OCM__BASE + WM_COMPAREITEM:
1609 case OCM__BASE + WM_HSCROLL:
1610 case OCM__BASE + WM_VSCROLL:
1611 case OCM__BASE + WM_PARENTNOTIFY:
1612 case OCM__BASE + WM_NOTIFY:
1613 return TRUE;
1614 default:
1615 return FALSE;
1619 /***********************************************************************
1620 * MirrorIcon [COMCTL32.414]
1622 * Mirrors an icon so that it will appear correctly on a mirrored DC.
1624 * PARAMS
1625 * phicon1 [I/O] Icon.
1626 * phicon2 [I/O] Icon.
1628 * RETURNS
1629 * Success: TRUE.
1630 * Failure: FALSE.
1632 BOOL WINAPI MirrorIcon(HICON *phicon1, HICON *phicon2)
1634 FIXME("(%p, %p): stub\n", phicon1, phicon2);
1635 return FALSE;
1638 static inline int IsDelimiter(WCHAR c)
1640 switch(c)
1642 case '/':
1643 case '\\':
1644 case '.':
1645 case ' ':
1646 return TRUE;
1648 return FALSE;
1651 static int CALLBACK PathWordBreakProc(LPCWSTR lpch, int ichCurrent, int cch, int code)
1653 if (code == WB_ISDELIMITER)
1654 return IsDelimiter(lpch[ichCurrent]);
1655 else
1657 int dir = (code == WB_LEFT) ? -1 : 1;
1658 for(; 0 <= ichCurrent && ichCurrent < cch; ichCurrent += dir)
1659 if (IsDelimiter(lpch[ichCurrent])) return ichCurrent;
1661 return ichCurrent;
1664 /***********************************************************************
1665 * SetPathWordBreakProc [COMCTL32.384]
1667 * Sets the word break procedure for an edit control to one that understands
1668 * paths so that the user can jump over directories.
1670 * PARAMS
1671 * hwnd [I] Handle to edit control.
1672 * bSet [I] If this is TRUE then the word break proc is set, otherwise it is removed.
1674 * RETURNS
1675 * Result from EM_SETWORDBREAKPROC message.
1677 LRESULT WINAPI SetPathWordBreakProc(HWND hwnd, BOOL bSet)
1679 return SendMessageW(hwnd, EM_SETWORDBREAKPROC, 0,
1680 (LPARAM)(bSet ? PathWordBreakProc : NULL));
1683 /***********************************************************************
1684 * DrawShadowText [COMCTL32.@]
1686 * Draw text with shadow.
1688 int WINAPI DrawShadowText(HDC hdc, LPCWSTR pszText, UINT cch, RECT *rect, DWORD dwFlags,
1689 COLORREF crText, COLORREF crShadow, int ixOffset, int iyOffset)
1691 FIXME("(%p, %s, %d, %p, %d, 0x%08x, 0x%08x, %d, %d): stub\n", hdc, debugstr_w(pszText), cch, rect, dwFlags,
1692 crText, crShadow, ixOffset, iyOffset);
1693 return DrawTextW(hdc, pszText, cch, rect, DT_LEFT);