Yet another attempt at fixing CW_USEDEFAULT handling.
[wine.git] / dlls / comctl32 / commctrl.c
blob6dd1e66c1968f166e8636dd8cbb9511284d1f6c0
1 /*
2 * Common controls functions
4 * Copyright 1997 Dimitrie O. Paun
5 * Copyright 1998,2000 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;
44 LANGID COMCTL32_uiLang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
47 /***********************************************************************
48 * COMCTL32_LibMain [Internal] Initializes the internal 'COMCTL32.DLL'.
50 * PARAMS
51 * hinstDLL [I] handle to the 'dlls' instance
52 * fdwReason [I]
53 * lpvReserved [I] reserverd, must be NULL
55 * RETURNS
56 * Success: TRUE
57 * Failure: FALSE
60 BOOL WINAPI
61 COMCTL32_LibMain (HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
63 TRACE("%x,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
65 switch (fdwReason) {
66 case DLL_PROCESS_ATTACH:
67 if (COMCTL32_dwProcessesAttached == 0) {
69 /* This will be wrong for any other process attching in this address-space! */
70 COMCTL32_hModule = (HMODULE)hinstDLL;
72 /* create private heap */
73 COMCTL32_hHeap = HeapCreate (0, 0x10000, 0);
74 TRACE("Heap created: 0x%x\n", COMCTL32_hHeap);
76 /* add global subclassing atom (used by 'tooltip' and 'updown') */
77 COMCTL32_aSubclass = (LPSTR)(DWORD)GlobalAddAtomA ("CC32SubclassInfo");
78 TRACE("Subclassing atom added: %p\n",
79 COMCTL32_aSubclass);
81 /* register all Win95 common control classes */
82 ANIMATE_Register ();
83 FLATSB_Register ();
84 HEADER_Register ();
85 HOTKEY_Register ();
86 LISTVIEW_Register ();
87 PROGRESS_Register ();
88 STATUS_Register ();
89 TAB_Register ();
90 TOOLBAR_Register ();
91 TOOLTIPS_Register ();
92 TRACKBAR_Register ();
93 TREEVIEW_Register ();
94 UPDOWN_Register ();
96 COMCTL32_dwProcessesAttached++;
97 break;
99 case DLL_PROCESS_DETACH:
100 COMCTL32_dwProcessesAttached--;
101 if (COMCTL32_dwProcessesAttached == 0) {
102 /* unregister all common control classes */
103 ANIMATE_Unregister ();
104 COMBOEX_Unregister ();
105 DATETIME_Unregister ();
106 FLATSB_Unregister ();
107 HEADER_Unregister ();
108 HOTKEY_Unregister ();
109 IPADDRESS_Unregister ();
110 LISTVIEW_Unregister ();
111 MONTHCAL_Unregister ();
112 NATIVEFONT_Unregister ();
113 PAGER_Unregister ();
114 PROGRESS_Unregister ();
115 REBAR_Unregister ();
116 STATUS_Unregister ();
117 TAB_Unregister ();
118 TOOLBAR_Unregister ();
119 TOOLTIPS_Unregister ();
120 TRACKBAR_Unregister ();
121 TREEVIEW_Unregister ();
122 UPDOWN_Unregister ();
124 /* delete global subclassing atom */
125 GlobalDeleteAtom (LOWORD(COMCTL32_aSubclass));
126 TRACE("Subclassing atom deleted: %p\n",
127 COMCTL32_aSubclass);
128 COMCTL32_aSubclass = (LPSTR)NULL;
130 /* destroy private heap */
131 HeapDestroy (COMCTL32_hHeap);
132 TRACE("Heap destroyed: 0x%x\n", COMCTL32_hHeap);
133 COMCTL32_hHeap = (HANDLE)NULL;
135 break;
138 return TRUE;
142 /***********************************************************************
143 * MenuHelp [COMCTL32.2]
145 * PARAMS
146 * uMsg [I] message (WM_MENUSELECT) (see NOTES)
147 * wParam [I] wParam of the message uMsg
148 * lParam [I] lParam of the message uMsg
149 * hMainMenu [I] handle to the application's main menu
150 * hInst [I] handle to the module that contains string resources
151 * hwndStatus [I] handle to the status bar window
152 * lpwIDs [I] pointer to an array of intergers (see NOTES)
154 * RETURNS
155 * No return value
157 * NOTES
158 * The official documentation is incomplete!
159 * This is the correct documentation:
161 * uMsg:
162 * MenuHelp() does NOT handle WM_COMMAND messages! It only handes
163 * WM_MENUSELECT messages.
165 * lpwIDs:
166 * (will be written ...)
169 VOID WINAPI
170 MenuHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu,
171 HINSTANCE hInst, HWND hwndStatus, LPUINT lpwIDs)
173 UINT uMenuID = 0;
175 if (!IsWindow (hwndStatus))
176 return;
178 switch (uMsg) {
179 case WM_MENUSELECT:
180 TRACE("WM_MENUSELECT wParam=0x%X lParam=0x%lX\n",
181 wParam, lParam);
183 if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {
184 /* menu was closed */
185 TRACE("menu was closed!\n");
186 SendMessageA (hwndStatus, SB_SIMPLE, FALSE, 0);
188 else {
189 /* menu item was selected */
190 if (HIWORD(wParam) & MF_POPUP)
191 uMenuID = (UINT)*(lpwIDs+1);
192 else
193 uMenuID = (UINT)LOWORD(wParam);
194 TRACE("uMenuID = %u\n", uMenuID);
196 if (uMenuID) {
197 CHAR szText[256];
199 if (!LoadStringA (hInst, uMenuID, szText, 256))
200 szText[0] = '\0';
202 SendMessageA (hwndStatus, SB_SETTEXTA,
203 255 | SBT_NOBORDERS, (LPARAM)szText);
204 SendMessageA (hwndStatus, SB_SIMPLE, TRUE, 0);
207 break;
209 case WM_COMMAND :
210 TRACE("WM_COMMAND wParam=0x%X lParam=0x%lX\n",
211 wParam, lParam);
212 /* WM_COMMAND is not invalid since it is documented
213 * in the windows api reference. So don't output
214 * any FIXME for WM_COMMAND
216 WARN("We don't care about the WM_COMMAND\n");
217 break;
219 default:
220 FIXME("Invalid Message 0x%x!\n", uMsg);
221 break;
226 /***********************************************************************
227 * ShowHideMenuCtl [COMCTL32.3]
229 * Shows or hides controls and updates the corresponding menu item.
231 * PARAMS
232 * hwnd [I] handle to the client window.
233 * uFlags [I] menu command id.
234 * lpInfo [I] pointer to an array of integers. (See NOTES.)
236 * RETURNS
237 * Success: TRUE
238 * Failure: FALSE
240 * NOTES
241 * The official documentation is incomplete!
242 * This is the correct documentation:
244 * hwnd
245 * Handle to the window that contains the menu and controls.
247 * uFlags
248 * Identifier of the menu item to receive or loose a check mark.
250 * lpInfo
251 * The array of integers contains pairs of values. BOTH values of
252 * the first pair must be the handles to the application's main menu.
253 * Each subsequent pair consists of a menu id and control id.
256 BOOL WINAPI
257 ShowHideMenuCtl (HWND hwnd, UINT uFlags, LPINT lpInfo)
259 LPINT lpMenuId;
261 TRACE("%x, %x, %p\n", hwnd, uFlags, lpInfo);
263 if (lpInfo == NULL)
264 return FALSE;
266 if (!(lpInfo[0]) || !(lpInfo[1]))
267 return FALSE;
269 /* search for control */
270 lpMenuId = &lpInfo[2];
271 while (*lpMenuId != uFlags)
272 lpMenuId += 2;
274 if (GetMenuState (lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) {
275 /* uncheck menu item */
276 CheckMenuItem (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_UNCHECKED);
278 /* hide control */
279 lpMenuId++;
280 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
281 SWP_HIDEWINDOW);
283 else {
284 /* check menu item */
285 CheckMenuItem (lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_CHECKED);
287 /* show control */
288 lpMenuId++;
289 SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
290 SWP_SHOWWINDOW);
293 return TRUE;
297 /***********************************************************************
298 * GetEffectiveClientRect [COMCTL32.4]
300 * PARAMS
301 * hwnd [I] handle to the client window.
302 * lpRect [O] pointer to the rectangle of the client window
303 * lpInfo [I] pointer to an array of integers (see NOTES)
305 * RETURNS
306 * No return value.
308 * NOTES
309 * The official documentation is incomplete!
310 * This is the correct documentation:
312 * lpInfo
313 * (will be written...)
316 VOID WINAPI
317 GetEffectiveClientRect (HWND hwnd, LPRECT lpRect, LPINT lpInfo)
319 RECT rcCtrl;
320 INT *lpRun;
321 HWND hwndCtrl;
323 TRACE("(0x%08lx 0x%08lx 0x%08lx)\n",
324 (DWORD)hwnd, (DWORD)lpRect, (DWORD)lpInfo);
326 GetClientRect (hwnd, lpRect);
327 lpRun = lpInfo;
329 do {
330 lpRun += 2;
331 if (*lpRun == 0)
332 return;
333 lpRun++;
334 hwndCtrl = GetDlgItem (hwnd, *lpRun);
335 if (GetWindowLongA (hwndCtrl, GWL_STYLE) & WS_VISIBLE) {
336 TRACE("control id 0x%x\n", *lpRun);
337 GetWindowRect (hwndCtrl, &rcCtrl);
338 MapWindowPoints ((HWND)0, hwnd, (LPPOINT)&rcCtrl, 2);
339 SubtractRect (lpRect, lpRect, &rcCtrl);
341 lpRun++;
342 } while (*lpRun);
346 /***********************************************************************
347 * DrawStatusTextA [COMCTL32.5][COMCTL32.27]
349 * Draws text with borders, like in a status bar.
351 * PARAMS
352 * hdc [I] handle to the window's display context
353 * lprc [I] pointer to a rectangle
354 * text [I] pointer to the text
355 * style [I] drawing style
357 * RETURNS
358 * No return value.
360 * NOTES
361 * The style variable can have one of the following values:
362 * (will be written ...)
365 VOID WINAPI
366 DrawStatusTextA (HDC hdc, LPRECT lprc, LPCSTR text, UINT style)
368 RECT r = *lprc;
369 UINT border = BDR_SUNKENOUTER;
371 if (style & SBT_POPOUT)
372 border = BDR_RAISEDOUTER;
373 else if (style & SBT_NOBORDERS)
374 border = 0;
376 DrawEdge (hdc, &r, border, BF_RECT|BF_ADJUST|BF_MIDDLE);
378 /* now draw text */
379 if (text) {
380 int oldbkmode = SetBkMode (hdc, TRANSPARENT);
381 r.left += 3;
382 DrawTextA (hdc, text, lstrlenA(text),
383 &r, DT_LEFT|DT_VCENTER|DT_SINGLELINE);
384 if (oldbkmode != TRANSPARENT)
385 SetBkMode(hdc, oldbkmode);
390 /***********************************************************************
391 * DrawStatusTextW [COMCTL32.28]
393 * Draws text with borders, like in a status bar.
395 * PARAMS
396 * hdc [I] handle to the window's display context
397 * lprc [I] pointer to a rectangle
398 * text [I] pointer to the text
399 * style [I] drawing style
401 * RETURNS
402 * No return value.
405 VOID WINAPI
406 DrawStatusTextW (HDC hdc, LPRECT lprc, LPCWSTR text, UINT style)
408 LPSTR p = HEAP_strdupWtoA (GetProcessHeap (), 0, text);
409 DrawStatusTextA (hdc, lprc, p, style);
410 HeapFree (GetProcessHeap (), 0, p );
414 /***********************************************************************
415 * CreateStatusWindowA [COMCTL32.6][COMCTL32.21]
417 * Creates a status bar
419 * PARAMS
420 * style [I] window style
421 * text [I] pointer to the window text
422 * parent [I] handle to the parent window
423 * wid [I] control id of the status bar
425 * RETURNS
426 * Success: handle to the status window
427 * Failure: 0
430 HWND WINAPI
431 CreateStatusWindowA (INT style, LPCSTR text, HWND parent, UINT wid)
433 return CreateWindowA(STATUSCLASSNAMEA, text, style,
434 CW_USEDEFAULT, CW_USEDEFAULT,
435 CW_USEDEFAULT, CW_USEDEFAULT,
436 parent, wid, 0, 0);
440 /***********************************************************************
441 * CreateStatusWindowW [COMCTL32.22] Creates a status bar control
443 * PARAMS
444 * style [I] window style
445 * text [I] pointer to the window text
446 * parent [I] handle to the parent window
447 * wid [I] control id of the status bar
449 * RETURNS
450 * Success: handle to the status window
451 * Failure: 0
454 HWND WINAPI
455 CreateStatusWindowW (INT style, LPCWSTR text, HWND parent, UINT wid)
457 return CreateWindowW(STATUSCLASSNAMEW, text, style,
458 CW_USEDEFAULT, CW_USEDEFAULT,
459 CW_USEDEFAULT, CW_USEDEFAULT,
460 parent, wid, 0, 0);
464 /***********************************************************************
465 * CreateUpDownControl [COMCTL32.16] Creates an up-down control
467 * PARAMS
468 * style [I] window styles
469 * x [I] horizontal position of the control
470 * y [I] vertical position of the control
471 * cx [I] with of the control
472 * cy [I] height of the control
473 * parent [I] handle to the parent window
474 * id [I] the control's identifier
475 * inst [I] handle to the application's module instance
476 * buddy [I] handle to the buddy window, can be NULL
477 * maxVal [I] upper limit of the control
478 * minVal [I] lower limit of the control
479 * curVal [I] current value of the control
481 * RETURNS
482 * Success: handle to the updown control
483 * Failure: 0
486 HWND WINAPI
487 CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
488 HWND parent, INT id, HINSTANCE inst,
489 HWND buddy, INT maxVal, INT minVal, INT curVal)
491 HWND hUD =
492 CreateWindowA (UPDOWN_CLASSA, 0, style, x, y, cx, cy,
493 parent, id, inst, 0);
494 if (hUD) {
495 SendMessageA (hUD, UDM_SETBUDDY, buddy, 0);
496 SendMessageA (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));
497 SendMessageA (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));
500 return hUD;
504 /***********************************************************************
505 * InitCommonControls [COMCTL32.17]
507 * Registers the common controls.
509 * PARAMS
510 * No parameters.
512 * RETURNS
513 * No return values.
515 * NOTES
516 * This function is just a dummy.
517 * The Win95 controls are registered at the DLL's initialization.
518 * To register other controls InitCommonControlsEx() must be used.
521 VOID WINAPI
522 InitCommonControls (void)
527 /***********************************************************************
528 * InitCommonControlsEx [COMCTL32.81]
530 * Registers the common controls.
532 * PARAMS
533 * lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
535 * RETURNS
536 * Success: TRUE
537 * Failure: FALSE
539 * NOTES
540 * Only the additinal common controls are registered by this function.
541 * The Win95 controls are registered at the DLL's initialization.
544 BOOL WINAPI
545 InitCommonControlsEx (LPINITCOMMONCONTROLSEX lpInitCtrls)
547 INT cCount;
548 DWORD dwMask;
550 if (!lpInitCtrls)
551 return FALSE;
552 if (lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
553 return FALSE;
555 TRACE("(0x%08lx)\n", lpInitCtrls->dwICC);
557 for (cCount = 0; cCount < 32; cCount++) {
558 dwMask = 1 << cCount;
559 if (!(lpInitCtrls->dwICC & dwMask))
560 continue;
562 switch (lpInitCtrls->dwICC & dwMask) {
563 /* dummy initialization */
564 case ICC_ANIMATE_CLASS:
565 case ICC_BAR_CLASSES:
566 case ICC_LISTVIEW_CLASSES:
567 case ICC_TREEVIEW_CLASSES:
568 case ICC_TAB_CLASSES:
569 case ICC_UPDOWN_CLASS:
570 case ICC_PROGRESS_CLASS:
571 case ICC_HOTKEY_CLASS:
572 break;
574 /* advanced classes - not included in Win95 */
575 case ICC_DATE_CLASSES:
576 MONTHCAL_Register ();
577 DATETIME_Register ();
578 break;
580 case ICC_USEREX_CLASSES:
581 COMBOEX_Register ();
582 break;
584 case ICC_COOL_CLASSES:
585 REBAR_Register ();
586 break;
588 case ICC_INTERNET_CLASSES:
589 IPADDRESS_Register ();
590 break;
592 case ICC_PAGESCROLLER_CLASS:
593 PAGER_Register ();
594 break;
596 case ICC_NATIVEFNTCTL_CLASS:
597 NATIVEFONT_Register ();
598 break;
600 default:
601 FIXME("Unknown class! dwICC=0x%lX\n", dwMask);
602 break;
606 return TRUE;
610 /***********************************************************************
611 * CreateToolbarEx [COMCTL32.32] Creates a tool bar window
613 * PARAMS
614 * hwnd
615 * style
616 * wID
617 * nBitmaps
618 * hBMInst
619 * wBMID
620 * lpButtons
621 * iNumButtons
622 * dxButton
623 * dyButton
624 * dxBitmap
625 * dyBitmap
626 * uStructSize
628 * RETURNS
629 * Success: handle to the tool bar control
630 * Failure: 0
633 HWND WINAPI
634 CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
635 HINSTANCE hBMInst, UINT wBMID, LPCTBBUTTON lpButtons,
636 INT iNumButtons, INT dxButton, INT dyButton,
637 INT dxBitmap, INT dyBitmap, UINT uStructSize)
639 HWND hwndTB =
640 CreateWindowExA (0, TOOLBARCLASSNAMEA, "", style, 0, 0, 0, 0,
641 hwnd, (HMENU)wID, 0, NULL);
642 if(hwndTB) {
643 TBADDBITMAP tbab;
645 SendMessageA (hwndTB, TB_BUTTONSTRUCTSIZE,
646 (WPARAM)uStructSize, 0);
648 /* set bitmap and button size */
649 /*If CreateToolbarEx receive 0, windows set default values*/
650 if (dyBitmap < 0)
651 dyBitmap = 15;
652 if (dxBitmap < 0)
653 dxBitmap = 16;
655 SendMessageA (hwndTB, TB_SETBITMAPSIZE, 0,
656 MAKELPARAM((WORD)dxBitmap, (WORD)dyBitmap));
657 SendMessageA (hwndTB, TB_SETBUTTONSIZE, 0,
658 MAKELPARAM((WORD)dxButton, (WORD)dyButton));
661 /* add bitmaps */
662 if (nBitmaps > 0)
664 tbab.hInst = hBMInst;
665 tbab.nID = wBMID;
667 SendMessageA (hwndTB, TB_ADDBITMAP,
668 (WPARAM)nBitmaps, (LPARAM)&tbab);
670 /* add buttons */
671 if(iNumButtons > 0)
672 SendMessageA (hwndTB, TB_ADDBUTTONSA,
673 (WPARAM)iNumButtons, (LPARAM)lpButtons);
676 return hwndTB;
680 /***********************************************************************
681 * CreateMappedBitmap [COMCTL32.8]
683 * PARAMS
684 * hInstance [I]
685 * idBitmap [I]
686 * wFlags [I]
687 * lpColorMap [I]
688 * iNumMaps [I]
690 * RETURNS
691 * Success: handle to the new bitmap
692 * Failure: 0
695 HBITMAP WINAPI
696 CreateMappedBitmap (HINSTANCE hInstance, INT idBitmap, UINT wFlags,
697 LPCOLORMAP lpColorMap, INT iNumMaps)
699 HGLOBAL hglb;
700 HRSRC hRsrc;
701 LPBITMAPINFOHEADER lpBitmap, lpBitmapInfo;
702 UINT nSize, nColorTableSize;
703 RGBQUAD *pColorTable;
704 INT iColor, i, iMaps, nWidth, nHeight;
705 HDC hdcScreen;
706 HBITMAP hbm;
707 LPCOLORMAP sysColorMap;
708 COLORREF cRef;
709 COLORMAP internalColorMap[4] =
710 {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
712 /* initialize pointer to colortable and default color table */
713 if (lpColorMap) {
714 iMaps = iNumMaps;
715 sysColorMap = lpColorMap;
717 else {
718 internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT);
719 internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW);
720 internalColorMap[2].to = GetSysColor (COLOR_BTNFACE);
721 internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT);
722 iMaps = 4;
723 sysColorMap = (LPCOLORMAP)internalColorMap;
726 hRsrc = FindResourceA (hInstance, (LPSTR)idBitmap, RT_BITMAPA);
727 if (hRsrc == 0)
728 return 0;
729 hglb = LoadResource (hInstance, hRsrc);
730 if (hglb == 0)
731 return 0;
732 lpBitmap = (LPBITMAPINFOHEADER)LockResource (hglb);
733 if (lpBitmap == NULL)
734 return 0;
736 nColorTableSize = (1 << lpBitmap->biBitCount);
737 nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
738 lpBitmapInfo = (LPBITMAPINFOHEADER)GlobalAlloc (GMEM_FIXED, nSize);
739 if (lpBitmapInfo == NULL)
740 return 0;
741 RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);
743 pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo)+(UINT)lpBitmapInfo->biSize);
745 for (iColor = 0; iColor < nColorTableSize; iColor++) {
746 for (i = 0; i < iMaps; i++) {
747 cRef = RGB(pColorTable[iColor].rgbRed,
748 pColorTable[iColor].rgbGreen,
749 pColorTable[iColor].rgbBlue);
750 if ( cRef == sysColorMap[i].from) {
751 #if 0
752 if (wFlags & CBS_MASKED) {
753 if (sysColorMap[i].to != COLOR_BTNTEXT)
754 pColorTable[iColor] = RGB(255, 255, 255);
756 else
757 #endif
758 pColorTable[iColor].rgbBlue = GetBValue(sysColorMap[i].to);
759 pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);
760 pColorTable[iColor].rgbRed = GetRValue(sysColorMap[i].to);
761 break;
765 nWidth = (INT)lpBitmapInfo->biWidth;
766 nHeight = (INT)lpBitmapInfo->biHeight;
767 hdcScreen = GetDC ((HWND)0);
768 hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
769 if (hbm) {
770 HDC hdcDst = CreateCompatibleDC (hdcScreen);
771 HBITMAP hbmOld = SelectObject (hdcDst, hbm);
772 LPBYTE lpBits = (LPBYTE)(lpBitmap + 1);
773 lpBits += (1 << (lpBitmapInfo->biBitCount)) * sizeof(RGBQUAD);
774 StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
775 lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
776 SRCCOPY);
777 SelectObject (hdcDst, hbmOld);
778 DeleteDC (hdcDst);
780 ReleaseDC ((HWND)0, hdcScreen);
781 GlobalFree ((HGLOBAL)lpBitmapInfo);
782 FreeResource (hglb);
784 return hbm;
788 /***********************************************************************
789 * CreateToolbar [COMCTL32.7] Creates a tool bar control
791 * PARAMS
792 * hwnd
793 * style
794 * wID
795 * nBitmaps
796 * hBMInst
797 * wBMID
798 * lpButtons
799 * iNumButtons
801 * RETURNS
802 * Success: handle to the tool bar control
803 * Failure: 0
805 * NOTES
806 * Do not use this functions anymore. Use CreateToolbarEx instead.
809 HWND WINAPI
810 CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
811 HINSTANCE hBMInst, UINT wBMID,
812 LPCOLDTBBUTTON lpButtons,INT iNumButtons)
814 return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
815 hBMInst, wBMID, (LPCTBBUTTON)lpButtons,
816 iNumButtons, 0, 0, 0, 0, sizeof (OLDTBBUTTON));
820 /***********************************************************************
821 * DllGetVersion [COMCTL32.25]
823 * Retrieves version information of the 'COMCTL32.DLL'
825 * PARAMS
826 * pdvi [O] pointer to version information structure.
828 * RETURNS
829 * Success: S_OK
830 * Failure: E_INVALIDARG
832 * NOTES
833 * Returns version of a comctl32.dll from IE4.01 SP1.
836 HRESULT WINAPI
837 COMCTL32_DllGetVersion (DLLVERSIONINFO *pdvi)
839 if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
840 WARN("wrong DLLVERSIONINFO size from app");
841 return E_INVALIDARG;
844 pdvi->dwMajorVersion = 5;
845 pdvi->dwMinorVersion = 0;
846 pdvi->dwBuildNumber = 2919;
847 pdvi->dwPlatformID = 6304;
849 TRACE("%lu.%lu.%lu.%lu\n",
850 pdvi->dwMajorVersion, pdvi->dwMinorVersion,
851 pdvi->dwBuildNumber, pdvi->dwPlatformID);
853 return S_OK;
856 /***********************************************************************
857 * DllInstall (COMCTL32.@)
859 HRESULT WINAPI COMCTL32_DllInstall(BOOL bInstall, LPCWSTR cmdline)
861 FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
862 debugstr_w(cmdline));
864 return S_OK;
868 typedef struct __TRACKINGLIST {
869 TRACKMOUSEEVENT tme;
870 POINT pos; /* center of hover rectangle */
871 INT iHoverTime; /* elapsed time the cursor has been inside of the hover rect */
872 } _TRACKINGLIST;
874 static _TRACKINGLIST TrackingList[10];
875 static int iTrackMax = 0;
876 static UINT_PTR timer;
877 static const INT iTimerInterval = 50; /* msec for timer interval */
879 /* FIXME: need to implement WM_NCMOUSELEAVE and WM_NCMOUSEHOVER for */
880 /* TrackMouseEventProc and _TrackMouseEvent */
881 static void CALLBACK TrackMouseEventProc(HWND hwndUnused, UINT uMsg, UINT_PTR idEvent,
882 DWORD dwTime)
884 int i = 0;
885 POINT pos;
886 HWND hwnd;
887 INT hoverwidth = 0, hoverheight = 0;
889 GetCursorPos(&pos);
890 hwnd = WindowFromPoint(pos);
892 SystemParametersInfoA(SPI_GETMOUSEHOVERWIDTH, 0, &hoverwidth, 0);
893 SystemParametersInfoA(SPI_GETMOUSEHOVERHEIGHT, 0, &hoverheight, 0);
895 /* loop through tracking events we are processing */
896 while (i < iTrackMax) {
897 /* see if this tracking event is looking for TME_LEAVE and that the */
898 /* mouse has left the window */
899 if ((TrackingList[i].tme.dwFlags & TME_LEAVE) &&
900 (TrackingList[i].tme.hwndTrack != hwnd)) {
901 PostMessageA(TrackingList[i].tme.hwndTrack, WM_MOUSELEAVE, 0, 0);
903 /* remove the TME_LEAVE flag */
904 TrackingList[i].tme.dwFlags ^= TME_LEAVE;
907 /* see if we are tracking hovering for this hwnd */
908 if(TrackingList[i].tme.dwFlags & TME_HOVER) {
909 /* add the timer interval to the hovering time */
910 TrackingList[i].iHoverTime+=iTimerInterval;
912 /* has the cursor moved outside the rectangle centered around pos? */
913 if((abs(pos.x - TrackingList[i].pos.x) > (hoverwidth / 2.0))
914 || (abs(pos.y - TrackingList[i].pos.y) > (hoverheight / 2.0)))
916 /* record this new position as the current position and reset */
917 /* the iHoverTime variable to 0 */
918 TrackingList[i].pos = pos;
919 TrackingList[i].iHoverTime = 0;
922 /* has the mouse hovered long enough? */
923 if(TrackingList[i].iHoverTime <= TrackingList[i].tme.dwHoverTime)
925 PostMessageA(TrackingList[i].tme.hwndTrack, WM_MOUSEHOVER, 0, 0);
927 /* stop tracking mouse hover */
928 TrackingList[i].tme.dwFlags ^= TME_HOVER;
932 /* see if we are still tracking TME_HOVER or TME_LEAVE for this entry */
933 if((TrackingList[i].tme.dwFlags & TME_HOVER) ||
934 (TrackingList[i].tme.dwFlags & TME_LEAVE)) {
935 i++;
936 } else { /* remove this entry from the tracking list */
937 TrackingList[i] = TrackingList[--iTrackMax];
941 /* stop the timer if the tracking list is empty */
942 if(iTrackMax == 0) {
943 KillTimer(0, timer);
944 timer = 0;
948 /***********************************************************************
949 * _TrackMouseEvent [COMCTL32.25]
951 * Requests notification of mouse events
953 * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
954 * to the hwnd specified in the ptme structure. After the event message
955 * is posted to the hwnd, the entry in the queue is removed.
957 * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
958 * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
959 * immediately and the TME_LEAVE flag being ignored.
961 * PARAMS
962 * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
964 * RETURNS
965 * Success: non-zero
966 * Failure: zero
970 BOOL WINAPI
971 _TrackMouseEvent (TRACKMOUSEEVENT *ptme)
973 DWORD flags = 0;
974 int i = 0;
975 BOOL cancel = 0, hover = 0, leave = 0, query = 0;
976 HWND hwnd;
977 POINT pos;
979 pos.x = 0;
980 pos.y = 0;
982 TRACE("%lx, %lx, %x, %lx\n", ptme->cbSize, ptme->dwFlags, ptme->hwndTrack, ptme->dwHoverTime);
984 if (ptme->cbSize != sizeof(TRACKMOUSEEVENT)) {
985 WARN("wrong TRACKMOUSEEVENT size from app");
986 SetLastError(ERROR_INVALID_PARAMETER); /* FIXME not sure if this is correct */
987 return FALSE;
990 flags = ptme->dwFlags;
992 /* if HOVER_DEFAULT was specified replace this with the systems current value */
993 if(ptme->dwHoverTime == HOVER_DEFAULT)
994 SystemParametersInfoA(SPI_GETMOUSEHOVERTIME, 0, &(ptme->dwHoverTime), 0);
996 GetCursorPos(&pos);
997 hwnd = WindowFromPoint(pos);
999 if ( flags & TME_CANCEL ) {
1000 flags &= ~ TME_CANCEL;
1001 cancel = 1;
1004 if ( flags & TME_HOVER ) {
1005 flags &= ~ TME_HOVER;
1006 hover = 1;
1009 if ( flags & TME_LEAVE ) {
1010 flags &= ~ TME_LEAVE;
1011 leave = 1;
1014 /* fill the TRACKMOUSEEVENT struct with the current tracking for the given hwnd */
1015 if ( flags & TME_QUERY ) {
1016 flags &= ~ TME_QUERY;
1017 query = 1;
1018 i = 0;
1020 /* Find the tracking list entry with the matching hwnd */
1021 while((i < iTrackMax) && (TrackingList[i].tme.hwndTrack != ptme->hwndTrack)) {
1022 i++;
1025 /* hwnd found, fill in the ptme struct */
1026 if(i < iTrackMax)
1027 *ptme = TrackingList[i].tme;
1028 else
1029 ptme->dwFlags = 0;
1031 return TRUE; /* return here, TME_QUERY is retrieving information */
1034 if ( flags )
1035 FIXME("Unknown flag(s) %08lx\n", flags );
1037 if(cancel) {
1038 /* find a matching hwnd if one exists */
1039 i = 0;
1041 while((i < iTrackMax) && (TrackingList[i].tme.hwndTrack != ptme->hwndTrack)) {
1042 i++;
1045 if(i < iTrackMax) {
1046 TrackingList[i].tme.dwFlags &= ~(ptme->dwFlags & ~TME_CANCEL);
1048 /* if we aren't tracking on hover or leave remove this entry */
1049 if(!((TrackingList[i].tme.dwFlags & TME_HOVER) ||
1050 (TrackingList[i].tme.dwFlags & TME_LEAVE)))
1052 TrackingList[i] = TrackingList[--iTrackMax];
1054 if(iTrackMax == 0) {
1055 KillTimer(0, timer);
1056 timer = 0;
1060 } else {
1061 /* see if hwndTrack isn't the current window */
1062 if(ptme->hwndTrack != hwnd) {
1063 if(leave) {
1064 PostMessageA(ptme->hwndTrack, WM_MOUSELEAVE, 0, 0);
1066 } else {
1067 /* See if this hwnd is already being tracked and update the tracking flags */
1068 for(i = 0; i < iTrackMax; i++) {
1069 if(TrackingList[i].tme.hwndTrack == ptme->hwndTrack) {
1070 if(hover) {
1071 TrackingList[i].tme.dwFlags |= TME_HOVER;
1072 TrackingList[i].tme.dwHoverTime = ptme->dwHoverTime;
1075 if(leave)
1076 TrackingList[i].tme.dwFlags |= TME_LEAVE;
1078 /* reset iHoverTime as per winapi specs */
1079 TrackingList[i].iHoverTime = 0;
1081 return TRUE;
1085 /* if the tracking list is full return FALSE */
1086 if (iTrackMax == sizeof (TrackingList) / sizeof(*TrackingList)) {
1087 return FALSE;
1090 /* Adding new mouse event to the tracking list */
1091 TrackingList[iTrackMax].tme = *ptme;
1093 /* Initialize HoverInfo variables even if not hover tracking */
1094 TrackingList[iTrackMax].iHoverTime = 0;
1095 TrackingList[iTrackMax].pos = pos;
1097 iTrackMax++;
1099 if (!timer) {
1100 timer = SetTimer(0, 0, iTimerInterval, TrackMouseEventProc);
1105 return TRUE;
1109 /*************************************************************************
1110 * GetMUILanguage [COMCTL32.39]
1112 * FIXME: What's this supposed to do? Apparently some i18n thing.
1115 LANGID WINAPI GetMUILanguage (VOID)
1117 return COMCTL32_uiLang;
1121 /*************************************************************************
1122 * InitMUILanguage [COMCTL32.85]
1124 * FIXME: What's this supposed to do? Apparently some i18n thing.
1128 VOID WINAPI InitMUILanguage (LANGID uiLang)
1130 COMCTL32_uiLang = uiLang;