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

Last change on this file since 6644 was 6644, checked in by bird, 24 years ago

Added $Id:$ keyword.

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