source: trunk/src/comctl32/comctl32.c@ 7334

Last change on this file since 7334 was 7334, checked in by phaller, 24 years ago

replaced heap alloc by stack alloc

File size: 33.1 KB
Line 
1/*
2 * Common controls functions
3 *
4 * Copyright 1997 Dimitrie O. Paun
5 * Copyright 1998,2000 Eric Kohl
6 *
7 */
8
9#ifdef __WIN32OS2__
10#include <odin.h>
11#endif
12
13#include <string.h>
14#include "winbase.h"
15#include "heap.h"
16#include "commctrl.h"
17#include "debugtools.h"
18#include "winerror.h"
19#include "shlwapi.h"
20#include "comctl32.h"
21
22DEFAULT_DEBUG_CHANNEL(commctrl);
23
24#ifndef __WIN32OS2__
25extern void ANIMATE_Register(void);
26extern void ANIMATE_Unregister(void);
27extern void COMBOEX_Register(void);
28extern void COMBOEX_Unregister(void);
29extern void DATETIME_Register(void);
30extern void DATETIME_Unregister(void);
31extern void FLATSB_Register(void);
32extern void FLATSB_Unregister(void);
33extern void HEADER_Register(void);
34extern void HEADER_Unregister(void);
35extern void HOTKEY_Register(void);
36extern void HOTKEY_Unregister(void);
37extern void IPADDRESS_Register(void);
38extern void IPADDRESS_Unregister(void);
39extern void LISTVIEW_Register(void);
40extern void LISTVIEW_Unregister(void);
41extern void MONTHCAL_Register(void);
42extern void MONTHCAL_Unregister(void);
43extern void NATIVEFONT_Register(void);
44extern void NATIVEFONT_Unregister(void);
45extern void PAGER_Register(void);
46extern void PAGER_Unregister(void);
47extern void PROGRESS_Register(void);
48extern void PROGRESS_Unregister(void);
49extern void REBAR_Register(void);
50extern void REBAR_Unregister(void);
51extern void STATUS_Register(void);
52extern void STATUS_Unregister(void);
53extern void TAB_Register(void);
54extern void TAB_Unregister(void);
55extern void TOOLBAR_Register(void);
56extern void TOOLBAR_Unregister(void);
57extern void TOOLTIPS_Register(void);
58extern void TOOLTIPS_Unregister(void);
59extern void TRACKBAR_Register(void);
60extern void TRACKBAR_Unregister(void);
61extern void TREEVIEW_Register(void);
62extern void TREEVIEW_Unregister(void);
63extern void UPDOWN_Register(void);
64extern void UPDOWN_Unregister(void);
65#endif
66
67HANDLE COMCTL32_hHeap = (HANDLE)NULL;
68LPSTR COMCTL32_aSubclass = (LPSTR)NULL;
69HMODULE COMCTL32_hModule = 0;
70LANGID COMCTL32_uiLang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
71HBRUSH COMCTL32_hPattern55AABrush = (HANDLE)NULL;
72
73static HBITMAP COMCTL32_hPattern55AABitmap = (HANDLE)NULL;
74
75static const WORD wPattern55AA[] =
76{
77 0x5555, 0xaaaa, 0x5555, 0xaaaa,
78 0x5555, 0xaaaa, 0x5555, 0xaaaa
79};
80
81
82/***********************************************************************
83 * COMCTL32_LibMain [Internal] Initializes the internal 'COMCTL32.DLL'.
84 *
85 * PARAMS
86 * hinstDLL [I] handle to the 'dlls' instance
87 * fdwReason [I]
88 * lpvReserved [I] reserverd, must be NULL
89 *
90 * RETURNS
91 * Success: TRUE
92 * Failure: FALSE
93 */
94
95BOOL WINAPI
96COMCTL32_LibMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
97{
98 TRACE("%x,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
99
100 switch (fdwReason) {
101 case DLL_PROCESS_ATTACH:
102 COMCTL32_hModule = (HMODULE)hinstDLL;
103
104 /* create private heap */
105 COMCTL32_hHeap = HeapCreate (0, 0x10000, 0);
106 TRACE("Heap created: 0x%x\n", COMCTL32_hHeap);
107
108 /* add global subclassing atom (used by 'tooltip' and 'updown') */
109 COMCTL32_aSubclass = (LPSTR)(DWORD)GlobalAddAtomA ("CC32SubclassInfo");
110 TRACE("Subclassing atom added: %p\n", COMCTL32_aSubclass);
111
112 /* create local pattern brush */
113 COMCTL32_hPattern55AABitmap = CreateBitmap (8, 8, 1, 1, wPattern55AA);
114 COMCTL32_hPattern55AABrush = CreatePatternBrush (COMCTL32_hPattern55AABitmap);
115
116 /* register all Win95 common control classes */
117 ANIMATE_Register ();
118 FLATSB_Register ();
119 HEADER_Register ();
120 HOTKEY_Register ();
121 LISTVIEW_Register ();
122 PROGRESS_Register ();
123 STATUS_Register ();
124 TAB_Register ();
125 TOOLBAR_Register ();
126 TOOLTIPS_Register ();
127 TRACKBAR_Register ();
128 TREEVIEW_Register ();
129 UPDOWN_Register ();
130 break;
131
132 case DLL_PROCESS_DETACH:
133 /* unregister all common control classes */
134 ANIMATE_Unregister ();
135 COMBOEX_Unregister ();
136 DATETIME_Unregister ();
137 FLATSB_Unregister ();
138 HEADER_Unregister ();
139 HOTKEY_Unregister ();
140 IPADDRESS_Unregister ();
141 LISTVIEW_Unregister ();
142 MONTHCAL_Unregister ();
143 NATIVEFONT_Unregister ();
144 PAGER_Unregister ();
145 PROGRESS_Unregister ();
146 REBAR_Unregister ();
147 STATUS_Unregister ();
148 TAB_Unregister ();
149 TOOLBAR_Unregister ();
150 TOOLTIPS_Unregister ();
151 TRACKBAR_Unregister ();
152 TREEVIEW_Unregister ();
153 UPDOWN_Unregister ();
154
155 /* delete local pattern brush */
156 DeleteObject (COMCTL32_hPattern55AABrush);
157 COMCTL32_hPattern55AABrush = (HANDLE)NULL;
158 DeleteObject (COMCTL32_hPattern55AABitmap);
159 COMCTL32_hPattern55AABitmap = (HANDLE)NULL;
160
161 /* delete global subclassing atom */
162 GlobalDeleteAtom (LOWORD(COMCTL32_aSubclass));
163 TRACE("Subclassing atom deleted: %p\n", COMCTL32_aSubclass);
164 COMCTL32_aSubclass = (LPSTR)NULL;
165
166 /* destroy private heap */
167 HeapDestroy (COMCTL32_hHeap);
168 TRACE("Heap destroyed: 0x%x\n", COMCTL32_hHeap);
169 COMCTL32_hHeap = (HANDLE)NULL;
170 break;
171 }
172
173 return TRUE;
174}
175
176
177/***********************************************************************
178 * MenuHelp [COMCTL32.2]
179 *
180 * PARAMS
181 * uMsg [I] message (WM_MENUSELECT) (see NOTES)
182 * wParam [I] wParam of the message uMsg
183 * lParam [I] lParam of the message uMsg
184 * hMainMenu [I] handle to the application's main menu
185 * hInst [I] handle to the module that contains string resources
186 * hwndStatus [I] handle to the status bar window
187 * lpwIDs [I] pointer to an array of integers (see NOTES)
188 *
189 * RETURNS
190 * No return value
191 *
192 * NOTES
193 * The official documentation is incomplete!
194 * This is the correct documentation:
195 *
196 * uMsg:
197 * MenuHelp() does NOT handle WM_COMMAND messages! It only handles
198 * WM_MENUSELECT messages.
199 *
200 * lpwIDs:
201 * (will be written ...)
202 */
203
204VOID WINAPI
205MenuHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu,
206 HINSTANCE hInst, HWND hwndStatus, LPUINT lpwIDs)
207{
208 UINT uMenuID = 0;
209
210 if (!IsWindow (hwndStatus))
211 return;
212
213 switch (uMsg) {
214 case WM_MENUSELECT:
215 TRACE("WM_MENUSELECT wParam=0x%X lParam=0x%lX\n",
216 wParam, lParam);
217
218 if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {
219 /* menu was closed */
220 TRACE("menu was closed!\n");
221 SendMessageA (hwndStatus, SB_SIMPLE, FALSE, 0);
222 }
223 else {
224 /* menu item was selected */
225 if (HIWORD(wParam) & MF_POPUP)
226 uMenuID = (UINT)*(lpwIDs+1);
227 else
228 uMenuID = (UINT)LOWORD(wParam);
229 TRACE("uMenuID = %u\n", uMenuID);
230
231 if (uMenuID) {
232 CHAR szText[256];
233
234 if (!LoadStringA (hInst, uMenuID, szText, 256))
235 szText[0] = '\0';
236
237 SendMessageA (hwndStatus, SB_SETTEXTA,
238 255 | SBT_NOBORDERS, (LPARAM)szText);
239 SendMessageA (hwndStatus, SB_SIMPLE, TRUE, 0);
240 }
241 }
242 break;
243
244 case WM_COMMAND :
245 TRACE("WM_COMMAND wParam=0x%X lParam=0x%lX\n",
246 wParam, lParam);
247 /* WM_COMMAND is not invalid since it is documented
248 * in the windows api reference. So don't output
249 * any FIXME for WM_COMMAND
250 */
251 WARN("We don't care about the WM_COMMAND\n");
252 break;
253
254 default:
255 FIXME("Invalid Message 0x%x!\n", uMsg);
256 break;
257 }
258}
259
260
261/***********************************************************************
262 * ShowHideMenuCtl [COMCTL32.3]
263 *
264 * Shows or hides controls and updates the corresponding menu item.
265 *
266 * PARAMS
267 * hwnd [I] handle to the client window.
268 * uFlags [I] menu command id.
269 * lpInfo [I] pointer to an array of integers. (See NOTES.)
270 *
271 * RETURNS
272 * Success: TRUE
273 * Failure: FALSE
274 *
275 * NOTES
276 * The official documentation is incomplete!
277 * This is the correct documentation:
278 *
279 * hwnd
280 * Handle to the window that contains the menu and controls.
281 *
282 * uFlags
283 * Identifier of the menu item to receive or loose a check mark.
284 *
285 * lpInfo
286 * The array of integers contains pairs of values. BOTH values of
287 * the first pair must be the handles to the application's main menu.
288 * Each subsequent pair consists of a menu id and control id.
289 */
290
291BOOL WINAPI
292ShowHideMenuCtl (HWND hwnd, UINT uFlags, LPINT lpInfo)
293{
294 LPINT lpMenuId;
295
296 TRACE("%x, %x, %p\n", hwnd, uFlags, lpInfo);
297
298 if (lpInfo == NULL)
299 return FALSE;
300
301 if (!(lpInfo[0]) || !(lpInfo[1]))
302 return FALSE;
303
304 /* search for control */
305 lpMenuId = &lpInfo[2];
306 while (*lpMenuId != uFlags)
307 lpMenuId += 2;
308
309 if (GetMenuState (lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) {
310 /* uncheck menu item */
311 CheckMenuItem (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_UNCHECKED);
312
313 /* hide control */
314 lpMenuId++;
315 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
316 SWP_HIDEWINDOW);
317 }
318 else {
319 /* check menu item */
320 CheckMenuItem (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_CHECKED);
321
322 /* show control */
323 lpMenuId++;
324 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
325 SWP_SHOWWINDOW);
326 }
327
328 return TRUE;
329}
330
331
332/***********************************************************************
333 * GetEffectiveClientRect [COMCTL32.4]
334 *
335 * PARAMS
336 * hwnd [I] handle to the client window.
337 * lpRect [O] pointer to the rectangle of the client window
338 * lpInfo [I] pointer to an array of integers (see NOTES)
339 *
340 * RETURNS
341 * No return value.
342 *
343 * NOTES
344 * The official documentation is incomplete!
345 * This is the correct documentation:
346 *
347 * lpInfo
348 * (will be written...)
349 */
350
351VOID WINAPI
352GetEffectiveClientRect (HWND hwnd, LPRECT lpRect, LPINT lpInfo)
353{
354 RECT rcCtrl;
355 INT *lpRun;
356 HWND hwndCtrl;
357
358 TRACE("(0x%08lx 0x%08lx 0x%08lx)\n",
359 (DWORD)hwnd, (DWORD)lpRect, (DWORD)lpInfo);
360
361 GetClientRect (hwnd, lpRect);
362 lpRun = lpInfo;
363
364 do {
365 lpRun += 2;
366 if (*lpRun == 0)
367 return;
368 lpRun++;
369 hwndCtrl = GetDlgItem (hwnd, *lpRun);
370 if (GetWindowLongA (hwndCtrl, GWL_STYLE) & WS_VISIBLE) {
371 TRACE("control id 0x%x\n", *lpRun);
372 GetWindowRect (hwndCtrl, &rcCtrl);
373 MapWindowPoints ((HWND)0, hwnd, (LPPOINT)&rcCtrl, 2);
374 SubtractRect (lpRect, lpRect, &rcCtrl);
375 }
376 lpRun++;
377 } while (*lpRun);
378}
379
380
381/***********************************************************************
382 * DrawStatusTextA [COMCTL32.5][COMCTL32.27]
383 *
384 * Draws text with borders, like in a status bar.
385 *
386 * PARAMS
387 * hdc [I] handle to the window's display context
388 * lprc [I] pointer to a rectangle
389 * text [I] pointer to the text
390 * style [I] drawing style
391 *
392 * RETURNS
393 * No return value.
394 *
395 * NOTES
396 * The style variable can have one of the following values:
397 * (will be written ...)
398 */
399
400VOID WINAPI
401DrawStatusTextA (HDC hdc, LPRECT lprc, LPCSTR text, UINT style)
402{
403 RECT r = *lprc;
404 UINT border = BDR_SUNKENOUTER;
405
406 if (style & SBT_POPOUT)
407 border = BDR_RAISEDOUTER;
408 else if (style & SBT_NOBORDERS)
409 border = 0;
410
411 DrawEdge (hdc, &r, border, BF_RECT|BF_ADJUST|BF_MIDDLE);
412
413 /* now draw text */
414 if (text) {
415 int oldbkmode = SetBkMode (hdc, TRANSPARENT);
416 r.left += 3;
417 DrawTextA (hdc, text, lstrlenA(text),
418 &r, DT_LEFT|DT_VCENTER|DT_SINGLELINE);
419 if (oldbkmode != TRANSPARENT)
420 SetBkMode(hdc, oldbkmode);
421 }
422}
423
424
425/***********************************************************************
426 * DrawStatusTextW [COMCTL32.28]
427 *
428 * Draws text with borders, like in a status bar.
429 *
430 * PARAMS
431 * hdc [I] handle to the window's display context
432 * lprc [I] pointer to a rectangle
433 * text [I] pointer to the text
434 * style [I] drawing style
435 *
436 * RETURNS
437 * No return value.
438 */
439
440VOID WINAPI
441DrawStatusTextW (HDC hdc, LPRECT lprc, LPCWSTR text, UINT style)
442{
443#ifdef __WIN32OS2__
444 LPSTR p;
445 STACK_strdupWtoA(text, p)
446#else
447 LPSTR p = HEAP_strdupWtoA (GetProcessHeap (), 0, text);
448#endif
449 DrawStatusTextA (hdc, lprc, p, style);
450#ifndef __WIN32OS2__
451 HeapFree (GetProcessHeap (), 0, p );
452#endif
453}
454
455
456/***********************************************************************
457 * CreateStatusWindowA [COMCTL32.6][COMCTL32.21]
458 *
459 * Creates a status bar
460 *
461 * PARAMS
462 * style [I] window style
463 * text [I] pointer to the window text
464 * parent [I] handle to the parent window
465 * wid [I] control id of the status bar
466 *
467 * RETURNS
468 * Success: handle to the status window
469 * Failure: 0
470 */
471
472HWND WINAPI
473CreateStatusWindowA (INT style, LPCSTR text, HWND parent, UINT wid)
474{
475 return CreateWindowA(STATUSCLASSNAMEA, text, style,
476 CW_USEDEFAULT, CW_USEDEFAULT,
477 CW_USEDEFAULT, CW_USEDEFAULT,
478 parent, wid, 0, 0);
479}
480
481
482/***********************************************************************
483 * CreateStatusWindowW [COMCTL32.22] Creates a status bar control
484 *
485 * PARAMS
486 * style [I] window style
487 * text [I] pointer to the window text
488 * parent [I] handle to the parent window
489 * wid [I] control id of the status bar
490 *
491 * RETURNS
492 * Success: handle to the status window
493 * Failure: 0
494 */
495
496HWND WINAPI
497CreateStatusWindowW (INT style, LPCWSTR text, HWND parent, UINT wid)
498{
499 return CreateWindowW(STATUSCLASSNAMEW, text, style,
500 CW_USEDEFAULT, CW_USEDEFAULT,
501 CW_USEDEFAULT, CW_USEDEFAULT,
502 parent, wid, 0, 0);
503}
504
505
506/***********************************************************************
507 * CreateUpDownControl [COMCTL32.16] Creates an up-down control
508 *
509 * PARAMS
510 * style [I] window styles
511 * x [I] horizontal position of the control
512 * y [I] vertical position of the control
513 * cx [I] with of the control
514 * cy [I] height of the control
515 * parent [I] handle to the parent window
516 * id [I] the control's identifier
517 * inst [I] handle to the application's module instance
518 * buddy [I] handle to the buddy window, can be NULL
519 * maxVal [I] upper limit of the control
520 * minVal [I] lower limit of the control
521 * curVal [I] current value of the control
522 *
523 * RETURNS
524 * Success: handle to the updown control
525 * Failure: 0
526 */
527
528HWND WINAPI
529CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
530 HWND parent, INT id, HINSTANCE inst,
531 HWND buddy, INT maxVal, INT minVal, INT curVal)
532{
533 HWND hUD =
534 CreateWindowA (UPDOWN_CLASSA, 0, style, x, y, cx, cy,
535 parent, id, inst, 0);
536 if (hUD) {
537 SendMessageA (hUD, UDM_SETBUDDY, buddy, 0);
538 SendMessageA (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));
539 SendMessageA (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));
540 }
541
542 return hUD;
543}
544
545
546/***********************************************************************
547 * InitCommonControls [COMCTL32.17]
548 *
549 * Registers the common controls.
550 *
551 * PARAMS
552 * No parameters.
553 *
554 * RETURNS
555 * No return values.
556 *
557 * NOTES
558 * This function is just a dummy.
559 * The Win95 controls are registered at the DLL's initialization.
560 * To register other controls InitCommonControlsEx() must be used.
561 */
562
563VOID WINAPI
564InitCommonControls (void)
565{
566}
567
568
569/***********************************************************************
570 * InitCommonControlsEx [COMCTL32.81]
571 *
572 * Registers the common controls.
573 *
574 * PARAMS
575 * lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
576 *
577 * RETURNS
578 * Success: TRUE
579 * Failure: FALSE
580 *
581 * NOTES
582 * Only the additional common controls are registered by this function.
583 * The Win95 controls are registered at the DLL's initialization.
584 */
585
586BOOL WINAPI
587InitCommonControlsEx (LPINITCOMMONCONTROLSEX lpInitCtrls)
588{
589 INT cCount;
590 DWORD dwMask;
591
592 if (!lpInitCtrls)
593 return FALSE;
594 if (lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
595 return FALSE;
596
597 TRACE("(0x%08lx)\n", lpInitCtrls->dwICC);
598
599 for (cCount = 0; cCount < 32; cCount++) {
600 dwMask = 1 << cCount;
601 if (!(lpInitCtrls->dwICC & dwMask))
602 continue;
603
604 switch (lpInitCtrls->dwICC & dwMask) {
605 /* dummy initialization */
606 case ICC_ANIMATE_CLASS:
607 case ICC_BAR_CLASSES:
608 case ICC_LISTVIEW_CLASSES:
609 case ICC_TREEVIEW_CLASSES:
610 case ICC_TAB_CLASSES:
611 case ICC_UPDOWN_CLASS:
612 case ICC_PROGRESS_CLASS:
613 case ICC_HOTKEY_CLASS:
614 break;
615
616 /* advanced classes - not included in Win95 */
617 case ICC_DATE_CLASSES:
618 MONTHCAL_Register ();
619 DATETIME_Register ();
620 break;
621
622 case ICC_USEREX_CLASSES:
623 COMBOEX_Register ();
624 break;
625
626 case ICC_COOL_CLASSES:
627 REBAR_Register ();
628 break;
629
630 case ICC_INTERNET_CLASSES:
631 IPADDRESS_Register ();
632 break;
633
634 case ICC_PAGESCROLLER_CLASS:
635 PAGER_Register ();
636 break;
637
638 case ICC_NATIVEFNTCTL_CLASS:
639 NATIVEFONT_Register ();
640 break;
641
642 default:
643 FIXME("Unknown class! dwICC=0x%lX\n", dwMask);
644 break;
645 }
646 }
647
648 return TRUE;
649}
650
651
652/***********************************************************************
653 * CreateToolbarEx [COMCTL32.32] Creates a tool bar window
654 *
655 * PARAMS
656 * hwnd
657 * style
658 * wID
659 * nBitmaps
660 * hBMInst
661 * wBMID
662 * lpButtons
663 * iNumButtons
664 * dxButton
665 * dyButton
666 * dxBitmap
667 * dyBitmap
668 * uStructSize
669 *
670 * RETURNS
671 * Success: handle to the tool bar control
672 * Failure: 0
673 */
674
675HWND WINAPI
676CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
677 HINSTANCE hBMInst, UINT wBMID, LPCTBBUTTON lpButtons,
678 INT iNumButtons, INT dxButton, INT dyButton,
679 INT dxBitmap, INT dyBitmap, UINT uStructSize)
680{
681 HWND hwndTB;
682
683 /* If not position is specified then put it at the top */
684 if ((style & CCS_BOTTOM) == 0) {
685 style|=CCS_TOP;
686 }
687
688 hwndTB =
689 CreateWindowExA (0, TOOLBARCLASSNAMEA, "", style|WS_CHILD, 0, 0, 0, 0,
690 hwnd, (HMENU)wID, 0, NULL);
691 if(hwndTB) {
692 TBADDBITMAP tbab;
693
694 SendMessageA (hwndTB, TB_BUTTONSTRUCTSIZE,
695 (WPARAM)uStructSize, 0);
696
697 /* set bitmap and button size */
698 /*If CreateToolbarEx receives 0, windows sets default values*/
699 if (dxBitmap <= 0)
700 dxBitmap = 16;
701 if (dyBitmap <= 0)
702 dyBitmap = 15;
703 SendMessageA (hwndTB, TB_SETBITMAPSIZE, 0,
704 MAKELPARAM((WORD)dxBitmap, (WORD)dyBitmap));
705
706 if (dxButton <= 0)
707 dxButton = 24;
708 if (dyButton <= 0)
709 dyButton = 22;
710 SendMessageA (hwndTB, TB_SETBUTTONSIZE, 0,
711 MAKELPARAM((WORD)dxButton, (WORD)dyButton));
712
713
714 /* add bitmaps */
715 if (nBitmaps > 0)
716 {
717 tbab.hInst = hBMInst;
718 tbab.nID = wBMID;
719
720 SendMessageA (hwndTB, TB_ADDBITMAP,
721 (WPARAM)nBitmaps, (LPARAM)&tbab);
722 }
723 /* add buttons */
724 if(iNumButtons > 0)
725 SendMessageA (hwndTB, TB_ADDBUTTONSA,
726 (WPARAM)iNumButtons, (LPARAM)lpButtons);
727 }
728
729 return hwndTB;
730}
731
732
733/***********************************************************************
734 * CreateMappedBitmap [COMCTL32.8]
735 *
736 * PARAMS
737 * hInstance [I]
738 * idBitmap [I]
739 * wFlags [I]
740 * lpColorMap [I]
741 * iNumMaps [I]
742 *
743 * RETURNS
744 * Success: handle to the new bitmap
745 * Failure: 0
746 */
747
748HBITMAP WINAPI
749CreateMappedBitmap (HINSTANCE hInstance, INT idBitmap, UINT wFlags,
750 LPCOLORMAP lpColorMap, INT iNumMaps)
751{
752 HGLOBAL hglb;
753 HRSRC hRsrc;
754 LPBITMAPINFOHEADER lpBitmap, lpBitmapInfo;
755 UINT nSize, nColorTableSize;
756 RGBQUAD *pColorTable;
757 INT iColor, i, iMaps, nWidth, nHeight;
758 HDC hdcScreen;
759 HBITMAP hbm;
760 LPCOLORMAP sysColorMap;
761 COLORREF cRef;
762 COLORMAP internalColorMap[4] =
763 {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
764
765 /* initialize pointer to colortable and default color table */
766 if (lpColorMap) {
767 iMaps = iNumMaps;
768 sysColorMap = lpColorMap;
769 }
770 else {
771 internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT);
772 internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW);
773 internalColorMap[2].to = GetSysColor (COLOR_BTNFACE);
774 internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT);
775 iMaps = 4;
776 sysColorMap = (LPCOLORMAP)internalColorMap;
777 }
778
779 hRsrc = FindResourceA (hInstance, (LPSTR)idBitmap, RT_BITMAPA);
780 if (hRsrc == 0)
781 return 0;
782 hglb = LoadResource (hInstance, hRsrc);
783 if (hglb == 0)
784 return 0;
785 lpBitmap = (LPBITMAPINFOHEADER)LockResource (hglb);
786 if (lpBitmap == NULL)
787 return 0;
788
789 nColorTableSize = (1 << lpBitmap->biBitCount);
790 nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
791 lpBitmapInfo = (LPBITMAPINFOHEADER)GlobalAlloc (GMEM_FIXED, nSize);
792 if (lpBitmapInfo == NULL)
793 return 0;
794 RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);
795
796 pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo)+(UINT)lpBitmapInfo->biSize);
797
798 for (iColor = 0; iColor < nColorTableSize; iColor++) {
799 for (i = 0; i < iMaps; i++) {
800 cRef = RGB(pColorTable[iColor].rgbRed,
801 pColorTable[iColor].rgbGreen,
802 pColorTable[iColor].rgbBlue);
803 if ( cRef == sysColorMap[i].from) {
804#if 0
805 if (wFlags & CBS_MASKED) {
806 if (sysColorMap[i].to != COLOR_BTNTEXT)
807 pColorTable[iColor] = RGB(255, 255, 255);
808 }
809 else
810#endif
811 pColorTable[iColor].rgbBlue = GetBValue(sysColorMap[i].to);
812 pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);
813 pColorTable[iColor].rgbRed = GetRValue(sysColorMap[i].to);
814 break;
815 }
816 }
817 }
818 nWidth = (INT)lpBitmapInfo->biWidth;
819 nHeight = (INT)lpBitmapInfo->biHeight;
820 hdcScreen = GetDC ((HWND)0);
821 hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
822 if (hbm) {
823 HDC hdcDst = CreateCompatibleDC (hdcScreen);
824 HBITMAP hbmOld = SelectObject (hdcDst, hbm);
825 LPBYTE lpBits = (LPBYTE)(lpBitmap + 1);
826 lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
827 StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
828 lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
829 SRCCOPY);
830 SelectObject (hdcDst, hbmOld);
831 DeleteDC (hdcDst);
832 }
833 ReleaseDC ((HWND)0, hdcScreen);
834 GlobalFree ((HGLOBAL)lpBitmapInfo);
835 FreeResource (hglb);
836
837 return hbm;
838}
839
840
841/***********************************************************************
842 * CreateToolbar [COMCTL32.7] Creates a tool bar control
843 *
844 * PARAMS
845 * hwnd
846 * style
847 * wID
848 * nBitmaps
849 * hBMInst
850 * wBMID
851 * lpButtons
852 * iNumButtons
853 *
854 * RETURNS
855 * Success: handle to the tool bar control
856 * Failure: 0
857 *
858 * NOTES
859 * Do not use this functions anymore. Use CreateToolbarEx instead.
860 */
861
862HWND WINAPI
863CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
864 HINSTANCE hBMInst, UINT wBMID,
865 LPCOLDTBBUTTON lpButtons,INT iNumButtons)
866{
867 return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
868 hBMInst, wBMID, (LPCTBBUTTON)lpButtons,
869 iNumButtons, 0, 0, 0, 0, sizeof (OLDTBBUTTON));
870}
871
872
873/***********************************************************************
874 * DllGetVersion [COMCTL32.25]
875 *
876 * Retrieves version information of the 'COMCTL32.DLL'
877 *
878 * PARAMS
879 * pdvi [O] pointer to version information structure.
880 *
881 * RETURNS
882 * Success: S_OK
883 * Failure: E_INVALIDARG
884 *
885 * NOTES
886 * Returns version of a comctl32.dll from IE4.01 SP1.
887 */
888
889HRESULT WINAPI
890COMCTL32_DllGetVersion (DLLVERSIONINFO *pdvi)
891{
892 if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
893 WARN("wrong DLLVERSIONINFO size from app");
894 return E_INVALIDARG;
895 }
896
897 pdvi->dwMajorVersion = COMCTL32_VERSION;
898 pdvi->dwMinorVersion = COMCTL32_VERSION_MINOR;
899 pdvi->dwBuildNumber = 2919;
900 pdvi->dwPlatformID = 6304;
901
902 TRACE("%lu.%lu.%lu.%lu\n",
903 pdvi->dwMajorVersion, pdvi->dwMinorVersion,
904 pdvi->dwBuildNumber, pdvi->dwPlatformID);
905
906 return S_OK;
907}
908
909/***********************************************************************
910 * DllInstall (COMCTL32.@)
911 */
912HRESULT WINAPI COMCTL32_DllInstall(BOOL bInstall, LPCWSTR cmdline)
913{
914 FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
915 debugstr_w(cmdline));
916
917 return S_OK;
918}
919
920
921typedef struct __TRACKINGLIST {
922 TRACKMOUSEEVENT tme;
923 POINT pos; /* center of hover rectangle */
924 INT iHoverTime; /* elapsed time the cursor has been inside of the hover rect */
925} _TRACKINGLIST;
926
927static _TRACKINGLIST TrackingList[10];
928static int iTrackMax = 0;
929static UINT_PTR timer;
930
931static const INT iTimerInterval = 50; /* msec for timer interval */
932
933/* FIXME: need to implement WM_NCMOUSELEAVE and WM_NCMOUSEHOVER for */
934/* TrackMouseEventProc and _TrackMouseEvent */
935static void CALLBACK TrackMouseEventProc(HWND hwndUnused, UINT uMsg, UINT_PTR idEvent,
936 DWORD dwTime)
937{
938 int i = 0;
939 POINT pos;
940 HWND hwnd;
941 INT hoverwidth = 0, hoverheight = 0;
942
943 GetCursorPos(&pos);
944 hwnd = WindowFromPoint(pos);
945
946 SystemParametersInfoA(SPI_GETMOUSEHOVERWIDTH, 0, &hoverwidth, 0);
947 SystemParametersInfoA(SPI_GETMOUSEHOVERHEIGHT, 0, &hoverheight, 0);
948
949 /* loop through tracking events we are processing */
950 while (i < iTrackMax) {
951 /* see if this tracking event is looking for TME_LEAVE and that the */
952 /* mouse has left the window */
953 if ((TrackingList[i].tme.dwFlags & TME_LEAVE) &&
954 (TrackingList[i].tme.hwndTrack != hwnd)) {
955 PostMessageA(TrackingList[i].tme.hwndTrack, WM_MOUSELEAVE, 0, 0);
956
957 /* remove the TME_LEAVE flag */
958 TrackingList[i].tme.dwFlags ^= TME_LEAVE;
959 }
960
961 /* see if we are tracking hovering for this hwnd */
962 if(TrackingList[i].tme.dwFlags & TME_HOVER) {
963 /* add the timer interval to the hovering time */
964 TrackingList[i].iHoverTime+=iTimerInterval;
965
966 /* has the cursor moved outside the rectangle centered around pos? */
967 if((abs(pos.x - TrackingList[i].pos.x) > (hoverwidth / 2.0))
968 || (abs(pos.y - TrackingList[i].pos.y) > (hoverheight / 2.0)))
969 {
970 /* record this new position as the current position and reset */
971 /* the iHoverTime variable to 0 */
972 TrackingList[i].pos = pos;
973 TrackingList[i].iHoverTime = 0;
974 }
975
976 /* has the mouse hovered long enough? */
977 if(TrackingList[i].iHoverTime <= TrackingList[i].tme.dwHoverTime)
978 {
979 PostMessageA(TrackingList[i].tme.hwndTrack, WM_MOUSEHOVER, 0, 0);
980
981 /* stop tracking mouse hover */
982 TrackingList[i].tme.dwFlags ^= TME_HOVER;
983 }
984 }
985
986 /* see if we are still tracking TME_HOVER or TME_LEAVE for this entry */
987 if((TrackingList[i].tme.dwFlags & TME_HOVER) ||
988 (TrackingList[i].tme.dwFlags & TME_LEAVE)) {
989 i++;
990 } else { /* remove this entry from the tracking list */
991 TrackingList[i] = TrackingList[--iTrackMax];
992 }
993 }
994
995 /* stop the timer if the tracking list is empty */
996 if(iTrackMax == 0) {
997 KillTimer(0, timer);
998 timer = 0;
999 }
1000}
1001
1002/***********************************************************************
1003 * _TrackMouseEvent [COMCTL32.25]
1004 *
1005 * Requests notification of mouse events
1006 *
1007 * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
1008 * to the hwnd specified in the ptme structure. After the event message
1009 * is posted to the hwnd, the entry in the queue is removed.
1010 *
1011 * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
1012 * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
1013 * immediately and the TME_LEAVE flag being ignored.
1014 *
1015 * PARAMS
1016 * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
1017 *
1018 * RETURNS
1019 * Success: non-zero
1020 * Failure: zero
1021 *
1022 */
1023
1024BOOL WINAPI
1025_TrackMouseEvent (TRACKMOUSEEVENT *ptme)
1026{
1027 DWORD flags = 0;
1028 int i = 0;
1029 BOOL cancel = 0, hover = 0, leave = 0, query = 0;
1030 HWND hwnd;
1031 POINT pos;
1032
1033 pos.x = 0;
1034 pos.y = 0;
1035
1036 TRACE("%lx, %lx, %x, %lx\n", ptme->cbSize, ptme->dwFlags, ptme->hwndTrack, ptme->dwHoverTime);
1037
1038 if (ptme->cbSize != sizeof(TRACKMOUSEEVENT)) {
1039 WARN("wrong TRACKMOUSEEVENT size from app");
1040 SetLastError(ERROR_INVALID_PARAMETER); /* FIXME not sure if this is correct */
1041 return FALSE;
1042 }
1043
1044 flags = ptme->dwFlags;
1045
1046 /* if HOVER_DEFAULT was specified replace this with the systems current value */
1047 if(ptme->dwHoverTime == HOVER_DEFAULT)
1048 SystemParametersInfoA(SPI_GETMOUSEHOVERTIME, 0, &(ptme->dwHoverTime), 0);
1049
1050 GetCursorPos(&pos);
1051 hwnd = WindowFromPoint(pos);
1052
1053 if ( flags & TME_CANCEL ) {
1054 flags &= ~ TME_CANCEL;
1055 cancel = 1;
1056 }
1057
1058 if ( flags & TME_HOVER ) {
1059 flags &= ~ TME_HOVER;
1060 hover = 1;
1061 }
1062
1063 if ( flags & TME_LEAVE ) {
1064 flags &= ~ TME_LEAVE;
1065 leave = 1;
1066 }
1067
1068 /* fill the TRACKMOUSEEVENT struct with the current tracking for the given hwnd */
1069 if ( flags & TME_QUERY ) {
1070 flags &= ~ TME_QUERY;
1071 query = 1;
1072 i = 0;
1073
1074 /* Find the tracking list entry with the matching hwnd */
1075 while((i < iTrackMax) && (TrackingList[i].tme.hwndTrack != ptme->hwndTrack)) {
1076 i++;
1077 }
1078
1079 /* hwnd found, fill in the ptme struct */
1080 if(i < iTrackMax)
1081 *ptme = TrackingList[i].tme;
1082 else
1083 ptme->dwFlags = 0;
1084
1085 return TRUE; /* return here, TME_QUERY is retrieving information */
1086 }
1087
1088 if ( flags )
1089 FIXME("Unknown flag(s) %08lx\n", flags );
1090
1091 if(cancel) {
1092 /* find a matching hwnd if one exists */
1093 i = 0;
1094
1095 while((i < iTrackMax) && (TrackingList[i].tme.hwndTrack != ptme->hwndTrack)) {
1096 i++;
1097 }
1098
1099 if(i < iTrackMax) {
1100 TrackingList[i].tme.dwFlags &= ~(ptme->dwFlags & ~TME_CANCEL);
1101
1102 /* if we aren't tracking on hover or leave remove this entry */
1103 if(!((TrackingList[i].tme.dwFlags & TME_HOVER) ||
1104 (TrackingList[i].tme.dwFlags & TME_LEAVE)))
1105 {
1106 TrackingList[i] = TrackingList[--iTrackMax];
1107
1108 if(iTrackMax == 0) {
1109 KillTimer(0, timer);
1110 timer = 0;
1111 }
1112 }
1113 }
1114 } else {
1115 /* see if hwndTrack isn't the current window */
1116 if(ptme->hwndTrack != hwnd) {
1117 if(leave) {
1118 PostMessageA(ptme->hwndTrack, WM_MOUSELEAVE, 0, 0);
1119 }
1120 } else {
1121 /* See if this hwnd is already being tracked and update the tracking flags */
1122 for(i = 0; i < iTrackMax; i++) {
1123 if(TrackingList[i].tme.hwndTrack == ptme->hwndTrack) {
1124 if(hover) {
1125 TrackingList[i].tme.dwFlags |= TME_HOVER;
1126 TrackingList[i].tme.dwHoverTime = ptme->dwHoverTime;
1127 }
1128
1129 if(leave)
1130 TrackingList[i].tme.dwFlags |= TME_LEAVE;
1131
1132 /* reset iHoverTime as per winapi specs */
1133 TrackingList[i].iHoverTime = 0;
1134
1135 return TRUE;
1136 }
1137 }
1138
1139 /* if the tracking list is full return FALSE */
1140 if (iTrackMax == sizeof (TrackingList) / sizeof(*TrackingList)) {
1141 return FALSE;
1142 }
1143
1144 /* Adding new mouse event to the tracking list */
1145 TrackingList[iTrackMax].tme = *ptme;
1146
1147 /* Initialize HoverInfo variables even if not hover tracking */
1148 TrackingList[iTrackMax].iHoverTime = 0;
1149 TrackingList[iTrackMax].pos = pos;
1150
1151 iTrackMax++;
1152
1153 if (!timer) {
1154 timer = SetTimer(0, 0, iTimerInterval, TrackMouseEventProc);
1155 }
1156 }
1157 }
1158
1159 return TRUE;
1160}
1161
1162
1163/*************************************************************************
1164 * GetMUILanguage [COMCTL32.39]
1165 *
1166 * FIXME: What's this supposed to do? Apparently some i18n thing.
1167 *
1168 */
1169LANGID WINAPI GetMUILanguage (VOID)
1170{
1171 return COMCTL32_uiLang;
1172}
1173
1174
1175/*************************************************************************
1176 * InitMUILanguage [COMCTL32.85]
1177 *
1178 * FIXME: What's this supposed to do? Apparently some i18n thing.
1179 *
1180 */
1181
1182VOID WINAPI InitMUILanguage (LANGID uiLang)
1183{
1184 COMCTL32_uiLang = uiLang;
1185}
1186
1187
1188/***********************************************************************
1189 * COMCTL32_CreateToolTip [NOT AN API]
1190 *
1191 * Creates a tooltip for the control specified in hwnd and does all
1192 * necessary setup and notifications.
1193 *
1194 * PARAMS
1195 * hwndOwner [I] Handle to the window that will own the tool tip.
1196 *
1197 * RETURNS
1198 * Success: Handle of tool tip window.
1199 * Failure: NULL
1200 */
1201HWND
1202COMCTL32_CreateToolTip(HWND hwndOwner)
1203{
1204 HWND hwndToolTip;
1205
1206 hwndToolTip = CreateWindowExA(0, TOOLTIPS_CLASSA, NULL, 0,
1207 CW_USEDEFAULT, CW_USEDEFAULT,
1208 CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner,
1209 0, 0, 0);
1210
1211 /* Send NM_TOOLTIPSCREATED notification */
1212 if (hwndToolTip)
1213 {
1214 NMTOOLTIPSCREATED nmttc;
1215 /* true owner can be different if hwndOwner is a child window */
1216 HWND hwndTrueOwner = GetWindow(hwndToolTip, GW_OWNER);
1217 nmttc.hdr.hwndFrom = hwndTrueOwner;
1218 nmttc.hdr.idFrom = GetWindowLongA(hwndTrueOwner, GWL_ID);
1219 nmttc.hdr.code = NM_TOOLTIPSCREATED;
1220 nmttc.hwndToolTips = hwndToolTip;
1221
1222 SendMessageA(GetParent(hwndTrueOwner), WM_NOTIFY,
1223 (WPARAM)GetWindowLongA(hwndTrueOwner, GWL_ID),
1224 (LPARAM)&nmttc);
1225 }
1226
1227 return hwndToolTip;
1228}
Note: See TracBrowser for help on using the repository browser.