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