Abey George (of Macadamian/Corel)
[wine.git] / dlls / comctl32 / commctrl.c
blobd012dd4a0a448569389d7ed62f0bc33a2e84ee86
1 /*
2 * Common controls functions
4 * Copyright 1997 Dimitrie O. Paun
5 * Copyright 1998 Eric Kohl
7 */
9 #include <string.h>
11 #include "winbase.h"
12 #include "heap.h"
13 #include "commctrl.h"
14 #include "animate.h"
15 #include "comboex.h"
16 #include "datetime.h"
17 #include "flatsb.h"
18 #include "header.h"
19 #include "hotkey.h"
20 #include "ipaddress.h"
21 #include "listview.h"
22 #include "monthcal.h"
23 #include "nativefont.h"
24 #include "pager.h"
25 #include "progress.h"
26 #include "rebar.h"
27 #include "status.h"
28 #include "tab.h"
29 #include "toolbar.h"
30 #include "tooltips.h"
31 #include "trackbar.h"
32 #include "treeview.h"
33 #include "updown.h"
34 #include "debugtools.h"
35 #include "winerror.h"
37 DEFAULT_DEBUG_CHANNEL(commctrl)
40 HANDLE COMCTL32_hHeap = (HANDLE)NULL;
41 DWORD COMCTL32_dwProcessesAttached = 0;
42 LPSTR COMCTL32_aSubclass = (LPSTR)NULL;
43 HMODULE COMCTL32_hModule = 0;
46 /***********************************************************************
47 * COMCTL32_LibMain [Internal] Initializes the internal 'COMCTL32.DLL'.
49 * PARAMS
50 * hinstDLL [I] handle to the 'dlls' instance
51 * fdwReason [I]
52 * lpvReserved [I] reserverd, must be NULL
54 * RETURNS
55 * Success: TRUE
56 * Failure: FALSE
59 BOOL WINAPI
60 COMCTL32_LibMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
62 TRACE("%x,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
64 switch (fdwReason) {
65 case DLL_PROCESS_ATTACH:
66 if (COMCTL32_dwProcessesAttached == 0) {
68 /* This will be wrong for any other process attching in this address-space! */
69 COMCTL32_hModule = (HMODULE)hinstDLL;
71 /* create private heap */
72 COMCTL32_hHeap = HeapCreate (0, 0x10000, 0);
73 TRACE("Heap created: 0x%x\n", COMCTL32_hHeap);
75 /* add global subclassing atom (used by 'tooltip' and 'updown') */
76 COMCTL32_aSubclass = (LPSTR)(DWORD)GlobalAddAtomA ("CC32SubclassInfo");
77 TRACE("Subclassing atom added: %p\n",
78 COMCTL32_aSubclass);
80 /* register all Win95 common control classes */
81 ANIMATE_Register ();
82 FLATSB_Register ();
83 HEADER_Register ();
84 HOTKEY_Register ();
85 LISTVIEW_Register ();
86 PROGRESS_Register ();
87 STATUS_Register ();
88 TAB_Register ();
89 TOOLBAR_Register ();
90 TOOLTIPS_Register ();
91 TRACKBAR_Register ();
92 TREEVIEW_Register ();
93 UPDOWN_Register ();
95 COMCTL32_dwProcessesAttached++;
96 break;
98 case DLL_PROCESS_DETACH:
99 COMCTL32_dwProcessesAttached--;
100 if (COMCTL32_dwProcessesAttached == 0) {
101 /* unregister all common control classes */
102 ANIMATE_Unregister ();
103 COMBOEX_Unregister ();
104 DATETIME_Unregister ();
105 FLATSB_Unregister ();
106 HEADER_Unregister ();
107 HOTKEY_Unregister ();
108 IPADDRESS_Unregister ();
109 LISTVIEW_Unregister ();
110 MONTHCAL_Unregister ();
111 NATIVEFONT_Unregister ();
112 PAGER_Unregister ();
113 PROGRESS_Unregister ();
114 REBAR_Unregister ();
115 STATUS_Unregister ();
116 TAB_Unregister ();
117 TOOLBAR_Unregister ();
118 TOOLTIPS_Unregister ();
119 TRACKBAR_Unregister ();
120 TREEVIEW_Unregister ();
121 UPDOWN_Unregister ();
123 /* delete global subclassing atom */
124 GlobalDeleteAtom (LOWORD(COMCTL32_aSubclass));
125 TRACE("Subclassing atom deleted: %p\n",
126 COMCTL32_aSubclass);
127 COMCTL32_aSubclass = (LPSTR)NULL;
129 /* destroy private heap */
130 HeapDestroy (COMCTL32_hHeap);
131 TRACE("Heap destroyed: 0x%x\n", COMCTL32_hHeap);
132 COMCTL32_hHeap = (HANDLE)NULL;
134 break;
137 return TRUE;
141 /***********************************************************************
142 * MenuHelp [COMCTL32.2]
144 * PARAMS
145 * uMsg [I] message (WM_MENUSELECT) (see NOTES)
146 * wParam [I] wParam of the message uMsg
147 * lParam [I] lParam of the message uMsg
148 * hMainMenu [I] handle to the application's main menu
149 * hInst [I] handle to the module that contains string resources
150 * hwndStatus [I] handle to the status bar window
151 * lpwIDs [I] pointer to an array of intergers (see NOTES)
153 * RETURNS
154 * No return value
156 * NOTES
157 * The official documentation is incomplete!
158 * This is the correct documentation:
160 * uMsg:
161 * MenuHelp() does NOT handle WM_COMMAND messages! It only handes
162 * WM_MENUSELECT messages.
164 * lpwIDs:
165 * (will be written ...)
168 VOID WINAPI
169 MenuHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu,
170 HINSTANCE hInst, HWND hwndStatus, LPUINT lpwIDs)
172 UINT uMenuID = 0;
174 if (!IsWindow (hwndStatus))
175 return;
177 switch (uMsg) {
178 case WM_MENUSELECT:
179 TRACE("WM_MENUSELECT wParam=0x%X lParam=0x%lX\n",
180 wParam, lParam);
182 if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {
183 /* menu was closed */
184 TRACE("menu was closed!\n");
185 SendMessageA (hwndStatus, SB_SIMPLE, FALSE, 0);
187 else {
188 /* menu item was selected */
189 if (HIWORD(wParam) & MF_POPUP)
190 uMenuID = (UINT)*(lpwIDs+1);
191 else
192 uMenuID = (UINT)LOWORD(wParam);
193 TRACE("uMenuID = %u\n", uMenuID);
195 if (uMenuID) {
196 CHAR szText[256];
198 if (!LoadStringA (hInst, uMenuID, szText, 256))
199 szText[0] = '\0';
201 SendMessageA (hwndStatus, SB_SETTEXTA,
202 255 | SBT_NOBORDERS, (LPARAM)szText);
203 SendMessageA (hwndStatus, SB_SIMPLE, TRUE, 0);
206 break;
208 case WM_COMMAND :
209 TRACE("WM_COMMAND wParam=0x%X lParam=0x%lX\n",
210 wParam, lParam);
211 /* WM_COMMAND is not invalid since it is documented
212 * in the windows api reference. So don't output
213 * any FIXME for WM_COMMAND
215 WARN("We don't care about the WM_COMMAND\n");
216 break;
218 default:
219 FIXME("Invalid Message 0x%x!\n", uMsg);
220 break;
225 /***********************************************************************
226 * ShowHideMenuCtl [COMCTL32.3]
228 * Shows or hides controls and updates the corresponding menu item.
230 * PARAMS
231 * hwnd [I] handle to the client window.
232 * uFlags [I] menu command id.
233 * lpInfo [I] pointer to an array of integers. (See NOTES.)
235 * RETURNS
236 * Success: TRUE
237 * Failure: FALSE
239 * NOTES
240 * The official documentation is incomplete!
241 * This is the correct documentation:
243 * hwnd
244 * Handle to the window that contains the menu and controls.
246 * uFlags
247 * Identifier of the menu item to receive or loose a check mark.
249 * lpInfo
250 * The array of integers contains pairs of values. BOTH values of
251 * the first pair must be the handles to the application's main menu.
252 * Each subsequent pair consists of a menu id and control id.
255 BOOL WINAPI
256 ShowHideMenuCtl (HWND hwnd, UINT uFlags, LPINT lpInfo)
258 LPINT lpMenuId;
260 TRACE("%x, %x, %p\n", hwnd, uFlags, lpInfo);
262 if (lpInfo == NULL)
263 return FALSE;
265 if (!(lpInfo[0]) || !(lpInfo[1]))
266 return FALSE;
268 /* search for control */
269 lpMenuId = &lpInfo[2];
270 while (*lpMenuId != uFlags)
271 lpMenuId += 2;
273 if (GetMenuState (lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) {
274 /* uncheck menu item */
275 CheckMenuItem (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_UNCHECKED);
277 /* hide control */
278 lpMenuId++;
279 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
280 SWP_HIDEWINDOW);
282 else {
283 /* check menu item */
284 CheckMenuItem (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_CHECKED);
286 /* show control */
287 lpMenuId++;
288 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
289 SWP_SHOWWINDOW);
292 return TRUE;
296 /***********************************************************************
297 * GetEffectiveClientRect [COMCTL32.4]
299 * PARAMS
300 * hwnd [I] handle to the client window.
301 * lpRect [O] pointer to the rectangle of the client window
302 * lpInfo [I] pointer to an array of integers (see NOTES)
304 * RETURNS
305 * No return value.
307 * NOTES
308 * The official documentation is incomplete!
309 * This is the correct documentation:
311 * lpInfo
312 * (will be written...)
315 VOID WINAPI
316 GetEffectiveClientRect (HWND hwnd, LPRECT lpRect, LPINT lpInfo)
318 RECT rcCtrl;
319 INT *lpRun;
320 HWND hwndCtrl;
322 TRACE("(0x%08lx 0x%08lx 0x%08lx)\n",
323 (DWORD)hwnd, (DWORD)lpRect, (DWORD)lpInfo);
325 GetClientRect (hwnd, lpRect);
326 lpRun = lpInfo;
328 do {
329 lpRun += 2;
330 if (*lpRun == 0)
331 return;
332 lpRun++;
333 hwndCtrl = GetDlgItem (hwnd, *lpRun);
334 if (GetWindowLongA (hwndCtrl, GWL_STYLE) & WS_VISIBLE) {
335 TRACE("control id 0x%x\n", *lpRun);
336 GetWindowRect (hwndCtrl, &rcCtrl);
337 MapWindowPoints ((HWND)0, hwnd, (LPPOINT)&rcCtrl, 2);
338 SubtractRect (lpRect, lpRect, &rcCtrl);
340 lpRun++;
341 } while (*lpRun);
345 /***********************************************************************
346 * DrawStatusTextA [COMCTL32.5][COMCTL32.27]
348 * Draws text with borders, like in a status bar.
350 * PARAMS
351 * hdc [I] handle to the window's display context
352 * lprc [I] pointer to a rectangle
353 * text [I] pointer to the text
354 * style [I] drawing style
356 * RETURNS
357 * No return value.
359 * NOTES
360 * The style variable can have one of the following values:
361 * (will be written ...)
364 VOID WINAPI
365 DrawStatusTextA (HDC hdc, LPRECT lprc, LPCSTR text, UINT style)
367 RECT r = *lprc;
368 UINT border = BDR_SUNKENOUTER;
370 if (style & SBT_POPOUT)
371 border = BDR_RAISEDOUTER;
372 else if (style & SBT_NOBORDERS)
373 border = 0;
375 DrawEdge (hdc, &r, border, BF_RECT|BF_ADJUST|BF_MIDDLE);
377 /* now draw text */
378 if (text) {
379 int oldbkmode = SetBkMode (hdc, TRANSPARENT);
380 r.left += 3;
381 DrawTextA (hdc, text, lstrlenA(text),
382 &r, DT_LEFT|DT_VCENTER|DT_SINGLELINE);
383 if (oldbkmode != TRANSPARENT)
384 SetBkMode(hdc, oldbkmode);
389 /***********************************************************************
390 * DrawStatusTextW [COMCTL32.28]
392 * Draws text with borders, like in a status bar.
394 * PARAMS
395 * hdc [I] handle to the window's display context
396 * lprc [I] pointer to a rectangle
397 * text [I] pointer to the text
398 * style [I] drawing style
400 * RETURNS
401 * No return value.
404 VOID WINAPI
405 DrawStatusTextW (HDC hdc, LPRECT lprc, LPCWSTR text, UINT style)
407 LPSTR p = HEAP_strdupWtoA (GetProcessHeap (), 0, text);
408 DrawStatusTextA (hdc, lprc, p, style);
409 HeapFree (GetProcessHeap (), 0, p );
413 /***********************************************************************
414 * CreateStatusWindowA [COMCTL32.6][COMCTL32.21]
416 * Creates a status bar
418 * PARAMS
419 * style [I] window style
420 * text [I] pointer to the window text
421 * parent [I] handle to the parent window
422 * wid [I] control id of the status bar
424 * RETURNS
425 * Success: handle to the status window
426 * Failure: 0
429 HWND WINAPI
430 CreateStatusWindowA (INT style, LPCSTR text, HWND parent, UINT wid)
432 return CreateWindowA(STATUSCLASSNAMEA, text, style,
433 CW_USEDEFAULT, CW_USEDEFAULT,
434 CW_USEDEFAULT, CW_USEDEFAULT,
435 parent, wid, 0, 0);
439 /***********************************************************************
440 * CreateStatusWindowW [COMCTL32.22] Creates a status bar control
442 * PARAMS
443 * style [I] window style
444 * text [I] pointer to the window text
445 * parent [I] handle to the parent window
446 * wid [I] control id of the status bar
448 * RETURNS
449 * Success: handle to the status window
450 * Failure: 0
453 HWND WINAPI
454 CreateStatusWindowW (INT style, LPCWSTR text, HWND parent, UINT wid)
456 return CreateWindowW(STATUSCLASSNAMEW, text, style,
457 CW_USEDEFAULT, CW_USEDEFAULT,
458 CW_USEDEFAULT, CW_USEDEFAULT,
459 parent, wid, 0, 0);
463 /***********************************************************************
464 * CreateUpDownControl [COMCTL32.16] Creates an up-down control
466 * PARAMS
467 * style [I] window styles
468 * x [I] horizontal position of the control
469 * y [I] vertical position of the control
470 * cx [I] with of the control
471 * cy [I] height of the control
472 * parent [I] handle to the parent window
473 * id [I] the control's identifier
474 * inst [I] handle to the application's module instance
475 * buddy [I] handle to the buddy window, can be NULL
476 * maxVal [I] upper limit of the control
477 * minVal [I] lower limit of the control
478 * curVal [I] current value of the control
480 * RETURNS
481 * Success: handle to the updown control
482 * Failure: 0
485 HWND WINAPI
486 CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
487 HWND parent, INT id, HINSTANCE inst,
488 HWND buddy, INT maxVal, INT minVal, INT curVal)
490 HWND hUD =
491 CreateWindowA (UPDOWN_CLASSA, 0, style, x, y, cx, cy,
492 parent, id, inst, 0);
493 if (hUD) {
494 SendMessageA (hUD, UDM_SETBUDDY, buddy, 0);
495 SendMessageA (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));
496 SendMessageA (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));
499 return hUD;
503 /***********************************************************************
504 * InitCommonControls [COMCTL32.17]
506 * Registers the common controls.
508 * PARAMS
509 * No parameters.
511 * RETURNS
512 * No return values.
514 * NOTES
515 * This function is just a dummy.
516 * The Win95 controls are registered at the DLL's initialization.
517 * To register other controls InitCommonControlsEx() must be used.
520 VOID WINAPI
521 InitCommonControls (void)
526 /***********************************************************************
527 * InitCommonControlsEx [COMCTL32.81]
529 * Registers the common controls.
531 * PARAMS
532 * lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
534 * RETURNS
535 * Success: TRUE
536 * Failure: FALSE
538 * NOTES
539 * Only the additinal common controls are registered by this function.
540 * The Win95 controls are registered at the DLL's initialization.
543 BOOL WINAPI
544 InitCommonControlsEx (LPINITCOMMONCONTROLSEX lpInitCtrls)
546 INT cCount;
547 DWORD dwMask;
549 if (!lpInitCtrls)
550 return FALSE;
551 if (lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
552 return FALSE;
554 TRACE("(0x%08lx)\n", lpInitCtrls->dwICC);
556 for (cCount = 0; cCount < 32; cCount++) {
557 dwMask = 1 << cCount;
558 if (!(lpInitCtrls->dwICC & dwMask))
559 continue;
561 switch (lpInitCtrls->dwICC & dwMask) {
562 /* dummy initialization */
563 case ICC_ANIMATE_CLASS:
564 case ICC_BAR_CLASSES:
565 case ICC_LISTVIEW_CLASSES:
566 case ICC_TREEVIEW_CLASSES:
567 case ICC_TAB_CLASSES:
568 case ICC_UPDOWN_CLASS:
569 case ICC_PROGRESS_CLASS:
570 case ICC_HOTKEY_CLASS:
571 break;
573 /* advanced classes - not included in Win95 */
574 case ICC_DATE_CLASSES:
575 MONTHCAL_Register ();
576 DATETIME_Register ();
577 break;
579 case ICC_USEREX_CLASSES:
580 COMBOEX_Register ();
581 break;
583 case ICC_COOL_CLASSES:
584 REBAR_Register ();
585 break;
587 case ICC_INTERNET_CLASSES:
588 IPADDRESS_Register ();
589 break;
591 case ICC_PAGESCROLLER_CLASS:
592 PAGER_Register ();
593 break;
595 case ICC_NATIVEFNTCTL_CLASS:
596 NATIVEFONT_Register ();
597 break;
599 default:
600 FIXME("Unknown class! dwICC=0x%lX\n", dwMask);
601 break;
605 return TRUE;
609 /***********************************************************************
610 * CreateToolbarEx [COMCTL32.32] Creates a tool bar window
612 * PARAMS
613 * hwnd
614 * style
615 * wID
616 * nBitmaps
617 * hBMInst
618 * wBMID
619 * lpButtons
620 * iNumButtons
621 * dxButton
622 * dyButton
623 * dxBitmap
624 * dyBitmap
625 * uStructSize
627 * RETURNS
628 * Success: handle to the tool bar control
629 * Failure: 0
632 HWND WINAPI
633 CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
634 HINSTANCE hBMInst, UINT wBMID, LPCTBBUTTON lpButtons,
635 INT iNumButtons, INT dxButton, INT dyButton,
636 INT dxBitmap, INT dyBitmap, UINT uStructSize)
638 HWND hwndTB =
639 CreateWindowExA (0, TOOLBARCLASSNAMEA, "", style, 0, 0, 0, 0,
640 hwnd, (HMENU)wID, 0, NULL);
641 if(hwndTB) {
642 TBADDBITMAP tbab;
644 SendMessageA (hwndTB, TB_BUTTONSTRUCTSIZE,
645 (WPARAM)uStructSize, 0);
647 /* set bitmap and button size */
648 /*If CreateToolbarEx receive 0, windows set default values*/
649 if (dyBitmap < 0)
650 dyBitmap = 15;
651 if (dxBitmap < 0)
652 dxBitmap = 16;
654 SendMessageA (hwndTB, TB_SETBITMAPSIZE, 0,
655 MAKELPARAM((WORD)dxBitmap, (WORD)dyBitmap));
656 SendMessageA (hwndTB, TB_SETBUTTONSIZE, 0,
657 MAKELPARAM((WORD)dxButton, (WORD)dyButton));
660 /* add bitmaps */
661 if (nBitmaps > 0)
663 tbab.hInst = hBMInst;
664 tbab.nID = wBMID;
666 SendMessageA (hwndTB, TB_ADDBITMAP,
667 (WPARAM)nBitmaps, (LPARAM)&tbab);
669 /* add buttons */
670 if(iNumButtons > 0)
671 SendMessageA (hwndTB, TB_ADDBUTTONSA,
672 (WPARAM)iNumButtons, (LPARAM)lpButtons);
675 return hwndTB;
679 /***********************************************************************
680 * CreateMappedBitmap [COMCTL32.8]
682 * PARAMS
683 * hInstance [I]
684 * idBitmap [I]
685 * wFlags [I]
686 * lpColorMap [I]
687 * iNumMaps [I]
689 * RETURNS
690 * Success: handle to the new bitmap
691 * Failure: 0
694 HBITMAP WINAPI
695 CreateMappedBitmap (HINSTANCE hInstance, INT idBitmap, UINT wFlags,
696 LPCOLORMAP lpColorMap, INT iNumMaps)
698 HGLOBAL hglb;
699 HRSRC hRsrc;
700 LPBITMAPINFOHEADER lpBitmap, lpBitmapInfo;
701 UINT nSize, nColorTableSize;
702 RGBQUAD *pColorTable;
703 INT iColor, i, iMaps, nWidth, nHeight;
704 HDC hdcScreen;
705 HBITMAP hbm;
706 LPCOLORMAP sysColorMap;
707 COLORREF cRef;
708 COLORMAP internalColorMap[4] =
709 {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
711 /* initialize pointer to colortable and default color table */
712 if (lpColorMap) {
713 iMaps = iNumMaps;
714 sysColorMap = lpColorMap;
716 else {
717 internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT);
718 internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW);
719 internalColorMap[2].to = GetSysColor (COLOR_BTNFACE);
720 internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT);
721 iMaps = 4;
722 sysColorMap = (LPCOLORMAP)internalColorMap;
725 hRsrc = FindResourceA (hInstance, (LPSTR)idBitmap, RT_BITMAPA);
726 if (hRsrc == 0)
727 return 0;
728 hglb = LoadResource (hInstance, hRsrc);
729 if (hglb == 0)
730 return 0;
731 lpBitmap = (LPBITMAPINFOHEADER)LockResource (hglb);
732 if (lpBitmap == NULL)
733 return 0;
735 nColorTableSize = (1 << lpBitmap->biBitCount);
736 nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
737 lpBitmapInfo = (LPBITMAPINFOHEADER)GlobalAlloc (GMEM_FIXED, nSize);
738 if (lpBitmapInfo == NULL)
739 return 0;
740 RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);
742 pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo)+(UINT)lpBitmapInfo->biSize);
744 for (iColor = 0; iColor < nColorTableSize; iColor++) {
745 for (i = 0; i < iMaps; i++) {
746 cRef = RGB(pColorTable[iColor].rgbRed,
747 pColorTable[iColor].rgbGreen,
748 pColorTable[iColor].rgbBlue);
749 if ( cRef == sysColorMap[i].from) {
750 #if 0
751 if (wFlags & CBS_MASKED) {
752 if (sysColorMap[i].to != COLOR_BTNTEXT)
753 pColorTable[iColor] = RGB(255, 255, 255);
755 else
756 #endif
757 pColorTable[iColor].rgbBlue = GetBValue(sysColorMap[i].to);
758 pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);
759 pColorTable[iColor].rgbRed = GetRValue(sysColorMap[i].to);
760 break;
764 nWidth = (INT)lpBitmapInfo->biWidth;
765 nHeight = (INT)lpBitmapInfo->biHeight;
766 hdcScreen = GetDC ((HWND)0);
767 hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
768 if (hbm) {
769 HDC hdcDst = CreateCompatibleDC (hdcScreen);
770 HBITMAP hbmOld = SelectObject (hdcDst, hbm);
771 LPBYTE lpBits = (LPBYTE)(lpBitmap + 1);
772 lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
773 StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
774 lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
775 SRCCOPY);
776 SelectObject (hdcDst, hbmOld);
777 DeleteDC (hdcDst);
779 ReleaseDC ((HWND)0, hdcScreen);
780 GlobalFree ((HGLOBAL)lpBitmapInfo);
781 FreeResource (hglb);
783 return hbm;
787 /***********************************************************************
788 * CreateToolbar [COMCTL32.7] Creates a tool bar control
790 * PARAMS
791 * hwnd
792 * style
793 * wID
794 * nBitmaps
795 * hBMInst
796 * wBMID
797 * lpButtons
798 * iNumButtons
800 * RETURNS
801 * Success: handle to the tool bar control
802 * Failure: 0
804 * NOTES
805 * Do not use this functions anymore. Use CreateToolbarEx instead.
808 HWND WINAPI
809 CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
810 HINSTANCE hBMInst, UINT wBMID,
811 LPCOLDTBBUTTON lpButtons,INT iNumButtons)
813 return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
814 hBMInst, wBMID, (LPCTBBUTTON)lpButtons,
815 iNumButtons, 0, 0, 0, 0, sizeof (OLDTBBUTTON));
819 /***********************************************************************
820 * DllGetVersion [COMCTL32.25]
822 * Retrieves version information of the 'COMCTL32.DLL'
824 * PARAMS
825 * pdvi [O] pointer to version information structure.
827 * RETURNS
828 * Success: S_OK
829 * Failure: E_INVALIDARG
831 * NOTES
832 * Returns version of a comctl32.dll from IE4.01 SP1.
835 HRESULT WINAPI
836 COMCTL32_DllGetVersion (DLLVERSIONINFO *pdvi)
838 if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
839 WARN("wrong DLLVERSIONINFO size from app");
840 return E_INVALIDARG;
843 pdvi->dwMajorVersion = 4;
844 pdvi->dwMinorVersion = 72;
845 pdvi->dwBuildNumber = 3110;
846 pdvi->dwPlatformID = 1;
848 TRACE("%lu.%lu.%lu.%lu\n",
849 pdvi->dwMajorVersion, pdvi->dwMinorVersion,
850 pdvi->dwBuildNumber, pdvi->dwPlatformID);
852 return S_OK;
855 /***********************************************************************
856 * DllInstall (COMCTL32.@)
858 HRESULT WINAPI COMCTL32_DllInstall(BOOL bInstall, LPCWSTR cmdline)
860 FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
861 debugstr_w(cmdline));
863 return S_OK;
867 typedef struct __TRACKINGLIST {
868 TRACKMOUSEEVENT tme;
869 POINT pos; /* center of hover rectangle */
870 INT iHoverTime; /* elapsed time the cursor has been inside of the hover rect */
871 } _TRACKINGLIST;
873 static _TRACKINGLIST TrackingList[10];
874 static int iTrackMax = 0;
875 static UINT_PTR timer;
876 static const INT iTimerInterval = 50; /* msec for timer interval */
878 /* FIXME: need to implement WM_NCMOUSELEAVE and WM_NCMOUSEHOVER for */
879 /* TrackMouseEventProc and _TrackMouseEvent */
880 static void CALLBACK TrackMouseEventProc(HWND hwndUnused, UINT uMsg, UINT_PTR idEvent,
881 DWORD dwTime)
883 int i = 0;
884 POINT pos;
885 HWND hwnd;
886 INT hoverwidth = 0, hoverheight = 0;
888 GetCursorPos(&pos);
889 hwnd = WindowFromPoint(pos);
891 SystemParametersInfoA(SPI_GETMOUSEHOVERWIDTH, 0, &hoverwidth, 0);
892 SystemParametersInfoA(SPI_GETMOUSEHOVERHEIGHT, 0, &hoverheight, 0);
894 /* loop through tracking events we are processing */
895 while (i < iTrackMax) {
896 /* see if this tracking event is looking for TME_LEAVE and that the */
897 /* mouse has left the window */
898 if ((TrackingList[i].tme.dwFlags & TME_LEAVE) &&
899 (TrackingList[i].tme.hwndTrack != hwnd)) {
900 PostMessageA(TrackingList[i].tme.hwndTrack, WM_MOUSELEAVE, 0, 0);
902 /* remove the TME_LEAVE flag */
903 TrackingList[i].tme.dwFlags ^= TME_LEAVE;
906 /* see if we are tracking hovering for this hwnd */
907 if(TrackingList[i].tme.dwFlags & TME_HOVER) {
908 /* add the timer interval to the hovering time */
909 TrackingList[i].iHoverTime+=iTimerInterval;
911 /* has the cursor moved outside the rectangle centered around pos? */
912 if((abs(pos.x - TrackingList[i].pos.x) > (hoverwidth / 2.0))
913 || (abs(pos.y - TrackingList[i].pos.y) > (hoverheight / 2.0)))
915 /* record this new position as the current position and reset */
916 /* the iHoverTime variable to 0 */
917 TrackingList[i].pos = pos;
918 TrackingList[i].iHoverTime = 0;
921 /* has the mouse hovered long enough? */
922 if(TrackingList[i].iHoverTime <= TrackingList[i].tme.dwHoverTime)
924 PostMessageA(TrackingList[i].tme.hwndTrack, WM_MOUSEHOVER, 0, 0);
926 /* stop tracking mouse hover */
927 TrackingList[i].tme.dwFlags ^= TME_HOVER;
931 /* see if we are still tracking TME_HOVER or TME_LEAVE for this entry */
932 if((TrackingList[i].tme.dwFlags & TME_HOVER) ||
933 (TrackingList[i].tme.dwFlags & TME_LEAVE)) {
934 i++;
935 } else { /* remove this entry from the tracking list */
936 TrackingList[i] = TrackingList[--iTrackMax];
940 /* stop the timer if the tracking list is empty */
941 if(iTrackMax == 0) {
942 KillTimer(0, timer);
943 timer = 0;
947 /***********************************************************************
948 * _TrackMouseEvent [COMCTL32.25]
950 * Requests notification of mouse events
952 * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
953 * to the hwnd specified in the ptme structure. After the event message
954 * is posted to the hwnd, the entry in the queue is removed.
956 * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
957 * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
958 * immediately and the TME_LEAVE flag being ignored.
960 * PARAMS
961 * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
963 * RETURNS
964 * Success: non-zero
965 * Failure: zero
969 BOOL WINAPI
970 _TrackMouseEvent (TRACKMOUSEEVENT *ptme)
972 DWORD flags = 0;
973 int i = 0;
974 BOOL cancel = 0, hover = 0, leave = 0, query = 0;
975 HWND hwnd;
976 POINT pos;
978 pos.x = 0;
979 pos.y = 0;
981 TRACE("%lx, %lx, %x, %lx\n", ptme->cbSize, ptme->dwFlags, ptme->hwndTrack, ptme->dwHoverTime);
983 if (ptme->cbSize != sizeof(TRACKMOUSEEVENT)) {
984 WARN("wrong TRACKMOUSEEVENT size from app");
985 SetLastError(ERROR_INVALID_PARAMETER); /* FIXME not sure if this is correct */
986 return FALSE;
989 flags = ptme->dwFlags;
991 /* if HOVER_DEFAULT was specified replace this with the systems current value */
992 if(ptme->dwHoverTime == HOVER_DEFAULT)
993 SystemParametersInfoA(SPI_GETMOUSEHOVERTIME, 0, &(ptme->dwHoverTime), 0);
995 GetCursorPos(&pos);
996 hwnd = WindowFromPoint(pos);
998 if ( flags & TME_CANCEL ) {
999 flags &= ~ TME_CANCEL;
1000 cancel = 1;
1003 if ( flags & TME_HOVER ) {
1004 flags &= ~ TME_HOVER;
1005 hover = 1;
1008 if ( flags & TME_LEAVE ) {
1009 flags &= ~ TME_LEAVE;
1010 leave = 1;
1013 /* fill the TRACKMOUSEEVENT struct with the current tracking for the given hwnd */
1014 if ( flags & TME_QUERY ) {
1015 flags &= ~ TME_QUERY;
1016 query = 1;
1017 i = 0;
1019 /* Find the tracking list entry with the matching hwnd */
1020 while((i < iTrackMax) && (TrackingList[i].tme.hwndTrack != ptme->hwndTrack)) {
1021 i++;
1024 /* hwnd found, fill in the ptme struct */
1025 if(i < iTrackMax)
1026 *ptme = TrackingList[i].tme;
1027 else
1028 ptme->dwFlags = 0;
1030 return TRUE; /* return here, TME_QUERY is retrieving information */
1033 if ( flags )
1034 FIXME("Unknown flag(s) %08lx\n", flags );
1036 if(cancel) {
1037 /* find a matching hwnd if one exists */
1038 i = 0;
1040 while((i < iTrackMax) && (TrackingList[i].tme.hwndTrack != ptme->hwndTrack)) {
1041 i++;
1044 if(i < iTrackMax) {
1045 TrackingList[i].tme.dwFlags &= ~(ptme->dwFlags & ~TME_CANCEL);
1047 /* if we aren't tracking on hover or leave remove this entry */
1048 if(!((TrackingList[i].tme.dwFlags & TME_HOVER) ||
1049 (TrackingList[i].tme.dwFlags & TME_LEAVE)))
1051 TrackingList[i] = TrackingList[--iTrackMax];
1053 if(iTrackMax == 0) {
1054 KillTimer(0, timer);
1055 timer = 0;
1059 } else {
1060 /* see if hwndTrack isn't the current window */
1061 if(ptme->hwndTrack != hwnd) {
1062 if(leave) {
1063 PostMessageA(ptme->hwndTrack, WM_MOUSELEAVE, 0, 0);
1065 } else {
1066 /* See if this hwnd is already being tracked and update the tracking flags */
1067 for(i = 0; i < iTrackMax; i++) {
1068 if(TrackingList[i].tme.hwndTrack == ptme->hwndTrack) {
1069 if(hover) {
1070 TrackingList[i].tme.dwFlags |= TME_HOVER;
1071 TrackingList[i].tme.dwHoverTime = ptme->dwHoverTime;
1074 if(leave)
1075 TrackingList[i].tme.dwFlags |= TME_LEAVE;
1077 /* reset iHoverTime as per winapi specs */
1078 TrackingList[i].iHoverTime = 0;
1080 return TRUE;
1084 /* if the tracking list is full return FALSE */
1085 if (iTrackMax == sizeof (TrackingList) / sizeof(*TrackingList)) {
1086 return FALSE;
1089 /* Adding new mouse event to the tracking list */
1090 TrackingList[iTrackMax].tme = *ptme;
1092 /* Initialize HoverInfo variables even if not hover tracking */
1093 TrackingList[iTrackMax].iHoverTime = 0;
1094 TrackingList[iTrackMax].pos = pos;
1096 iTrackMax++;
1098 if (!timer) {
1099 timer = SetTimer(0, 0, iTimerInterval, TrackMouseEventProc);
1104 return TRUE;