-/*\r
- * Common controls functions\r
- *\r
- * Copyright 1997 Dimitrie O. Paun\r
- * Copyright 1998,2000 Eric Kohl\r
- *\r
- * This library is free software; you can redistribute it and/or\r
- * modify it under the terms of the GNU Lesser General Public\r
- * License as published by the Free Software Foundation; either\r
- * version 2.1 of the License, or (at your option) any later version.\r
- *\r
- * This library is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
- * Lesser General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU Lesser General Public\r
- * License along with this library; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\r
- *\r
- * NOTES\r
- * \r
- * This code was audited for completeness against the documented features\r
- * of Comctl32.dll version 6.0 on Oct. 21, 2002, by Christian Neumair.\r
- *\r
- * Unless otherwise noted, we believe this code to be complete, as per\r
- * the specification mentioned above.\r
- * If you discover missing features, or bugs, please note them below.\r
- *\r
- * TODO\r
- * -- implement GetMUILanguage + InitMUILanguage\r
- * -- LibMain => DLLMain ("DLLMain takes over the functionality of both the\r
- * LibMain and the WEP function.", MSDN)\r
- * -- finish NOTES for MenuHelp, GetEffectiveClientRect and GetStatusTextW\r
- * -- FIXMEs + BUGS (search for them)\r
- *\r
- * Control Classes\r
- * -- ICC_ANIMATE_CLASS\r
- * -- ICC_BAR_CLASSES\r
- * -- ICC_COOL_CLASSES\r
- * -- ICC_DATE_CLASSES\r
- * -- ICC_HOTKEY_CLASS\r
- * -- ICC_INTERNET_CLASSES\r
- * -- ICC_LINK_CLASS\r
- * -- ICC_LISTVIEW_CLASSES\r
- * -- ICC_NATIVEFNTCTL_CLASS\r
- * -- ICC_PAGESCROLLER_CLASS\r
- * -- ICC_PROGRESS_CLASS\r
- * -- ICC_STANDARD_CLASSES (not yet implemented)\r
- * -- ICC_TAB_CLASSES\r
- * -- ICC_TREEVIEW_CLASSES\r
- * -- ICC_UPDOWN_CLASS\r
- * -- ICC_USEREX_CLASSES\r
- * -- ICC_WIN95_CLASSES\r
- */\r
-\r
-#include <stdarg.h>\r
-#include <string.h>\r
-#include <stdlib.h>\r
-\r
-#include "windef.h"\r
-#include "winbase.h"\r
-#include "wingdi.h"\r
-#include "winuser.h"\r
-#include "winnls.h"\r
-#include "commctrl.h"\r
-#include "winerror.h"\r
-#include "winreg.h"\r
-#define NO_SHLWAPI_STREAM\r
-#include "shlwapi.h"\r
-#include "comctl32.h"\r
-#include "wine/debug.h"\r
-\r
-WINE_DEFAULT_DEBUG_CHANNEL(commctrl);\r
-\r
-LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);\r
-\r
-LPWSTR COMCTL32_wSubclass = NULL;\r
-HMODULE COMCTL32_hModule = 0;\r
-LANGID COMCTL32_uiLang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);\r
-HBRUSH COMCTL32_hPattern55AABrush = NULL;\r
-COMCTL32_SysColor comctl32_color;\r
-\r
-static HBITMAP COMCTL32_hPattern55AABitmap = NULL;\r
-\r
-static const WORD wPattern55AA[] =\r
-{\r
- 0x5555, 0xaaaa, 0x5555, 0xaaaa,\r
- 0x5555, 0xaaaa, 0x5555, 0xaaaa\r
-};\r
-\r
-static const WCHAR strCC32SubclassInfo[] = {\r
- 'C','C','3','2','S','u','b','c','l','a','s','s','I','n','f','o',0\r
-};\r
-\r
-/***********************************************************************\r
- * DllMain [Internal]\r
- *\r
- * Initializes the internal 'COMCTL32.DLL'.\r
- *\r
- * PARAMS\r
- * hinstDLL [I] handle to the 'dlls' instance\r
- * fdwReason [I]\r
- * lpvReserved [I] reserverd, must be NULL\r
- *\r
- * RETURNS\r
- * Success: TRUE\r
- * Failure: FALSE\r
- */\r
-\r
-BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)\r
-{\r
- TRACE("%p,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);\r
-\r
- switch (fdwReason) {\r
- case DLL_PROCESS_ATTACH:\r
- DisableThreadLibraryCalls(hinstDLL);\r
-\r
- COMCTL32_hModule = (HMODULE)hinstDLL;\r
-\r
- /* add global subclassing atom (used by 'tooltip' and 'updown') */\r
- COMCTL32_wSubclass = (LPWSTR)(DWORD)GlobalAddAtomW (strCC32SubclassInfo);\r
- TRACE("Subclassing atom added: %p\n", COMCTL32_wSubclass);\r
-\r
- /* create local pattern brush */\r
- COMCTL32_hPattern55AABitmap = CreateBitmap (8, 8, 1, 1, wPattern55AA);\r
- COMCTL32_hPattern55AABrush = CreatePatternBrush (COMCTL32_hPattern55AABitmap);\r
-\r
- /* Get all the colors at DLL load */\r
- COMCTL32_RefreshSysColors();\r
-\r
- /* register all Win95 common control classes */\r
- ANIMATE_Register ();\r
- FLATSB_Register ();\r
- HEADER_Register ();\r
- HOTKEY_Register ();\r
- LISTVIEW_Register ();\r
- PROGRESS_Register ();\r
- STATUS_Register ();\r
- SYSLINK_Register ();\r
- TAB_Register ();\r
- TOOLBAR_Register ();\r
- TOOLTIPS_Register ();\r
- TRACKBAR_Register ();\r
- TREEVIEW_Register ();\r
- UPDOWN_Register ();\r
- break;\r
-\r
- case DLL_PROCESS_DETACH:\r
- /* unregister all common control classes */\r
- ANIMATE_Unregister ();\r
- COMBOEX_Unregister ();\r
- DATETIME_Unregister ();\r
- FLATSB_Unregister ();\r
- HEADER_Unregister ();\r
- HOTKEY_Unregister ();\r
- IPADDRESS_Unregister ();\r
- LISTVIEW_Unregister ();\r
- MONTHCAL_Unregister ();\r
- NATIVEFONT_Unregister ();\r
- PAGER_Unregister ();\r
- PROGRESS_Unregister ();\r
- REBAR_Unregister ();\r
- STATUS_Unregister ();\r
- SYSLINK_Unregister ();\r
- TAB_Unregister ();\r
- TOOLBAR_Unregister ();\r
- TOOLTIPS_Unregister ();\r
- TRACKBAR_Unregister ();\r
- TREEVIEW_Unregister ();\r
- UPDOWN_Unregister ();\r
-\r
- /* delete local pattern brush */\r
- DeleteObject (COMCTL32_hPattern55AABrush);\r
- COMCTL32_hPattern55AABrush = NULL;\r
- DeleteObject (COMCTL32_hPattern55AABitmap);\r
- COMCTL32_hPattern55AABitmap = NULL;\r
-\r
- /* delete global subclassing atom */\r
- GlobalDeleteAtom (LOWORD(COMCTL32_wSubclass));\r
- TRACE("Subclassing atom deleted: %p\n", COMCTL32_wSubclass);\r
- COMCTL32_wSubclass = NULL;\r
- break;\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
-\r
-/***********************************************************************\r
- * MenuHelp [COMCTL32.2]\r
- *\r
- * Handles the setting of status bar help messages when the user\r
- * selects menu items.\r
- *\r
- * PARAMS\r
- * uMsg [I] message (WM_MENUSELECT) (see NOTES)\r
- * wParam [I] wParam of the message uMsg\r
- * lParam [I] lParam of the message uMsg\r
- * hMainMenu [I] handle to the application's main menu\r
- * hInst [I] handle to the module that contains string resources\r
- * hwndStatus [I] handle to the status bar window\r
- * lpwIDs [I] pointer to an array of integers (see NOTES)\r
- *\r
- * RETURNS\r
- * No return value\r
- *\r
- * NOTES\r
- * The official documentation is incomplete!\r
- * This is the correct documentation:\r
- *\r
- * uMsg:\r
- * MenuHelp() does NOT handle WM_COMMAND messages! It only handles\r
- * WM_MENUSELECT messages.\r
- *\r
- * lpwIDs:\r
- * (will be written ...)\r
- */\r
-\r
-VOID WINAPI\r
-MenuHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu,\r
- HINSTANCE hInst, HWND hwndStatus, UINT* lpwIDs)\r
-{\r
- UINT uMenuID = 0;\r
-\r
- if (!IsWindow (hwndStatus))\r
- return;\r
-\r
- switch (uMsg) {\r
- case WM_MENUSELECT:\r
- TRACE("WM_MENUSELECT wParam=0x%X lParam=0x%lX\n",\r
- wParam, lParam);\r
-\r
- if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {\r
- /* menu was closed */\r
- TRACE("menu was closed!\n");\r
- SendMessageW (hwndStatus, SB_SIMPLE, FALSE, 0);\r
- }\r
- else {\r
- /* menu item was selected */\r
- if (HIWORD(wParam) & MF_POPUP)\r
- uMenuID = (UINT)*(lpwIDs+1);\r
- else\r
- uMenuID = (UINT)LOWORD(wParam);\r
- TRACE("uMenuID = %u\n", uMenuID);\r
-\r
- if (uMenuID) {\r
- WCHAR szText[256];\r
-\r
- if (!LoadStringW (hInst, uMenuID, szText, sizeof(szText)/sizeof(szText[0])))\r
- szText[0] = '\0';\r
-\r
- SendMessageW (hwndStatus, SB_SETTEXTW,\r
- 255 | SBT_NOBORDERS, (LPARAM)szText);\r
- SendMessageW (hwndStatus, SB_SIMPLE, TRUE, 0);\r
- }\r
- }\r
- break;\r
-\r
- case WM_COMMAND :\r
- TRACE("WM_COMMAND wParam=0x%X lParam=0x%lX\n",\r
- wParam, lParam);\r
- /* WM_COMMAND is not invalid since it is documented\r
- * in the windows api reference. So don't output\r
- * any FIXME for WM_COMMAND\r
- */\r
- WARN("We don't care about the WM_COMMAND\n");\r
- break;\r
-\r
- default:\r
- FIXME("Invalid Message 0x%x!\n", uMsg);\r
- break;\r
- }\r
-}\r
-\r
-\r
-/***********************************************************************\r
- * ShowHideMenuCtl [COMCTL32.3]\r
- *\r
- * Shows or hides controls and updates the corresponding menu item.\r
- *\r
- * PARAMS\r
- * hwnd [I] handle to the client window.\r
- * uFlags [I] menu command id.\r
- * lpInfo [I] pointer to an array of integers. (See NOTES.)\r
- *\r
- * RETURNS\r
- * Success: TRUE\r
- * Failure: FALSE\r
- *\r
- * NOTES\r
- * The official documentation is incomplete!\r
- * This is the correct documentation:\r
- *\r
- * hwnd\r
- * Handle to the window that contains the menu and controls.\r
- *\r
- * uFlags\r
- * Identifier of the menu item to receive or lose a check mark.\r
- *\r
- * lpInfo\r
- * The array of integers contains pairs of values. BOTH values of\r
- * the first pair must be the handles to the application's main menu.\r
- * Each subsequent pair consists of a menu id and control id.\r
- */\r
-\r
-BOOL WINAPI\r
-ShowHideMenuCtl (HWND hwnd, UINT uFlags, LPINT lpInfo)\r
-{\r
- LPINT lpMenuId;\r
-\r
- TRACE("%p, %x, %p\n", hwnd, uFlags, lpInfo);\r
-\r
- if (lpInfo == NULL)\r
- return FALSE;\r
-\r
- if (!(lpInfo[0]) || !(lpInfo[1]))\r
- return FALSE;\r
-\r
- /* search for control */\r
- lpMenuId = &lpInfo[2];\r
- while (*lpMenuId != uFlags)\r
- lpMenuId += 2;\r
-\r
- if (GetMenuState ((HMENU)lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) {\r
- /* uncheck menu item */\r
- CheckMenuItem ((HMENU)lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_UNCHECKED);\r
-\r
- /* hide control */\r
- lpMenuId++;\r
- SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,\r
- SWP_HIDEWINDOW);\r
- }\r
- else {\r
- /* check menu item */\r
- CheckMenuItem ((HMENU)lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_CHECKED);\r
-\r
- /* show control */\r
- lpMenuId++;\r
- SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,\r
- SWP_SHOWWINDOW);\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
-\r
-/***********************************************************************\r
- * GetEffectiveClientRect [COMCTL32.4]\r
- *\r
- * Calculates the coordinates of a rectangle in the client area.\r
- *\r
- * PARAMS\r
- * hwnd [I] handle to the client window.\r
- * lpRect [O] pointer to the rectangle of the client window\r
- * lpInfo [I] pointer to an array of integers (see NOTES)\r
- *\r
- * RETURNS\r
- * No return value.\r
- *\r
- * NOTES\r
- * The official documentation is incomplete!\r
- * This is the correct documentation:\r
- *\r
- * lpInfo\r
- * (will be written ...)\r
- */\r
-\r
-VOID WINAPI\r
-GetEffectiveClientRect (HWND hwnd, LPRECT lpRect, LPINT lpInfo)\r
-{\r
- RECT rcCtrl;\r
- INT *lpRun;\r
- HWND hwndCtrl;\r
-\r
- TRACE("(0x%08lx 0x%08lx 0x%08lx)\n",\r
- (DWORD)hwnd, (DWORD)lpRect, (DWORD)lpInfo);\r
-\r
- GetClientRect (hwnd, lpRect);\r
- lpRun = lpInfo;\r
-\r
- do {\r
- lpRun += 2;\r
- if (*lpRun == 0)\r
- return;\r
- lpRun++;\r
- hwndCtrl = GetDlgItem (hwnd, *lpRun);\r
- if (GetWindowLongW (hwndCtrl, GWL_STYLE) & WS_VISIBLE) {\r
- TRACE("control id 0x%x\n", *lpRun);\r
- GetWindowRect (hwndCtrl, &rcCtrl);\r
- MapWindowPoints (NULL, hwnd, (LPPOINT)&rcCtrl, 2);\r
- SubtractRect (lpRect, lpRect, &rcCtrl);\r
- }\r
- lpRun++;\r
- } while (*lpRun);\r
-}\r
-\r
-\r
-/***********************************************************************\r
- * DrawStatusTextW [COMCTL32.@]\r
- *\r
- * Draws text with borders, like in a status bar.\r
- *\r
- * PARAMS\r
- * hdc [I] handle to the window's display context\r
- * lprc [I] pointer to a rectangle\r
- * text [I] pointer to the text\r
- * style [I] drawing style\r
- *\r
- * RETURNS\r
- * No return value.\r
- *\r
- * NOTES\r
- * The style variable can have one of the following values:\r
- * (will be written ...)\r
- */\r
-\r
-void WINAPI DrawStatusTextW (HDC hdc, LPRECT lprc, LPCWSTR text, UINT style)\r
-{\r
- RECT r = *lprc;\r
- UINT border = BDR_SUNKENOUTER;\r
-\r
- if (style & SBT_POPOUT)\r
- border = BDR_RAISEDOUTER;\r
- else if (style & SBT_NOBORDERS)\r
- border = 0;\r
-\r
- DrawEdge (hdc, &r, border, BF_RECT|BF_ADJUST);\r
-\r
- /* now draw text */\r
- if (text) {\r
- int oldbkmode = SetBkMode (hdc, TRANSPARENT);\r
- UINT align = DT_LEFT;\r
- if (*text == L'\t') {\r
- text++;\r
- align = DT_CENTER;\r
- if (*text == L'\t') {\r
- text++;\r
- align = DT_RIGHT;\r
- }\r
- }\r
- r.left += 3;\r
- if (style & SBT_RTLREADING)\r
- FIXME("Unsupported RTL style!\n");\r
- DrawTextW (hdc, text, -1, &r, align|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX);\r
- SetBkMode(hdc, oldbkmode);\r
- }\r
-}\r
-\r
-\r
-/***********************************************************************\r
- * DrawStatusText [COMCTL32.@]\r
- * DrawStatusTextA [COMCTL32.5]\r
- *\r
- * Draws text with borders, like in a status bar.\r
- *\r
- * PARAMS\r
- * hdc [I] handle to the window's display context\r
- * lprc [I] pointer to a rectangle\r
- * text [I] pointer to the text\r
- * style [I] drawing style\r
- *\r
- * RETURNS\r
- * No return value.\r
- */\r
-\r
-void WINAPI DrawStatusTextA (HDC hdc, LPRECT lprc, LPCSTR text, UINT style)\r
-{\r
- INT len;\r
- LPWSTR textW = NULL;\r
-\r
- if ( text ) {\r
- if ( (len = MultiByteToWideChar( CP_ACP, 0, text, -1, NULL, 0 )) ) {\r
- if ( (textW = Alloc( len * sizeof(WCHAR) )) )\r
- MultiByteToWideChar( CP_ACP, 0, text, -1, textW, len );\r
- }\r
- }\r
- DrawStatusTextW( hdc, lprc, textW, style );\r
- Free( textW );\r
-}\r
-\r
-\r
-/***********************************************************************\r
- * CreateStatusWindow [COMCTL32.@]\r
- * CreateStatusWindowA [COMCTL32.6]\r
- *\r
- * Creates a status bar\r
- *\r
- * PARAMS\r
- * style [I] window style\r
- * text [I] pointer to the window text\r
- * parent [I] handle to the parent window\r
- * wid [I] control id of the status bar\r
- *\r
- * RETURNS\r
- * Success: handle to the status window\r
- * Failure: 0\r
- */\r
-\r
-HWND WINAPI\r
-CreateStatusWindowA (LONG style, LPCSTR text, HWND parent, UINT wid)\r
-{\r
- return CreateWindowA(STATUSCLASSNAMEA, text, style,\r
- CW_USEDEFAULT, CW_USEDEFAULT,\r
- CW_USEDEFAULT, CW_USEDEFAULT,\r
- parent, (HMENU)wid, 0, 0);\r
-}\r
-\r
-\r
-/***********************************************************************\r
- * CreateStatusWindowW [COMCTL32.@]\r
- *\r
- * Creates a status bar control\r
- *\r
- * PARAMS\r
- * style [I] window style\r
- * text [I] pointer to the window text\r
- * parent [I] handle to the parent window\r
- * wid [I] control id of the status bar\r
- *\r
- * RETURNS\r
- * Success: handle to the status window\r
- * Failure: 0\r
- */\r
-\r
-HWND WINAPI\r
-CreateStatusWindowW (LONG style, LPCWSTR text, HWND parent, UINT wid)\r
-{\r
- return CreateWindowW(STATUSCLASSNAMEW, text, style,\r
- CW_USEDEFAULT, CW_USEDEFAULT,\r
- CW_USEDEFAULT, CW_USEDEFAULT,\r
- parent, (HMENU)wid, 0, 0);\r
-}\r
-\r
-\r
-/***********************************************************************\r
- * CreateUpDownControl [COMCTL32.16]\r
- *\r
- * Creates an up-down control\r
- *\r
- * PARAMS\r
- * style [I] window styles\r
- * x [I] horizontal position of the control\r
- * y [I] vertical position of the control\r
- * cx [I] with of the control\r
- * cy [I] height of the control\r
- * parent [I] handle to the parent window\r
- * id [I] the control's identifier\r
- * inst [I] handle to the application's module instance\r
- * buddy [I] handle to the buddy window, can be NULL\r
- * maxVal [I] upper limit of the control\r
- * minVal [I] lower limit of the control\r
- * curVal [I] current value of the control\r
- *\r
- * RETURNS\r
- * Success: handle to the updown control\r
- * Failure: 0\r
- */\r
-\r
-HWND WINAPI\r
-CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,\r
- HWND parent, INT id, HINSTANCE inst,\r
- HWND buddy, INT maxVal, INT minVal, INT curVal)\r
-{\r
- HWND hUD =\r
- CreateWindowW (UPDOWN_CLASSW, 0, style, x, y, cx, cy,\r
- parent, (HMENU)id, inst, 0);\r
- if (hUD) {\r
- SendMessageW (hUD, UDM_SETBUDDY, (WPARAM)buddy, 0);\r
- SendMessageW (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));\r
- SendMessageW (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));\r
- }\r
-\r
- return hUD;\r
-}\r
-\r
-\r
-/***********************************************************************\r
- * InitCommonControls [COMCTL32.17]\r
- *\r
- * Registers the common controls.\r
- *\r
- * PARAMS\r
- * No parameters.\r
- *\r
- * RETURNS\r
- * No return values.\r
- *\r
- * NOTES\r
- * This function is just a dummy.\r
- * The Win95 controls are registered at the DLL's initialization.\r
- * To register other controls InitCommonControlsEx() must be used.\r
- */\r
-\r
-VOID WINAPI\r
-InitCommonControls (void)\r
-{\r
-}\r
-\r
-\r
-/***********************************************************************\r
- * InitCommonControlsEx [COMCTL32.@]\r
- *\r
- * Registers the common controls.\r
- *\r
- * PARAMS\r
- * lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.\r
- *\r
- * RETURNS\r
- * Success: TRUE\r
- * Failure: FALSE\r
- *\r
- * NOTES\r
- * Only the additional common controls are registered by this function.\r
- * The Win95 controls are registered at the DLL's initialization.\r
- *\r
- * FIXME\r
- * implement the following control classes:\r
- * ICC_LINK_CLASS\r
- * ICC_STANDARD_CLASSES\r
- */\r
-\r
-BOOL WINAPI\r
-InitCommonControlsEx (LPINITCOMMONCONTROLSEX lpInitCtrls)\r
-{\r
- INT cCount;\r
- DWORD dwMask;\r
-\r
- if (!lpInitCtrls)\r
- return FALSE;\r
- if (lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))\r
- return FALSE;\r
-\r
- TRACE("(0x%08lx)\n", lpInitCtrls->dwICC);\r
-\r
- for (cCount = 0; cCount < 32; cCount++) {\r
- dwMask = 1 << cCount;\r
- if (!(lpInitCtrls->dwICC & dwMask))\r
- continue;\r
-\r
- switch (lpInitCtrls->dwICC & dwMask) {\r
- /* dummy initialization */\r
- case ICC_ANIMATE_CLASS:\r
- case ICC_BAR_CLASSES:\r
- case ICC_LISTVIEW_CLASSES:\r
- case ICC_TREEVIEW_CLASSES:\r
- case ICC_TAB_CLASSES:\r
- case ICC_UPDOWN_CLASS:\r
- case ICC_PROGRESS_CLASS:\r
- case ICC_HOTKEY_CLASS:\r
- break;\r
-\r
- /* advanced classes - not included in Win95 */\r
- case ICC_DATE_CLASSES:\r
- MONTHCAL_Register ();\r
- DATETIME_Register ();\r
- break;\r
-\r
- case ICC_USEREX_CLASSES:\r
- COMBOEX_Register ();\r
- break;\r
-\r
- case ICC_COOL_CLASSES:\r
- REBAR_Register ();\r
- break;\r
-\r
- case ICC_INTERNET_CLASSES:\r
- IPADDRESS_Register ();\r
- break;\r
-\r
- case ICC_PAGESCROLLER_CLASS:\r
- PAGER_Register ();\r
- break;\r
-\r
- case ICC_NATIVEFNTCTL_CLASS:\r
- NATIVEFONT_Register ();\r
- break;\r
-\r
- case ICC_LINK_CLASS:\r
- SYSLINK_Register ();\r
- break;\r
-\r
- default:\r
- FIXME("Unknown class! dwICC=0x%lX\n", dwMask);\r
- break;\r
- }\r
- }\r
-\r
- return TRUE;\r
-}\r
-\r
-\r
-/***********************************************************************\r
- * CreateToolbarEx [COMCTL32.@]\r
- *\r
- * Creates a toolbar window.\r
- *\r
- * PARAMS\r
- * hwnd\r
- * style\r
- * wID\r
- * nBitmaps\r
- * hBMInst\r
- * wBMID\r
- * lpButtons\r
- * iNumButtons\r
- * dxButton\r
- * dyButton\r
- * dxBitmap\r
- * dyBitmap\r
- * uStructSize\r
- *\r
- * RETURNS\r
- * Success: handle to the tool bar control\r
- * Failure: 0\r
- */\r
-\r
-HWND WINAPI\r
-CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,\r
- HINSTANCE hBMInst, UINT wBMID, LPCTBBUTTON lpButtons,\r
- INT iNumButtons, INT dxButton, INT dyButton,\r
- INT dxBitmap, INT dyBitmap, UINT uStructSize)\r
-{\r
- HWND hwndTB;\r
-\r
- hwndTB =\r
- CreateWindowExW(0, TOOLBARCLASSNAMEW, NULL, style|WS_CHILD, 0,0,100,30,\r
- hwnd, (HMENU)wID, COMCTL32_hModule, NULL);\r
- if(hwndTB) {\r
- TBADDBITMAP tbab;\r
-\r
- SendMessageW (hwndTB, TB_BUTTONSTRUCTSIZE, (WPARAM)uStructSize, 0);\r
-\r
- /* set bitmap and button size */\r
- /*If CreateToolbarEx receives 0, windows sets default values*/\r
- if (dxBitmap <= 0)\r
- dxBitmap = 16;\r
- if (dyBitmap <= 0)\r
- dyBitmap = 15;\r
- SendMessageW (hwndTB, TB_SETBITMAPSIZE, 0,\r
- MAKELPARAM((WORD)dxBitmap, (WORD)dyBitmap));\r
-\r
- if (dxButton <= 0)\r
- dxButton = 24;\r
- if (dyButton <= 0)\r
- dyButton = 22;\r
- SendMessageW (hwndTB, TB_SETBUTTONSIZE, 0,\r
- MAKELPARAM((WORD)dxButton, (WORD)dyButton));\r
-\r
-\r
- /* add bitmaps */\r
- if (nBitmaps > 0)\r
- {\r
- tbab.hInst = hBMInst;\r
- tbab.nID = wBMID;\r
-\r
- SendMessageW (hwndTB, TB_ADDBITMAP, (WPARAM)nBitmaps, (LPARAM)&tbab);\r
- }\r
- /* add buttons */\r
- if(iNumButtons > 0)\r
- SendMessageW (hwndTB, TB_ADDBUTTONSW,\r
- (WPARAM)iNumButtons, (LPARAM)lpButtons);\r
- }\r
-\r
- return hwndTB;\r
-}\r
-\r
-\r
-/***********************************************************************\r
- * CreateMappedBitmap [COMCTL32.8]\r
- *\r
- * Loads a bitmap resource using a colour map.\r
- *\r
- * PARAMS\r
- * hInstance [I] Handle to the module containing the bitmap.\r
- * idBitmap [I] The bitmap resource ID.\r
- * wFlags [I] CMB_MASKED for using bitmap as a mask or 0 for normal.\r
- * lpColorMap [I] Colour information needed for the bitmap or NULL (uses system colours).\r
- * iNumMaps [I] Number of COLORMAP's pointed to by lpColorMap.\r
- *\r
- * RETURNS\r
- * Success: handle to the new bitmap\r
- * Failure: 0\r
- */\r
-\r
-HBITMAP WINAPI\r
-CreateMappedBitmap (HINSTANCE hInstance, INT idBitmap, UINT wFlags,\r
- LPCOLORMAP lpColorMap, INT iNumMaps)\r
-{\r
- HGLOBAL hglb;\r
- HRSRC hRsrc;\r
- LPBITMAPINFOHEADER lpBitmap, lpBitmapInfo;\r
- UINT nSize, nColorTableSize, iColor;\r
- RGBQUAD *pColorTable;\r
- INT i, iMaps, nWidth, nHeight;\r
- HDC hdcScreen;\r
- HBITMAP hbm;\r
- LPCOLORMAP sysColorMap;\r
- COLORREF cRef;\r
- COLORMAP internalColorMap[4] =\r
- {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};\r
-\r
- /* initialize pointer to colortable and default color table */\r
- if (lpColorMap) {\r
- iMaps = iNumMaps;\r
- sysColorMap = lpColorMap;\r
- }\r
- else {\r
- internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT);\r
- internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW);\r
- internalColorMap[2].to = GetSysColor (COLOR_BTNFACE);\r
- internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT);\r
- iMaps = 4;\r
- sysColorMap = (LPCOLORMAP)internalColorMap;\r
- }\r
-\r
- hRsrc = FindResourceW (hInstance, (LPWSTR)idBitmap, (LPWSTR)RT_BITMAP);\r
- if (hRsrc == 0)\r
- return 0;\r
- hglb = LoadResource (hInstance, hRsrc);\r
- if (hglb == 0)\r
- return 0;\r
- lpBitmap = (LPBITMAPINFOHEADER)LockResource (hglb);\r
- if (lpBitmap == NULL)\r
- return 0;\r
-\r
- if (lpBitmap->biSize >= sizeof(BITMAPINFOHEADER) && lpBitmap->biClrUsed)\r
- nColorTableSize = lpBitmap->biClrUsed;\r
- else if (lpBitmap->biBitCount <= 8) \r
- nColorTableSize = (1 << lpBitmap->biBitCount);\r
- else\r
- nColorTableSize = 0;\r
- nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);\r
- lpBitmapInfo = (LPBITMAPINFOHEADER)GlobalAlloc (GMEM_FIXED, nSize);\r
- if (lpBitmapInfo == NULL)\r
- return 0;\r
- RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);\r
-\r
- pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo)+(UINT)lpBitmapInfo->biSize);\r
-\r
- for (iColor = 0; iColor < nColorTableSize; iColor++) {\r
- for (i = 0; i < iMaps; i++) {\r
- cRef = RGB(pColorTable[iColor].rgbRed,\r
- pColorTable[iColor].rgbGreen,\r
- pColorTable[iColor].rgbBlue);\r
- if ( cRef == sysColorMap[i].from) {\r
-#if 0\r
- if (wFlags & CBS_MASKED) {\r
- if (sysColorMap[i].to != COLOR_BTNTEXT)\r
- pColorTable[iColor] = RGB(255, 255, 255);\r
- }\r
- else\r
-#endif\r
- pColorTable[iColor].rgbBlue = GetBValue(sysColorMap[i].to);\r
- pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);\r
- pColorTable[iColor].rgbRed = GetRValue(sysColorMap[i].to);\r
- break;\r
- }\r
- }\r
- }\r
- nWidth = (INT)lpBitmapInfo->biWidth;\r
- nHeight = (INT)lpBitmapInfo->biHeight;\r
- hdcScreen = GetDC (NULL);\r
- hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);\r
- if (hbm) {\r
- HDC hdcDst = CreateCompatibleDC (hdcScreen);\r
- HBITMAP hbmOld = SelectObject (hdcDst, hbm);\r
- LPBYTE lpBits = (LPBYTE)(lpBitmap + 1);\r
- lpBits += nColorTableSize * sizeof(RGBQUAD);\r
- StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,\r
- lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,\r
- SRCCOPY);\r
- SelectObject (hdcDst, hbmOld);\r
- DeleteDC (hdcDst);\r
- }\r
- ReleaseDC (NULL, hdcScreen);\r
- GlobalFree ((HGLOBAL)lpBitmapInfo);\r
- FreeResource (hglb);\r
-\r
- return hbm;\r
-}\r
-\r
-\r
-/***********************************************************************\r
- * CreateToolbar [COMCTL32.7]\r
- *\r
- * Creates a toolbar control.\r
- *\r
- * PARAMS\r
- * hwnd\r
- * style\r
- * wID\r
- * nBitmaps\r
- * hBMInst\r
- * wBMID\r
- * lpButtons\r
- * iNumButtons\r
- *\r
- * RETURNS\r
- * Success: handle to the tool bar control\r
- * Failure: 0\r
- *\r
- * NOTES\r
- * Do not use this functions anymore. Use CreateToolbarEx instead.\r
- */\r
-\r
-HWND WINAPI\r
-CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,\r
- HINSTANCE hBMInst, UINT wBMID,\r
- LPCTBBUTTON lpButtons,INT iNumButtons)\r
-{\r
- return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,\r
- hBMInst, wBMID, lpButtons,\r
- iNumButtons, 0, 0, 0, 0, CCSIZEOF_STRUCT(TBBUTTON, dwData));\r
-}\r
-\r
-\r
-/***********************************************************************\r
- * DllGetVersion [COMCTL32.@]\r
- *\r
- * Retrieves version information of the 'COMCTL32.DLL'\r
- *\r
- * PARAMS\r
- * pdvi [O] pointer to version information structure.\r
- *\r
- * RETURNS\r
- * Success: S_OK\r
- * Failure: E_INVALIDARG\r
- *\r
- * NOTES\r
- * Returns version of a comctl32.dll from IE4.01 SP1.\r
- */\r
-\r
-HRESULT WINAPI\r
-COMCTL32_DllGetVersion (DLLVERSIONINFO *pdvi)\r
-{\r
- if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {\r
- WARN("wrong DLLVERSIONINFO size from app\n");\r
- return E_INVALIDARG;\r
- }\r
-\r
- pdvi->dwMajorVersion = COMCTL32_VERSION;\r
- pdvi->dwMinorVersion = COMCTL32_VERSION_MINOR;\r
- pdvi->dwBuildNumber = 2919;\r
- pdvi->dwPlatformID = 6304;\r
-\r
- TRACE("%lu.%lu.%lu.%lu\n",\r
- pdvi->dwMajorVersion, pdvi->dwMinorVersion,\r
- pdvi->dwBuildNumber, pdvi->dwPlatformID);\r
-\r
- return S_OK;\r
-}\r
-\r
-/***********************************************************************\r
- * DllInstall (COMCTL32.@)\r
- *\r
- * Installs the ComCtl32 DLL.\r
- *\r
- * RETURNS\r
- * Success: S_OK\r
- * Failure: A HRESULT error\r
- */\r
-HRESULT WINAPI COMCTL32_DllInstall(BOOL bInstall, LPCWSTR cmdline)\r
-{\r
- FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",\r
- debugstr_w(cmdline));\r
-\r
- return S_OK;\r
-}\r
-\r
-/***********************************************************************\r
- * _TrackMouseEvent [COMCTL32.@]\r
- *\r
- * Requests notification of mouse events\r
- *\r
- * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted\r
- * to the hwnd specified in the ptme structure. After the event message\r
- * is posted to the hwnd, the entry in the queue is removed.\r
- *\r
- * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely\r
- * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted\r
- * immediately and the TME_LEAVE flag being ignored.\r
- *\r
- * PARAMS\r
- * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.\r
- *\r
- * RETURNS\r
- * Success: non-zero\r
- * Failure: zero\r
- *\r
- * IMPLEMENTATION moved to USER32.TrackMouseEvent\r
- *\r
- */\r
-\r
-BOOL WINAPI\r
-_TrackMouseEvent (TRACKMOUSEEVENT *ptme)\r
-{\r
- return TrackMouseEvent (ptme);\r
-}\r
-\r
-/*************************************************************************\r
- * GetMUILanguage [COMCTL32.@]\r
- *\r
- * Returns the user interface language in use by the current process.\r
- *\r
- * RETURNS\r
- * Language ID in use by the current process.\r
- */\r
-LANGID WINAPI GetMUILanguage (VOID)\r
-{\r
- return COMCTL32_uiLang;\r
-}\r
-\r
-\r
-/*************************************************************************\r
- * InitMUILanguage [COMCTL32.@]\r
- *\r
- * Sets the user interface language to be used by the current process.\r
- *\r
- * RETURNS\r
- * Nothing.\r
- */\r
-VOID WINAPI InitMUILanguage (LANGID uiLang)\r
-{\r
- COMCTL32_uiLang = uiLang;\r
-}\r
-\r
-\r
-/***********************************************************************\r
- * SetWindowSubclass [COMCTL32.410]\r
- *\r
- * Starts a window subclass\r
- *\r
- * PARAMS\r
- * hWnd [in] handle to window subclass.\r
- * pfnSubclass [in] Pointer to new window procedure.\r
- * uIDSubclass [in] Unique identifier of sublass together with pfnSubclass.\r
- * dwRef [in] Reference data to pass to window procedure.\r
- *\r
- * RETURNS\r
- * Success: non-zero\r
- * Failure: zero\r
- *\r
- * BUGS\r
- * If an application manually subclasses a window after subclassing it with\r
- * this API and then with this API again, then none of the previous \r
- * subclasses get called or the origional window procedure.\r
- */\r
-\r
-BOOL WINAPI SetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,\r
- UINT_PTR uIDSubclass, DWORD_PTR dwRef)\r
-{\r
- LPSUBCLASS_INFO stack;\r
- LPSUBCLASSPROCS proc;\r
-\r
- TRACE ("(%p, %p, %x, %lx)\n", hWnd, pfnSubclass, uIDSubclass, dwRef);\r
-\r
- /* Since the window procedure that we set here has two additional arguments,\r
- * we can't simply set it as the new window procedure of the window. So we\r
- * set our own window procedure and then calculate the other two arguments\r
- * from there. */\r
-\r
- /* See if we have been called for this window */\r
- stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);\r
- if (!stack) {\r
- /* allocate stack */\r
- stack = Alloc (sizeof(SUBCLASS_INFO));\r
- if (!stack) {\r
- ERR ("Failed to allocate our Subclassing stack\n");\r
- return FALSE;\r
- }\r
- SetPropW (hWnd, COMCTL32_wSubclass, (HANDLE)stack);\r
-\r
- /* set window procedure to our own and save the current one */\r
- if (IsWindowUnicode (hWnd))\r
- stack->origproc = (WNDPROC)SetWindowLongPtrW (hWnd, GWLP_WNDPROC,\r
- (DWORD_PTR)COMCTL32_SubclassProc);\r
- else\r
- stack->origproc = (WNDPROC)SetWindowLongPtrA (hWnd, GWLP_WNDPROC,\r
- (DWORD_PTR)COMCTL32_SubclassProc);\r
- }\r
- else {\r
- /* Check to see if we have called this function with the same uIDSubClass\r
- * and pfnSubclass */\r
- proc = stack->SubclassProcs;\r
- while (proc) {\r
- if ((proc->id == uIDSubclass) &&\r
- (proc->subproc == pfnSubclass)) {\r
- proc->ref = dwRef;\r
- return TRUE;\r
- }\r
- proc = proc->next;\r
- }\r
- }\r
- \r
- proc = Alloc(sizeof(SUBCLASSPROCS));\r
- if (!proc) {\r
- ERR ("Failed to allocate subclass entry in stack\n");\r
- if (IsWindowUnicode (hWnd))\r
- SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);\r
- else\r
- SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);\r
- Free (stack);\r
- RemovePropW( hWnd, COMCTL32_wSubclass );\r
- return FALSE;\r
- }\r
- \r
- proc->subproc = pfnSubclass;\r
- proc->ref = dwRef;\r
- proc->id = uIDSubclass;\r
- proc->next = stack->SubclassProcs;\r
- stack->SubclassProcs = proc;\r
-\r
- return TRUE;\r
-}\r
-\r
-\r
-/***********************************************************************\r
- * GetWindowSubclass [COMCTL32.411]\r
- *\r
- * Gets the Reference data from a subclass.\r
- *\r
- * PARAMS\r
- * hWnd [in] Handle to window which were subclassing\r
- * pfnSubclass [in] Pointer to the subclass procedure\r
- * uID [in] Unique indentifier of the subclassing procedure\r
- * pdwRef [out] Pointer to the reference data\r
- *\r
- * RETURNS\r
- * Success: Non-zero\r
- * Failure: 0\r
- */\r
-\r
-BOOL WINAPI GetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,\r
- UINT_PTR uID, DWORD_PTR *pdwRef)\r
-{\r
- LPSUBCLASS_INFO stack;\r
- LPSUBCLASSPROCS proc;\r
-\r
- TRACE ("(%p, %p, %x, %p)\n", hWnd, pfnSubclass, uID, pdwRef);\r
-\r
- /* See if we have been called for this window */\r
- stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);\r
- if (!stack)\r
- return FALSE;\r
-\r
- proc = stack->SubclassProcs;\r
- while (proc) {\r
- if ((proc->id == uID) &&\r
- (proc->subproc == pfnSubclass)) {\r
- *pdwRef = proc->ref;\r
- return TRUE;\r
- }\r
- proc = proc->next;\r
- }\r
-\r
- return FALSE;\r
-}\r
-\r
-\r
-/***********************************************************************\r
- * RemoveWindowSubclass [COMCTL32.412]\r
- *\r
- * Removes a window subclass.\r
- *\r
- * PARAMS\r
- * hWnd [in] Handle to the window were subclassing\r
- * pfnSubclass [in] Pointer to the subclass procedure\r
- * uID [in] Unique identifier of this subclass\r
- *\r
- * RETURNS\r
- * Success: non-zero\r
- * Failure: zero\r
- */\r
-\r
-BOOL WINAPI RemoveWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR uID)\r
-{\r
- LPSUBCLASS_INFO stack;\r
- LPSUBCLASSPROCS prevproc = NULL;\r
- LPSUBCLASSPROCS proc;\r
- BOOL ret = FALSE;\r
-\r
- TRACE ("(%p, %p, %x)\n", hWnd, pfnSubclass, uID);\r
-\r
- /* Find the Subclass to remove */\r
- stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);\r
- if (!stack)\r
- return FALSE;\r
-\r
- proc = stack->SubclassProcs;\r
- while (proc) {\r
- if ((proc->id == uID) &&\r
- (proc->subproc == pfnSubclass)) {\r
- \r
- if (!prevproc)\r
- stack->SubclassProcs = proc->next;\r
- else\r
- prevproc->next = proc->next;\r
- \r
- if (stack->stackpos == proc)\r
- stack->stackpos = stack->stackpos->next;\r
- \r
- Free (proc);\r
- ret = TRUE;\r
- break;\r
- }\r
- prevproc = proc;\r
- proc = proc->next;\r
- }\r
- \r
- if (!stack->SubclassProcs && !stack->running) {\r
- TRACE("Last Subclass removed, cleaning up\n");\r
- /* clean up our heap and reset the origional window procedure */\r
- if (IsWindowUnicode (hWnd))\r
- SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);\r
- else\r
- SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);\r
- Free (stack);\r
- RemovePropW( hWnd, COMCTL32_wSubclass );\r
- }\r
- \r
- return ret;\r
-}\r
-\r
-/***********************************************************************\r
- * COMCTL32_SubclassProc (internal)\r
- *\r
- * Window procedure for all subclassed windows. \r
- * Saves the current subclassing stack position to support nested messages\r
- */\r
-LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)\r
-{\r
- LPSUBCLASS_INFO stack;\r
- LPSUBCLASSPROCS proc;\r
- LRESULT ret;\r
- \r
- TRACE ("(%p, 0x%08x, 0x%08x, 0x%08lx)\n", hWnd, uMsg, wParam, lParam);\r
-\r
- stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);\r
- if (!stack) {\r
- ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);\r
- return 0;\r
- }\r
- \r
- /* Save our old stackpos to properly handle nested messages */\r
- proc = stack->stackpos;\r
- stack->stackpos = stack->SubclassProcs;\r
- stack->running++;\r
- ret = DefSubclassProc(hWnd, uMsg, wParam, lParam);\r
- stack->running--;\r
- stack->stackpos = proc;\r
- \r
- if (!stack->SubclassProcs && !stack->running) {\r
- TRACE("Last Subclass removed, cleaning up\n");\r
- /* clean up our heap and reset the origional window procedure */\r
- if (IsWindowUnicode (hWnd))\r
- SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);\r
- else\r
- SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);\r
- Free (stack);\r
- RemovePropW( hWnd, COMCTL32_wSubclass );\r
- }\r
- return ret;\r
-}\r
-\r
-/***********************************************************************\r
- * DefSubclassProc [COMCTL32.413]\r
- *\r
- * Calls the next window procedure (ie. the one before this subclass)\r
- *\r
- * PARAMS\r
- * hWnd [in] The window that we're subclassing\r
- * uMsg [in] Message\r
- * wParam [in] WPARAM\r
- * lParam [in] LPARAM\r
- *\r
- * RETURNS\r
- * Success: non-zero\r
- * Failure: zero\r
- */\r
-\r
-LRESULT WINAPI DefSubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)\r
-{\r
- LPSUBCLASS_INFO stack;\r
- LRESULT ret;\r
- \r
- TRACE ("(%p, 0x%08x, 0x%08x, 0x%08lx)\n", hWnd, uMsg, wParam, lParam);\r
-\r
- /* retrieve our little stack from the Properties */\r
- stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);\r
- if (!stack) {\r
- ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);\r
- return 0;\r
- }\r
-\r
- /* If we are at the end of stack then we have to call the original\r
- * window procedure */\r
- if (!stack->stackpos) {\r
- if (IsWindowUnicode (hWnd))\r
- ret = CallWindowProcW (stack->origproc, hWnd, uMsg, wParam, lParam);\r
- else\r
- ret = CallWindowProcA (stack->origproc, hWnd, uMsg, wParam, lParam);\r
- } else {\r
- LPSUBCLASSPROCS proc = stack->stackpos;\r
- stack->stackpos = stack->stackpos->next; \r
- /* call the Subclass procedure from the stack */\r
- ret = proc->subproc (hWnd, uMsg, wParam, lParam,\r
- proc->id, proc->ref);\r
- }\r
-\r
- return ret;\r
-}\r
-\r
-\r
-/***********************************************************************\r
- * COMCTL32_CreateToolTip [NOT AN API]\r
- *\r
- * Creates a tooltip for the control specified in hwnd and does all\r
- * necessary setup and notifications.\r
- *\r
- * PARAMS\r
- * hwndOwner [I] Handle to the window that will own the tool tip.\r
- *\r
- * RETURNS\r
- * Success: Handle of tool tip window.\r
- * Failure: NULL\r
- */\r
-\r
-HWND\r
-COMCTL32_CreateToolTip(HWND hwndOwner)\r
-{\r
- HWND hwndToolTip;\r
-\r
- hwndToolTip = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, 0,\r
- CW_USEDEFAULT, CW_USEDEFAULT,\r
- CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner,\r
- 0, 0, 0);\r
-\r
- /* Send NM_TOOLTIPSCREATED notification */\r
- if (hwndToolTip)\r
- {\r
- NMTOOLTIPSCREATED nmttc;\r
- /* true owner can be different if hwndOwner is a child window */\r
- HWND hwndTrueOwner = GetWindow(hwndToolTip, GW_OWNER);\r
- nmttc.hdr.hwndFrom = hwndTrueOwner;\r
- nmttc.hdr.idFrom = GetWindowLongPtrW(hwndTrueOwner, GWLP_ID);\r
- nmttc.hdr.code = NM_TOOLTIPSCREATED;\r
- nmttc.hwndToolTips = hwndToolTip;\r
-\r
- SendMessageW(GetParent(hwndTrueOwner), WM_NOTIFY,\r
- (WPARAM)GetWindowLongPtrW(hwndTrueOwner, GWLP_ID),\r
- (LPARAM)&nmttc);\r
- }\r
-\r
- return hwndToolTip;\r
-}\r
-\r
-\r
-/***********************************************************************\r
- * COMCTL32_RefreshSysColors [NOT AN API]\r
- *\r
- * Invoked on any control recognizing a WM_SYSCOLORCHANGE message to\r
- * refresh the color values in the color structure\r
- *\r
- * PARAMS\r
- * none\r
- *\r
- * RETURNS\r
- * none\r
- */\r
-\r
-VOID\r
-COMCTL32_RefreshSysColors(void)\r
-{\r
- comctl32_color.clrBtnHighlight = GetSysColor (COLOR_BTNHIGHLIGHT);\r
- comctl32_color.clrBtnShadow = GetSysColor (COLOR_BTNSHADOW);\r
- comctl32_color.clrBtnText = GetSysColor (COLOR_BTNTEXT);\r
- comctl32_color.clrBtnFace = GetSysColor (COLOR_BTNFACE);\r
- comctl32_color.clrHighlight = GetSysColor (COLOR_HIGHLIGHT);\r
- comctl32_color.clrHighlightText = GetSysColor (COLOR_HIGHLIGHTTEXT);\r
- comctl32_color.clr3dHilight = GetSysColor (COLOR_3DHILIGHT);\r
- comctl32_color.clr3dShadow = GetSysColor (COLOR_3DSHADOW);\r
- comctl32_color.clr3dDkShadow = GetSysColor (COLOR_3DDKSHADOW);\r
- comctl32_color.clr3dFace = GetSysColor (COLOR_3DFACE);\r
- comctl32_color.clrWindow = GetSysColor (COLOR_WINDOW);\r
- comctl32_color.clrWindowText = GetSysColor (COLOR_WINDOWTEXT);\r
- comctl32_color.clrGrayText = GetSysColor (COLOR_GRAYTEXT);\r
- comctl32_color.clrActiveCaption = GetSysColor (COLOR_ACTIVECAPTION);\r
- comctl32_color.clrInfoBk = GetSysColor (COLOR_INFOBK);\r
- comctl32_color.clrInfoText = GetSysColor (COLOR_INFOTEXT);\r
-}\r
-\r
-/***********************************************************************\r
- * COMCTL32_DrawInsertMark [NOT AN API]\r
- *\r
- * Draws an insertion mark (which looks similar to an 'I').\r
- *\r
- * PARAMS\r
- * hDC [I] Device context to draw onto.\r
- * lpRect [I] Co-ordinates of insertion mark.\r
- * clrInsertMark [I] Colour of the insertion mark.\r
- * bHorizontal [I] True if insert mark should be drawn horizontally,\r
- * vertical otherwise.\r
- *\r
- * RETURNS\r
- * none\r
- *\r
- * NOTES\r
- * Draws up to but not including the bottom co-ordinate when drawing\r
- * vertically or the right co-ordinate when horizontal.\r
- */\r
-void COMCTL32_DrawInsertMark(HDC hDC, const RECT *lpRect, COLORREF clrInsertMark, BOOL bHorizontal)\r
-{\r
- HPEN hPen = CreatePen(PS_SOLID, 1, clrInsertMark);\r
- HPEN hOldPen;\r
- static const DWORD adwPolyPoints[] = {4,4,4};\r
- LONG lCentre = (bHorizontal ? \r
- lpRect->top + (lpRect->bottom - lpRect->top)/2 : \r
- lpRect->left + (lpRect->right - lpRect->left)/2);\r
- LONG l1 = (bHorizontal ? lpRect->left : lpRect->top);\r
- LONG l2 = (bHorizontal ? lpRect->right : lpRect->bottom);\r
- const POINT aptInsertMark[] =\r
- {\r
- /* top (V) or left (H) arrow */\r
- {lCentre , l1 + 2},\r
- {lCentre - 2, l1 },\r
- {lCentre + 3, l1 },\r
- {lCentre + 1, l1 + 2},\r
- /* middle line */\r
- {lCentre , l2 - 2},\r
- {lCentre , l1 - 1},\r
- {lCentre + 1, l1 - 1},\r
- {lCentre + 1, l2 - 2},\r
- /* bottom (V) or right (H) arrow */\r
- {lCentre , l2 - 3},\r
- {lCentre - 2, l2 - 1},\r
- {lCentre + 3, l2 - 1},\r
- {lCentre + 1, l2 - 3},\r
- };\r
- hOldPen = SelectObject(hDC, hPen);\r
- PolyPolyline(hDC, aptInsertMark, adwPolyPoints, sizeof(adwPolyPoints)/sizeof(adwPolyPoints[0]));\r
- SelectObject(hDC, hOldPen);\r
- DeleteObject(hPen);\r
-}\r
-\r
-/***********************************************************************\r
- * MirrorIcon [COMCTL32.414]\r
- *\r
- * Mirrors an icon so that it will appear correctly on a mirrored DC.\r
- *\r
- * PARAMS\r
- * phicon1 [I/O] Icon.\r
- * phicon2 [I/O] Icon.\r
- *\r
- * RETURNS\r
- * Success: TRUE.\r
- * Failure: FALSE.\r
- */\r
-BOOL WINAPI MirrorIcon(HICON *phicon1, HICON *phicon2)\r
-{\r
- FIXME("(%p, %p): stub\n", phicon1, phicon2);\r
- return FALSE;\r
-}\r
-\r
-static inline int IsDelimiter(WCHAR c)\r
-{\r
- switch(c)\r
- {\r
- case '/':\r
- case '\\':\r
- case '.':\r
- case ' ':\r
- return TRUE;\r
- }\r
- return FALSE;\r
-}\r
-\r
-static int CALLBACK PathWordBreakProc(LPWSTR lpch, int ichCurrent, int cch, int code)\r
-{\r
- if (code == WB_ISDELIMITER)\r
- return IsDelimiter(lpch[ichCurrent]);\r
- else\r
- {\r
- int dir = (code == WB_LEFT) ? -1 : 1;\r
- for(; 0 <= ichCurrent && ichCurrent < cch; ichCurrent += dir)\r
- if (IsDelimiter(lpch[ichCurrent])) return ichCurrent;\r
- }\r
- return ichCurrent;\r
-}\r
-\r
-/***********************************************************************\r
- * SetPathWordBreakProc [COMCTL32.384]\r
- *\r
- * Sets the word break procedure for an edit control to one that understands\r
- * paths so that the user can jump over directories.\r
- *\r
- * PARAMS\r
- * hwnd [I] Handle to edit control.\r
- * bSet [I] If this is TRUE then the word break proc is set, otherwise it is removed.\r
- *\r
- * RETURNS\r
- * Result from EM_SETWORDBREAKPROC message.\r
- */\r
-LRESULT WINAPI SetPathWordBreakProc(HWND hwnd, BOOL bSet)\r
-{\r
- return SendMessageW(hwnd, EM_SETWORDBREAKPROC, 0,\r
- (LPARAM)(bSet ? PathWordBreakProc : NULL));\r
-}\r
+/*
+ * Common controls functions
+ *
+ * Copyright 1997 Dimitrie O. Paun
+ * Copyright 1998,2000 Eric Kohl
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * NOTES
+ *
+ * This code was audited for completeness against the documented features
+ * of Comctl32.dll version 6.0 on Oct. 21, 2002, by Christian Neumair.
+ *
+ * Unless otherwise noted, we believe this code to be complete, as per
+ * the specification mentioned above.
+ * If you discover missing features, or bugs, please note them below.
+ *
+ * TODO
+ * -- implement GetMUILanguage + InitMUILanguage
+ * -- LibMain => DLLMain ("DLLMain takes over the functionality of both the
+ * LibMain and the WEP function.", MSDN)
+ * -- finish NOTES for MenuHelp, GetEffectiveClientRect and GetStatusTextW
+ * -- FIXMEs + BUGS (search for them)
+ *
+ * Control Classes
+ * -- ICC_ANIMATE_CLASS
+ * -- ICC_BAR_CLASSES
+ * -- ICC_COOL_CLASSES
+ * -- ICC_DATE_CLASSES
+ * -- ICC_HOTKEY_CLASS
+ * -- ICC_INTERNET_CLASSES
+ * -- ICC_LINK_CLASS
+ * -- ICC_LISTVIEW_CLASSES
+ * -- ICC_NATIVEFNTCTL_CLASS
+ * -- ICC_PAGESCROLLER_CLASS
+ * -- ICC_PROGRESS_CLASS
+ * -- ICC_STANDARD_CLASSES (not yet implemented)
+ * -- ICC_TAB_CLASSES
+ * -- ICC_TREEVIEW_CLASSES
+ * -- ICC_UPDOWN_CLASS
+ * -- ICC_USEREX_CLASSES
+ * -- ICC_WIN95_CLASSES
+ */
+
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "wingdi.h"
+#include "winuser.h"
+#include "winnls.h"
+#include "commctrl.h"
+#include "winerror.h"
+#include "winreg.h"
+#define NO_SHLWAPI_STREAM
+#include "shlwapi.h"
+#include "comctl32.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(commctrl);
+
+LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
+
+LPWSTR COMCTL32_wSubclass = NULL;
+HMODULE COMCTL32_hModule = 0;
+LANGID COMCTL32_uiLang = MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL);
+HBRUSH COMCTL32_hPattern55AABrush = NULL;
+COMCTL32_SysColor comctl32_color;
+
+static HBITMAP COMCTL32_hPattern55AABitmap = NULL;
+
+static const WORD wPattern55AA[] =
+{
+ 0x5555, 0xaaaa, 0x5555, 0xaaaa,
+ 0x5555, 0xaaaa, 0x5555, 0xaaaa
+};
+
+static const WCHAR strCC32SubclassInfo[] = {
+ 'C','C','3','2','S','u','b','c','l','a','s','s','I','n','f','o',0
+};
+
+/***********************************************************************
+ * DllMain [Internal]
+ *
+ * Initializes the internal 'COMCTL32.DLL'.
+ *
+ * PARAMS
+ * hinstDLL [I] handle to the 'dlls' instance
+ * fdwReason [I]
+ * lpvReserved [I] reserverd, must be NULL
+ *
+ * RETURNS
+ * Success: TRUE
+ * Failure: FALSE
+ */
+
+BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
+{
+ TRACE("%p,%lx,%p\n", hinstDLL, fdwReason, lpvReserved);
+
+ switch (fdwReason) {
+ case DLL_PROCESS_ATTACH:
+ DisableThreadLibraryCalls(hinstDLL);
+
+ COMCTL32_hModule = (HMODULE)hinstDLL;
+
+ /* add global subclassing atom (used by 'tooltip' and 'updown') */
+ COMCTL32_wSubclass = (LPWSTR)(DWORD)GlobalAddAtomW (strCC32SubclassInfo);
+ TRACE("Subclassing atom added: %p\n", COMCTL32_wSubclass);
+
+ /* create local pattern brush */
+ COMCTL32_hPattern55AABitmap = CreateBitmap (8, 8, 1, 1, wPattern55AA);
+ COMCTL32_hPattern55AABrush = CreatePatternBrush (COMCTL32_hPattern55AABitmap);
+
+ /* Get all the colors at DLL load */
+ COMCTL32_RefreshSysColors();
+
+ /* register all Win95 common control classes */
+ ANIMATE_Register ();
+ FLATSB_Register ();
+ HEADER_Register ();
+ HOTKEY_Register ();
+ LISTVIEW_Register ();
+ PROGRESS_Register ();
+ STATUS_Register ();
+ SYSLINK_Register ();
+ TAB_Register ();
+ TOOLBAR_Register ();
+ TOOLTIPS_Register ();
+ TRACKBAR_Register ();
+ TREEVIEW_Register ();
+ UPDOWN_Register ();
+ break;
+
+ case DLL_PROCESS_DETACH:
+ /* unregister all common control classes */
+ ANIMATE_Unregister ();
+ COMBOEX_Unregister ();
+ DATETIME_Unregister ();
+ FLATSB_Unregister ();
+ HEADER_Unregister ();
+ HOTKEY_Unregister ();
+ IPADDRESS_Unregister ();
+ LISTVIEW_Unregister ();
+ MONTHCAL_Unregister ();
+ NATIVEFONT_Unregister ();
+ PAGER_Unregister ();
+ PROGRESS_Unregister ();
+ REBAR_Unregister ();
+ STATUS_Unregister ();
+ SYSLINK_Unregister ();
+ TAB_Unregister ();
+ TOOLBAR_Unregister ();
+ TOOLTIPS_Unregister ();
+ TRACKBAR_Unregister ();
+ TREEVIEW_Unregister ();
+ UPDOWN_Unregister ();
+
+ /* delete local pattern brush */
+ DeleteObject (COMCTL32_hPattern55AABrush);
+ COMCTL32_hPattern55AABrush = NULL;
+ DeleteObject (COMCTL32_hPattern55AABitmap);
+ COMCTL32_hPattern55AABitmap = NULL;
+
+ /* delete global subclassing atom */
+ GlobalDeleteAtom (LOWORD(COMCTL32_wSubclass));
+ TRACE("Subclassing atom deleted: %p\n", COMCTL32_wSubclass);
+ COMCTL32_wSubclass = NULL;
+ break;
+ }
+
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * MenuHelp [COMCTL32.2]
+ *
+ * Handles the setting of status bar help messages when the user
+ * selects menu items.
+ *
+ * PARAMS
+ * uMsg [I] message (WM_MENUSELECT) (see NOTES)
+ * wParam [I] wParam of the message uMsg
+ * lParam [I] lParam of the message uMsg
+ * hMainMenu [I] handle to the application's main menu
+ * hInst [I] handle to the module that contains string resources
+ * hwndStatus [I] handle to the status bar window
+ * lpwIDs [I] pointer to an array of integers (see NOTES)
+ *
+ * RETURNS
+ * No return value
+ *
+ * NOTES
+ * The official documentation is incomplete!
+ * This is the correct documentation:
+ *
+ * uMsg:
+ * MenuHelp() does NOT handle WM_COMMAND messages! It only handles
+ * WM_MENUSELECT messages.
+ *
+ * lpwIDs:
+ * (will be written ...)
+ */
+
+VOID WINAPI
+MenuHelp (UINT uMsg, WPARAM wParam, LPARAM lParam, HMENU hMainMenu,
+ HINSTANCE hInst, HWND hwndStatus, UINT* lpwIDs)
+{
+ UINT uMenuID = 0;
+
+ if (!IsWindow (hwndStatus))
+ return;
+
+ switch (uMsg) {
+ case WM_MENUSELECT:
+ TRACE("WM_MENUSELECT wParam=0x%X lParam=0x%lX\n",
+ wParam, lParam);
+
+ if ((HIWORD(wParam) == 0xFFFF) && (lParam == 0)) {
+ /* menu was closed */
+ TRACE("menu was closed!\n");
+ SendMessageW (hwndStatus, SB_SIMPLE, FALSE, 0);
+ }
+ else {
+ /* menu item was selected */
+ if (HIWORD(wParam) & MF_POPUP)
+ uMenuID = (UINT)*(lpwIDs+1);
+ else
+ uMenuID = (UINT)LOWORD(wParam);
+ TRACE("uMenuID = %u\n", uMenuID);
+
+ if (uMenuID) {
+ WCHAR szText[256];
+
+ if (!LoadStringW (hInst, uMenuID, szText, sizeof(szText)/sizeof(szText[0])))
+ szText[0] = '\0';
+
+ SendMessageW (hwndStatus, SB_SETTEXTW,
+ 255 | SBT_NOBORDERS, (LPARAM)szText);
+ SendMessageW (hwndStatus, SB_SIMPLE, TRUE, 0);
+ }
+ }
+ break;
+
+ case WM_COMMAND :
+ TRACE("WM_COMMAND wParam=0x%X lParam=0x%lX\n",
+ wParam, lParam);
+ /* WM_COMMAND is not invalid since it is documented
+ * in the windows api reference. So don't output
+ * any FIXME for WM_COMMAND
+ */
+ WARN("We don't care about the WM_COMMAND\n");
+ break;
+
+ default:
+ FIXME("Invalid Message 0x%x!\n", uMsg);
+ break;
+ }
+}
+
+
+/***********************************************************************
+ * ShowHideMenuCtl [COMCTL32.3]
+ *
+ * Shows or hides controls and updates the corresponding menu item.
+ *
+ * PARAMS
+ * hwnd [I] handle to the client window.
+ * uFlags [I] menu command id.
+ * lpInfo [I] pointer to an array of integers. (See NOTES.)
+ *
+ * RETURNS
+ * Success: TRUE
+ * Failure: FALSE
+ *
+ * NOTES
+ * The official documentation is incomplete!
+ * This is the correct documentation:
+ *
+ * hwnd
+ * Handle to the window that contains the menu and controls.
+ *
+ * uFlags
+ * Identifier of the menu item to receive or lose a check mark.
+ *
+ * lpInfo
+ * The array of integers contains pairs of values. BOTH values of
+ * the first pair must be the handles to the application's main menu.
+ * Each subsequent pair consists of a menu id and control id.
+ */
+
+BOOL WINAPI
+ShowHideMenuCtl (HWND hwnd, UINT uFlags, LPINT lpInfo)
+{
+ LPINT lpMenuId;
+
+ TRACE("%p, %x, %p\n", hwnd, uFlags, lpInfo);
+
+ if (lpInfo == NULL)
+ return FALSE;
+
+ if (!(lpInfo[0]) || !(lpInfo[1]))
+ return FALSE;
+
+ /* search for control */
+ lpMenuId = &lpInfo[2];
+ while (*lpMenuId != uFlags)
+ lpMenuId += 2;
+
+ if (GetMenuState ((HMENU)lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) {
+ /* uncheck menu item */
+ CheckMenuItem ((HMENU)lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_UNCHECKED);
+
+ /* hide control */
+ lpMenuId++;
+ SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
+ SWP_HIDEWINDOW);
+ }
+ else {
+ /* check menu item */
+ CheckMenuItem ((HMENU)lpInfo[0], *lpMenuId, MF_BYCOMMAND | MF_CHECKED);
+
+ /* show control */
+ lpMenuId++;
+ SetWindowPos (GetDlgItem (hwnd, *lpMenuId), 0, 0, 0, 0, 0,
+ SWP_SHOWWINDOW);
+ }
+
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * GetEffectiveClientRect [COMCTL32.4]
+ *
+ * Calculates the coordinates of a rectangle in the client area.
+ *
+ * PARAMS
+ * hwnd [I] handle to the client window.
+ * lpRect [O] pointer to the rectangle of the client window
+ * lpInfo [I] pointer to an array of integers (see NOTES)
+ *
+ * RETURNS
+ * No return value.
+ *
+ * NOTES
+ * The official documentation is incomplete!
+ * This is the correct documentation:
+ *
+ * lpInfo
+ * (will be written ...)
+ */
+
+VOID WINAPI
+GetEffectiveClientRect (HWND hwnd, LPRECT lpRect, LPINT lpInfo)
+{
+ RECT rcCtrl;
+ INT *lpRun;
+ HWND hwndCtrl;
+
+ TRACE("(0x%08lx 0x%08lx 0x%08lx)\n",
+ (DWORD)hwnd, (DWORD)lpRect, (DWORD)lpInfo);
+
+ GetClientRect (hwnd, lpRect);
+ lpRun = lpInfo;
+
+ do {
+ lpRun += 2;
+ if (*lpRun == 0)
+ return;
+ lpRun++;
+ hwndCtrl = GetDlgItem (hwnd, *lpRun);
+ if (GetWindowLongW (hwndCtrl, GWL_STYLE) & WS_VISIBLE) {
+ TRACE("control id 0x%x\n", *lpRun);
+ GetWindowRect (hwndCtrl, &rcCtrl);
+ MapWindowPoints (NULL, hwnd, (LPPOINT)&rcCtrl, 2);
+ SubtractRect (lpRect, lpRect, &rcCtrl);
+ }
+ lpRun++;
+ } while (*lpRun);
+}
+
+
+/***********************************************************************
+ * DrawStatusTextW [COMCTL32.@]
+ *
+ * Draws text with borders, like in a status bar.
+ *
+ * PARAMS
+ * hdc [I] handle to the window's display context
+ * lprc [I] pointer to a rectangle
+ * text [I] pointer to the text
+ * style [I] drawing style
+ *
+ * RETURNS
+ * No return value.
+ *
+ * NOTES
+ * The style variable can have one of the following values:
+ * (will be written ...)
+ */
+
+void WINAPI DrawStatusTextW (HDC hdc, LPRECT lprc, LPCWSTR text, UINT style)
+{
+ RECT r = *lprc;
+ UINT border = BDR_SUNKENOUTER;
+
+ if (style & SBT_POPOUT)
+ border = BDR_RAISEDOUTER;
+ else if (style & SBT_NOBORDERS)
+ border = 0;
+
+ DrawEdge (hdc, &r, border, BF_RECT|BF_ADJUST);
+
+ /* now draw text */
+ if (text) {
+ int oldbkmode = SetBkMode (hdc, TRANSPARENT);
+ UINT align = DT_LEFT;
+ if (*text == L'\t') {
+ text++;
+ align = DT_CENTER;
+ if (*text == L'\t') {
+ text++;
+ align = DT_RIGHT;
+ }
+ }
+ r.left += 3;
+ if (style & SBT_RTLREADING)
+ FIXME("Unsupported RTL style!\n");
+ DrawTextW (hdc, text, -1, &r, align|DT_VCENTER|DT_SINGLELINE|DT_NOPREFIX);
+ SetBkMode(hdc, oldbkmode);
+ }
+}
+
+
+/***********************************************************************
+ * DrawStatusText [COMCTL32.@]
+ * DrawStatusTextA [COMCTL32.5]
+ *
+ * Draws text with borders, like in a status bar.
+ *
+ * PARAMS
+ * hdc [I] handle to the window's display context
+ * lprc [I] pointer to a rectangle
+ * text [I] pointer to the text
+ * style [I] drawing style
+ *
+ * RETURNS
+ * No return value.
+ */
+
+void WINAPI DrawStatusTextA (HDC hdc, LPRECT lprc, LPCSTR text, UINT style)
+{
+ INT len;
+ LPWSTR textW = NULL;
+
+ if ( text ) {
+ if ( (len = MultiByteToWideChar( CP_ACP, 0, text, -1, NULL, 0 )) ) {
+ if ( (textW = Alloc( len * sizeof(WCHAR) )) )
+ MultiByteToWideChar( CP_ACP, 0, text, -1, textW, len );
+ }
+ }
+ DrawStatusTextW( hdc, lprc, textW, style );
+ Free( textW );
+}
+
+
+/***********************************************************************
+ * CreateStatusWindow [COMCTL32.@]
+ * CreateStatusWindowA [COMCTL32.6]
+ *
+ * Creates a status bar
+ *
+ * PARAMS
+ * style [I] window style
+ * text [I] pointer to the window text
+ * parent [I] handle to the parent window
+ * wid [I] control id of the status bar
+ *
+ * RETURNS
+ * Success: handle to the status window
+ * Failure: 0
+ */
+
+HWND WINAPI
+CreateStatusWindowA (LONG style, LPCSTR text, HWND parent, UINT wid)
+{
+ return CreateWindowA(STATUSCLASSNAMEA, text, style,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ parent, (HMENU)wid, 0, 0);
+}
+
+
+/***********************************************************************
+ * CreateStatusWindowW [COMCTL32.@]
+ *
+ * Creates a status bar control
+ *
+ * PARAMS
+ * style [I] window style
+ * text [I] pointer to the window text
+ * parent [I] handle to the parent window
+ * wid [I] control id of the status bar
+ *
+ * RETURNS
+ * Success: handle to the status window
+ * Failure: 0
+ */
+
+HWND WINAPI
+CreateStatusWindowW (LONG style, LPCWSTR text, HWND parent, UINT wid)
+{
+ return CreateWindowW(STATUSCLASSNAMEW, text, style,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ parent, (HMENU)wid, 0, 0);
+}
+
+
+/***********************************************************************
+ * CreateUpDownControl [COMCTL32.16]
+ *
+ * Creates an up-down control
+ *
+ * PARAMS
+ * style [I] window styles
+ * x [I] horizontal position of the control
+ * y [I] vertical position of the control
+ * cx [I] with of the control
+ * cy [I] height of the control
+ * parent [I] handle to the parent window
+ * id [I] the control's identifier
+ * inst [I] handle to the application's module instance
+ * buddy [I] handle to the buddy window, can be NULL
+ * maxVal [I] upper limit of the control
+ * minVal [I] lower limit of the control
+ * curVal [I] current value of the control
+ *
+ * RETURNS
+ * Success: handle to the updown control
+ * Failure: 0
+ */
+
+HWND WINAPI
+CreateUpDownControl (DWORD style, INT x, INT y, INT cx, INT cy,
+ HWND parent, INT id, HINSTANCE inst,
+ HWND buddy, INT maxVal, INT minVal, INT curVal)
+{
+ HWND hUD =
+ CreateWindowW (UPDOWN_CLASSW, 0, style, x, y, cx, cy,
+ parent, (HMENU)id, inst, 0);
+ if (hUD) {
+ SendMessageW (hUD, UDM_SETBUDDY, (WPARAM)buddy, 0);
+ SendMessageW (hUD, UDM_SETRANGE, 0, MAKELONG(maxVal, minVal));
+ SendMessageW (hUD, UDM_SETPOS, 0, MAKELONG(curVal, 0));
+ }
+
+ return hUD;
+}
+
+
+/***********************************************************************
+ * InitCommonControls [COMCTL32.17]
+ *
+ * Registers the common controls.
+ *
+ * PARAMS
+ * No parameters.
+ *
+ * RETURNS
+ * No return values.
+ *
+ * NOTES
+ * This function is just a dummy.
+ * The Win95 controls are registered at the DLL's initialization.
+ * To register other controls InitCommonControlsEx() must be used.
+ */
+
+VOID WINAPI
+InitCommonControls (void)
+{
+}
+
+
+/***********************************************************************
+ * InitCommonControlsEx [COMCTL32.@]
+ *
+ * Registers the common controls.
+ *
+ * PARAMS
+ * lpInitCtrls [I] pointer to an INITCOMMONCONTROLS structure.
+ *
+ * RETURNS
+ * Success: TRUE
+ * Failure: FALSE
+ *
+ * NOTES
+ * Only the additional common controls are registered by this function.
+ * The Win95 controls are registered at the DLL's initialization.
+ *
+ * FIXME
+ * implement the following control classes:
+ * ICC_LINK_CLASS
+ * ICC_STANDARD_CLASSES
+ */
+
+BOOL WINAPI
+InitCommonControlsEx (LPINITCOMMONCONTROLSEX lpInitCtrls)
+{
+ INT cCount;
+ DWORD dwMask;
+
+ if (!lpInitCtrls)
+ return FALSE;
+ if (lpInitCtrls->dwSize != sizeof(INITCOMMONCONTROLSEX))
+ return FALSE;
+
+ TRACE("(0x%08lx)\n", lpInitCtrls->dwICC);
+
+ for (cCount = 0; cCount < 32; cCount++) {
+ dwMask = 1 << cCount;
+ if (!(lpInitCtrls->dwICC & dwMask))
+ continue;
+
+ switch (lpInitCtrls->dwICC & dwMask) {
+ /* dummy initialization */
+ case ICC_ANIMATE_CLASS:
+ case ICC_BAR_CLASSES:
+ case ICC_LISTVIEW_CLASSES:
+ case ICC_TREEVIEW_CLASSES:
+ case ICC_TAB_CLASSES:
+ case ICC_UPDOWN_CLASS:
+ case ICC_PROGRESS_CLASS:
+ case ICC_HOTKEY_CLASS:
+ break;
+
+ /* advanced classes - not included in Win95 */
+ case ICC_DATE_CLASSES:
+ MONTHCAL_Register ();
+ DATETIME_Register ();
+ break;
+
+ case ICC_USEREX_CLASSES:
+ COMBOEX_Register ();
+ break;
+
+ case ICC_COOL_CLASSES:
+ REBAR_Register ();
+ break;
+
+ case ICC_INTERNET_CLASSES:
+ IPADDRESS_Register ();
+ break;
+
+ case ICC_PAGESCROLLER_CLASS:
+ PAGER_Register ();
+ break;
+
+ case ICC_NATIVEFNTCTL_CLASS:
+ NATIVEFONT_Register ();
+ break;
+
+ case ICC_LINK_CLASS:
+ SYSLINK_Register ();
+ break;
+
+ default:
+ FIXME("Unknown class! dwICC=0x%lX\n", dwMask);
+ break;
+ }
+ }
+
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * CreateToolbarEx [COMCTL32.@]
+ *
+ * Creates a toolbar window.
+ *
+ * PARAMS
+ * hwnd
+ * style
+ * wID
+ * nBitmaps
+ * hBMInst
+ * wBMID
+ * lpButtons
+ * iNumButtons
+ * dxButton
+ * dyButton
+ * dxBitmap
+ * dyBitmap
+ * uStructSize
+ *
+ * RETURNS
+ * Success: handle to the tool bar control
+ * Failure: 0
+ */
+
+HWND WINAPI
+CreateToolbarEx (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
+ HINSTANCE hBMInst, UINT wBMID, LPCTBBUTTON lpButtons,
+ INT iNumButtons, INT dxButton, INT dyButton,
+ INT dxBitmap, INT dyBitmap, UINT uStructSize)
+{
+ HWND hwndTB;
+
+ hwndTB =
+ CreateWindowExW(0, TOOLBARCLASSNAMEW, NULL, style|WS_CHILD, 0,0,100,30,
+ hwnd, (HMENU)wID, COMCTL32_hModule, NULL);
+ if(hwndTB) {
+ TBADDBITMAP tbab;
+
+ SendMessageW (hwndTB, TB_BUTTONSTRUCTSIZE, (WPARAM)uStructSize, 0);
+
+ /* set bitmap and button size */
+ /*If CreateToolbarEx receives 0, windows sets default values*/
+ if (dxBitmap <= 0)
+ dxBitmap = 16;
+ if (dyBitmap <= 0)
+ dyBitmap = 15;
+ SendMessageW (hwndTB, TB_SETBITMAPSIZE, 0,
+ MAKELPARAM((WORD)dxBitmap, (WORD)dyBitmap));
+
+ if (dxButton <= 0)
+ dxButton = 24;
+ if (dyButton <= 0)
+ dyButton = 22;
+ SendMessageW (hwndTB, TB_SETBUTTONSIZE, 0,
+ MAKELPARAM((WORD)dxButton, (WORD)dyButton));
+
+
+ /* add bitmaps */
+ if (nBitmaps > 0)
+ {
+ tbab.hInst = hBMInst;
+ tbab.nID = wBMID;
+
+ SendMessageW (hwndTB, TB_ADDBITMAP, (WPARAM)nBitmaps, (LPARAM)&tbab);
+ }
+ /* add buttons */
+ if(iNumButtons > 0)
+ SendMessageW (hwndTB, TB_ADDBUTTONSW,
+ (WPARAM)iNumButtons, (LPARAM)lpButtons);
+ }
+
+ return hwndTB;
+}
+
+
+/***********************************************************************
+ * CreateMappedBitmap [COMCTL32.8]
+ *
+ * Loads a bitmap resource using a colour map.
+ *
+ * PARAMS
+ * hInstance [I] Handle to the module containing the bitmap.
+ * idBitmap [I] The bitmap resource ID.
+ * wFlags [I] CMB_MASKED for using bitmap as a mask or 0 for normal.
+ * lpColorMap [I] Colour information needed for the bitmap or NULL (uses system colours).
+ * iNumMaps [I] Number of COLORMAP's pointed to by lpColorMap.
+ *
+ * RETURNS
+ * Success: handle to the new bitmap
+ * Failure: 0
+ */
+
+HBITMAP WINAPI
+CreateMappedBitmap (HINSTANCE hInstance, INT idBitmap, UINT wFlags,
+ LPCOLORMAP lpColorMap, INT iNumMaps)
+{
+ HGLOBAL hglb;
+ HRSRC hRsrc;
+ LPBITMAPINFOHEADER lpBitmap, lpBitmapInfo;
+ UINT nSize, nColorTableSize, iColor;
+ RGBQUAD *pColorTable;
+ INT i, iMaps, nWidth, nHeight;
+ HDC hdcScreen;
+ HBITMAP hbm;
+ LPCOLORMAP sysColorMap;
+ COLORREF cRef;
+ COLORMAP internalColorMap[4] =
+ {{0x000000, 0}, {0x808080, 0}, {0xC0C0C0, 0}, {0xFFFFFF, 0}};
+
+ /* initialize pointer to colortable and default color table */
+ if (lpColorMap) {
+ iMaps = iNumMaps;
+ sysColorMap = lpColorMap;
+ }
+ else {
+ internalColorMap[0].to = GetSysColor (COLOR_BTNTEXT);
+ internalColorMap[1].to = GetSysColor (COLOR_BTNSHADOW);
+ internalColorMap[2].to = GetSysColor (COLOR_BTNFACE);
+ internalColorMap[3].to = GetSysColor (COLOR_BTNHIGHLIGHT);
+ iMaps = 4;
+ sysColorMap = (LPCOLORMAP)internalColorMap;
+ }
+
+ hRsrc = FindResourceW (hInstance, (LPWSTR)idBitmap, (LPWSTR)RT_BITMAP);
+ if (hRsrc == 0)
+ return 0;
+ hglb = LoadResource (hInstance, hRsrc);
+ if (hglb == 0)
+ return 0;
+ lpBitmap = (LPBITMAPINFOHEADER)LockResource (hglb);
+ if (lpBitmap == NULL)
+ return 0;
+
+ if (lpBitmap->biSize >= sizeof(BITMAPINFOHEADER) && lpBitmap->biClrUsed)
+ nColorTableSize = lpBitmap->biClrUsed;
+ else if (lpBitmap->biBitCount <= 8)
+ nColorTableSize = (1 << lpBitmap->biBitCount);
+ else
+ nColorTableSize = 0;
+ nSize = lpBitmap->biSize + nColorTableSize * sizeof(RGBQUAD);
+ lpBitmapInfo = (LPBITMAPINFOHEADER)GlobalAlloc (GMEM_FIXED, nSize);
+ if (lpBitmapInfo == NULL)
+ return 0;
+ RtlMoveMemory (lpBitmapInfo, lpBitmap, nSize);
+
+ pColorTable = (RGBQUAD*)(((LPBYTE)lpBitmapInfo)+(UINT)lpBitmapInfo->biSize);
+
+ for (iColor = 0; iColor < nColorTableSize; iColor++) {
+ for (i = 0; i < iMaps; i++) {
+ cRef = RGB(pColorTable[iColor].rgbRed,
+ pColorTable[iColor].rgbGreen,
+ pColorTable[iColor].rgbBlue);
+ if ( cRef == sysColorMap[i].from) {
+#if 0
+ if (wFlags & CBS_MASKED) {
+ if (sysColorMap[i].to != COLOR_BTNTEXT)
+ pColorTable[iColor] = RGB(255, 255, 255);
+ }
+ else
+#endif
+ pColorTable[iColor].rgbBlue = GetBValue(sysColorMap[i].to);
+ pColorTable[iColor].rgbGreen = GetGValue(sysColorMap[i].to);
+ pColorTable[iColor].rgbRed = GetRValue(sysColorMap[i].to);
+ break;
+ }
+ }
+ }
+ nWidth = (INT)lpBitmapInfo->biWidth;
+ nHeight = (INT)lpBitmapInfo->biHeight;
+ hdcScreen = GetDC (NULL);
+ hbm = CreateCompatibleBitmap (hdcScreen, nWidth, nHeight);
+ if (hbm) {
+ HDC hdcDst = CreateCompatibleDC (hdcScreen);
+ HBITMAP hbmOld = SelectObject (hdcDst, hbm);
+ LPBYTE lpBits = (LPBYTE)(lpBitmap + 1);
+ lpBits += nColorTableSize * sizeof(RGBQUAD);
+ StretchDIBits (hdcDst, 0, 0, nWidth, nHeight, 0, 0, nWidth, nHeight,
+ lpBits, (LPBITMAPINFO)lpBitmapInfo, DIB_RGB_COLORS,
+ SRCCOPY);
+ SelectObject (hdcDst, hbmOld);
+ DeleteDC (hdcDst);
+ }
+ ReleaseDC (NULL, hdcScreen);
+ GlobalFree ((HGLOBAL)lpBitmapInfo);
+ FreeResource (hglb);
+
+ return hbm;
+}
+
+
+/***********************************************************************
+ * CreateToolbar [COMCTL32.7]
+ *
+ * Creates a toolbar control.
+ *
+ * PARAMS
+ * hwnd
+ * style
+ * wID
+ * nBitmaps
+ * hBMInst
+ * wBMID
+ * lpButtons
+ * iNumButtons
+ *
+ * RETURNS
+ * Success: handle to the tool bar control
+ * Failure: 0
+ *
+ * NOTES
+ * Do not use this functions anymore. Use CreateToolbarEx instead.
+ */
+
+HWND WINAPI
+CreateToolbar (HWND hwnd, DWORD style, UINT wID, INT nBitmaps,
+ HINSTANCE hBMInst, UINT wBMID,
+ LPCTBBUTTON lpButtons,INT iNumButtons)
+{
+ return CreateToolbarEx (hwnd, style | CCS_NODIVIDER, wID, nBitmaps,
+ hBMInst, wBMID, lpButtons,
+ iNumButtons, 0, 0, 0, 0, CCSIZEOF_STRUCT(TBBUTTON, dwData));
+}
+
+
+/***********************************************************************
+ * DllGetVersion [COMCTL32.@]
+ *
+ * Retrieves version information of the 'COMCTL32.DLL'
+ *
+ * PARAMS
+ * pdvi [O] pointer to version information structure.
+ *
+ * RETURNS
+ * Success: S_OK
+ * Failure: E_INVALIDARG
+ *
+ * NOTES
+ * Returns version of a comctl32.dll from IE4.01 SP1.
+ */
+
+HRESULT WINAPI
+COMCTL32_DllGetVersion (DLLVERSIONINFO *pdvi)
+{
+ if (pdvi->cbSize != sizeof(DLLVERSIONINFO)) {
+ WARN("wrong DLLVERSIONINFO size from app\n");
+ return E_INVALIDARG;
+ }
+
+ pdvi->dwMajorVersion = COMCTL32_VERSION;
+ pdvi->dwMinorVersion = COMCTL32_VERSION_MINOR;
+ pdvi->dwBuildNumber = 2919;
+ pdvi->dwPlatformID = 6304;
+
+ TRACE("%lu.%lu.%lu.%lu\n",
+ pdvi->dwMajorVersion, pdvi->dwMinorVersion,
+ pdvi->dwBuildNumber, pdvi->dwPlatformID);
+
+ return S_OK;
+}
+
+/***********************************************************************
+ * DllInstall (COMCTL32.@)
+ *
+ * Installs the ComCtl32 DLL.
+ *
+ * RETURNS
+ * Success: S_OK
+ * Failure: A HRESULT error
+ */
+HRESULT WINAPI COMCTL32_DllInstall(BOOL bInstall, LPCWSTR cmdline)
+{
+ FIXME("(%s, %s): stub\n", bInstall?"TRUE":"FALSE",
+ debugstr_w(cmdline));
+
+ return S_OK;
+}
+
+/***********************************************************************
+ * _TrackMouseEvent [COMCTL32.@]
+ *
+ * Requests notification of mouse events
+ *
+ * During mouse tracking WM_MOUSEHOVER or WM_MOUSELEAVE events are posted
+ * to the hwnd specified in the ptme structure. After the event message
+ * is posted to the hwnd, the entry in the queue is removed.
+ *
+ * If the current hwnd isn't ptme->hwndTrack the TME_HOVER flag is completely
+ * ignored. The TME_LEAVE flag results in a WM_MOUSELEAVE message being posted
+ * immediately and the TME_LEAVE flag being ignored.
+ *
+ * PARAMS
+ * ptme [I,O] pointer to TRACKMOUSEEVENT information structure.
+ *
+ * RETURNS
+ * Success: non-zero
+ * Failure: zero
+ *
+ * IMPLEMENTATION moved to USER32.TrackMouseEvent
+ *
+ */
+
+BOOL WINAPI
+_TrackMouseEvent (TRACKMOUSEEVENT *ptme)
+{
+ return TrackMouseEvent (ptme);
+}
+
+/*************************************************************************
+ * GetMUILanguage [COMCTL32.@]
+ *
+ * Returns the user interface language in use by the current process.
+ *
+ * RETURNS
+ * Language ID in use by the current process.
+ */
+LANGID WINAPI GetMUILanguage (VOID)
+{
+ return COMCTL32_uiLang;
+}
+
+
+/*************************************************************************
+ * InitMUILanguage [COMCTL32.@]
+ *
+ * Sets the user interface language to be used by the current process.
+ *
+ * RETURNS
+ * Nothing.
+ */
+VOID WINAPI InitMUILanguage (LANGID uiLang)
+{
+ COMCTL32_uiLang = uiLang;
+}
+
+
+/***********************************************************************
+ * SetWindowSubclass [COMCTL32.410]
+ *
+ * Starts a window subclass
+ *
+ * PARAMS
+ * hWnd [in] handle to window subclass.
+ * pfnSubclass [in] Pointer to new window procedure.
+ * uIDSubclass [in] Unique identifier of sublass together with pfnSubclass.
+ * dwRef [in] Reference data to pass to window procedure.
+ *
+ * RETURNS
+ * Success: non-zero
+ * Failure: zero
+ *
+ * BUGS
+ * If an application manually subclasses a window after subclassing it with
+ * this API and then with this API again, then none of the previous
+ * subclasses get called or the origional window procedure.
+ */
+
+BOOL WINAPI SetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
+ UINT_PTR uIDSubclass, DWORD_PTR dwRef)
+{
+ LPSUBCLASS_INFO stack;
+ LPSUBCLASSPROCS proc;
+
+ TRACE ("(%p, %p, %x, %lx)\n", hWnd, pfnSubclass, uIDSubclass, dwRef);
+
+ /* Since the window procedure that we set here has two additional arguments,
+ * we can't simply set it as the new window procedure of the window. So we
+ * set our own window procedure and then calculate the other two arguments
+ * from there. */
+
+ /* See if we have been called for this window */
+ stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
+ if (!stack) {
+ /* allocate stack */
+ stack = Alloc (sizeof(SUBCLASS_INFO));
+ if (!stack) {
+ ERR ("Failed to allocate our Subclassing stack\n");
+ return FALSE;
+ }
+ SetPropW (hWnd, COMCTL32_wSubclass, (HANDLE)stack);
+
+ /* set window procedure to our own and save the current one */
+ if (IsWindowUnicode (hWnd))
+ stack->origproc = (WNDPROC)SetWindowLongPtrW (hWnd, GWLP_WNDPROC,
+ (DWORD_PTR)COMCTL32_SubclassProc);
+ else
+ stack->origproc = (WNDPROC)SetWindowLongPtrA (hWnd, GWLP_WNDPROC,
+ (DWORD_PTR)COMCTL32_SubclassProc);
+ }
+ else {
+ /* Check to see if we have called this function with the same uIDSubClass
+ * and pfnSubclass */
+ proc = stack->SubclassProcs;
+ while (proc) {
+ if ((proc->id == uIDSubclass) &&
+ (proc->subproc == pfnSubclass)) {
+ proc->ref = dwRef;
+ return TRUE;
+ }
+ proc = proc->next;
+ }
+ }
+
+ proc = Alloc(sizeof(SUBCLASSPROCS));
+ if (!proc) {
+ ERR ("Failed to allocate subclass entry in stack\n");
+ if (IsWindowUnicode (hWnd))
+ SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
+ else
+ SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
+ Free (stack);
+ RemovePropW( hWnd, COMCTL32_wSubclass );
+ return FALSE;
+ }
+
+ proc->subproc = pfnSubclass;
+ proc->ref = dwRef;
+ proc->id = uIDSubclass;
+ proc->next = stack->SubclassProcs;
+ stack->SubclassProcs = proc;
+
+ return TRUE;
+}
+
+
+/***********************************************************************
+ * GetWindowSubclass [COMCTL32.411]
+ *
+ * Gets the Reference data from a subclass.
+ *
+ * PARAMS
+ * hWnd [in] Handle to window which were subclassing
+ * pfnSubclass [in] Pointer to the subclass procedure
+ * uID [in] Unique indentifier of the subclassing procedure
+ * pdwRef [out] Pointer to the reference data
+ *
+ * RETURNS
+ * Success: Non-zero
+ * Failure: 0
+ */
+
+BOOL WINAPI GetWindowSubclass (HWND hWnd, SUBCLASSPROC pfnSubclass,
+ UINT_PTR uID, DWORD_PTR *pdwRef)
+{
+ LPSUBCLASS_INFO stack;
+ LPSUBCLASSPROCS proc;
+
+ TRACE ("(%p, %p, %x, %p)\n", hWnd, pfnSubclass, uID, pdwRef);
+
+ /* See if we have been called for this window */
+ stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
+ if (!stack)
+ return FALSE;
+
+ proc = stack->SubclassProcs;
+ while (proc) {
+ if ((proc->id == uID) &&
+ (proc->subproc == pfnSubclass)) {
+ *pdwRef = proc->ref;
+ return TRUE;
+ }
+ proc = proc->next;
+ }
+
+ return FALSE;
+}
+
+
+/***********************************************************************
+ * RemoveWindowSubclass [COMCTL32.412]
+ *
+ * Removes a window subclass.
+ *
+ * PARAMS
+ * hWnd [in] Handle to the window were subclassing
+ * pfnSubclass [in] Pointer to the subclass procedure
+ * uID [in] Unique identifier of this subclass
+ *
+ * RETURNS
+ * Success: non-zero
+ * Failure: zero
+ */
+
+BOOL WINAPI RemoveWindowSubclass(HWND hWnd, SUBCLASSPROC pfnSubclass, UINT_PTR uID)
+{
+ LPSUBCLASS_INFO stack;
+ LPSUBCLASSPROCS prevproc = NULL;
+ LPSUBCLASSPROCS proc;
+ BOOL ret = FALSE;
+
+ TRACE ("(%p, %p, %x)\n", hWnd, pfnSubclass, uID);
+
+ /* Find the Subclass to remove */
+ stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
+ if (!stack)
+ return FALSE;
+
+ proc = stack->SubclassProcs;
+ while (proc) {
+ if ((proc->id == uID) &&
+ (proc->subproc == pfnSubclass)) {
+
+ if (!prevproc)
+ stack->SubclassProcs = proc->next;
+ else
+ prevproc->next = proc->next;
+
+ if (stack->stackpos == proc)
+ stack->stackpos = stack->stackpos->next;
+
+ Free (proc);
+ ret = TRUE;
+ break;
+ }
+ prevproc = proc;
+ proc = proc->next;
+ }
+
+ if (!stack->SubclassProcs && !stack->running) {
+ TRACE("Last Subclass removed, cleaning up\n");
+ /* clean up our heap and reset the origional window procedure */
+ if (IsWindowUnicode (hWnd))
+ SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
+ else
+ SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
+ Free (stack);
+ RemovePropW( hWnd, COMCTL32_wSubclass );
+ }
+
+ return ret;
+}
+
+/***********************************************************************
+ * COMCTL32_SubclassProc (internal)
+ *
+ * Window procedure for all subclassed windows.
+ * Saves the current subclassing stack position to support nested messages
+ */
+LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ LPSUBCLASS_INFO stack;
+ LPSUBCLASSPROCS proc;
+ LRESULT ret;
+
+ TRACE ("(%p, 0x%08x, 0x%08x, 0x%08lx)\n", hWnd, uMsg, wParam, lParam);
+
+ stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
+ if (!stack) {
+ ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
+ return 0;
+ }
+
+ /* Save our old stackpos to properly handle nested messages */
+ proc = stack->stackpos;
+ stack->stackpos = stack->SubclassProcs;
+ stack->running++;
+ ret = DefSubclassProc(hWnd, uMsg, wParam, lParam);
+ stack->running--;
+ stack->stackpos = proc;
+
+ if (!stack->SubclassProcs && !stack->running) {
+ TRACE("Last Subclass removed, cleaning up\n");
+ /* clean up our heap and reset the origional window procedure */
+ if (IsWindowUnicode (hWnd))
+ SetWindowLongPtrW (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
+ else
+ SetWindowLongPtrA (hWnd, GWLP_WNDPROC, (DWORD_PTR)stack->origproc);
+ Free (stack);
+ RemovePropW( hWnd, COMCTL32_wSubclass );
+ }
+ return ret;
+}
+
+/***********************************************************************
+ * DefSubclassProc [COMCTL32.413]
+ *
+ * Calls the next window procedure (ie. the one before this subclass)
+ *
+ * PARAMS
+ * hWnd [in] The window that we're subclassing
+ * uMsg [in] Message
+ * wParam [in] WPARAM
+ * lParam [in] LPARAM
+ *
+ * RETURNS
+ * Success: non-zero
+ * Failure: zero
+ */
+
+LRESULT WINAPI DefSubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+ LPSUBCLASS_INFO stack;
+ LRESULT ret;
+
+ TRACE ("(%p, 0x%08x, 0x%08x, 0x%08lx)\n", hWnd, uMsg, wParam, lParam);
+
+ /* retrieve our little stack from the Properties */
+ stack = (LPSUBCLASS_INFO)GetPropW (hWnd, COMCTL32_wSubclass);
+ if (!stack) {
+ ERR ("Our sub classing stack got erased for %p!! Nothing we can do\n", hWnd);
+ return 0;
+ }
+
+ /* If we are at the end of stack then we have to call the original
+ * window procedure */
+ if (!stack->stackpos) {
+ if (IsWindowUnicode (hWnd))
+ ret = CallWindowProcW (stack->origproc, hWnd, uMsg, wParam, lParam);
+ else
+ ret = CallWindowProcA (stack->origproc, hWnd, uMsg, wParam, lParam);
+ } else {
+ LPSUBCLASSPROCS proc = stack->stackpos;
+ stack->stackpos = stack->stackpos->next;
+ /* call the Subclass procedure from the stack */
+ ret = proc->subproc (hWnd, uMsg, wParam, lParam,
+ proc->id, proc->ref);
+ }
+
+ return ret;
+}
+
+
+/***********************************************************************
+ * COMCTL32_CreateToolTip [NOT AN API]
+ *
+ * Creates a tooltip for the control specified in hwnd and does all
+ * necessary setup and notifications.
+ *
+ * PARAMS
+ * hwndOwner [I] Handle to the window that will own the tool tip.
+ *
+ * RETURNS
+ * Success: Handle of tool tip window.
+ * Failure: NULL
+ */
+
+HWND
+COMCTL32_CreateToolTip(HWND hwndOwner)
+{
+ HWND hwndToolTip;
+
+ hwndToolTip = CreateWindowExW(0, TOOLTIPS_CLASSW, NULL, 0,
+ CW_USEDEFAULT, CW_USEDEFAULT,
+ CW_USEDEFAULT, CW_USEDEFAULT, hwndOwner,
+ 0, 0, 0);
+
+ /* Send NM_TOOLTIPSCREATED notification */
+ if (hwndToolTip)
+ {
+ NMTOOLTIPSCREATED nmttc;
+ /* true owner can be different if hwndOwner is a child window */
+ HWND hwndTrueOwner = GetWindow(hwndToolTip, GW_OWNER);
+ nmttc.hdr.hwndFrom = hwndTrueOwner;
+ nmttc.hdr.idFrom = GetWindowLongPtrW(hwndTrueOwner, GWLP_ID);
+ nmttc.hdr.code = NM_TOOLTIPSCREATED;
+ nmttc.hwndToolTips = hwndToolTip;
+
+ SendMessageW(GetParent(hwndTrueOwner), WM_NOTIFY,
+ (WPARAM)GetWindowLongPtrW(hwndTrueOwner, GWLP_ID),
+ (LPARAM)&nmttc);
+ }
+
+ return hwndToolTip;
+}
+
+
+/***********************************************************************
+ * COMCTL32_RefreshSysColors [NOT AN API]
+ *
+ * Invoked on any control recognizing a WM_SYSCOLORCHANGE message to
+ * refresh the color values in the color structure
+ *
+ * PARAMS
+ * none
+ *
+ * RETURNS
+ * none
+ */
+
+VOID
+COMCTL32_RefreshSysColors(void)
+{
+ comctl32_color.clrBtnHighlight = GetSysColor (COLOR_BTNHIGHLIGHT);
+ comctl32_color.clrBtnShadow = GetSysColor (COLOR_BTNSHADOW);
+ comctl32_color.clrBtnText = GetSysColor (COLOR_BTNTEXT);
+ comctl32_color.clrBtnFace = GetSysColor (COLOR_BTNFACE);
+ comctl32_color.clrHighlight = GetSysColor (COLOR_HIGHLIGHT);
+ comctl32_color.clrHighlightText = GetSysColor (COLOR_HIGHLIGHTTEXT);
+ comctl32_color.clr3dHilight = GetSysColor (COLOR_3DHILIGHT);
+ comctl32_color.clr3dShadow = GetSysColor (COLOR_3DSHADOW);
+ comctl32_color.clr3dDkShadow = GetSysColor (COLOR_3DDKSHADOW);
+ comctl32_color.clr3dFace = GetSysColor (COLOR_3DFACE);
+ comctl32_color.clrWindow = GetSysColor (COLOR_WINDOW);
+ comctl32_color.clrWindowText = GetSysColor (COLOR_WINDOWTEXT);
+ comctl32_color.clrGrayText = GetSysColor (COLOR_GRAYTEXT);
+ comctl32_color.clrActiveCaption = GetSysColor (COLOR_ACTIVECAPTION);
+ comctl32_color.clrInfoBk = GetSysColor (COLOR_INFOBK);
+ comctl32_color.clrInfoText = GetSysColor (COLOR_INFOTEXT);
+}
+
+/***********************************************************************
+ * COMCTL32_DrawInsertMark [NOT AN API]
+ *
+ * Draws an insertion mark (which looks similar to an 'I').
+ *
+ * PARAMS
+ * hDC [I] Device context to draw onto.
+ * lpRect [I] Co-ordinates of insertion mark.
+ * clrInsertMark [I] Colour of the insertion mark.
+ * bHorizontal [I] True if insert mark should be drawn horizontally,
+ * vertical otherwise.
+ *
+ * RETURNS
+ * none
+ *
+ * NOTES
+ * Draws up to but not including the bottom co-ordinate when drawing
+ * vertically or the right co-ordinate when horizontal.
+ */
+void COMCTL32_DrawInsertMark(HDC hDC, const RECT *lpRect, COLORREF clrInsertMark, BOOL bHorizontal)
+{
+ HPEN hPen = CreatePen(PS_SOLID, 1, clrInsertMark);
+ HPEN hOldPen;
+ static const DWORD adwPolyPoints[] = {4,4,4};
+ LONG lCentre = (bHorizontal ?
+ lpRect->top + (lpRect->bottom - lpRect->top)/2 :
+ lpRect->left + (lpRect->right - lpRect->left)/2);
+ LONG l1 = (bHorizontal ? lpRect->left : lpRect->top);
+ LONG l2 = (bHorizontal ? lpRect->right : lpRect->bottom);
+ const POINT aptInsertMark[] =
+ {
+ /* top (V) or left (H) arrow */
+ {lCentre , l1 + 2},
+ {lCentre - 2, l1 },
+ {lCentre + 3, l1 },
+ {lCentre + 1, l1 + 2},
+ /* middle line */
+ {lCentre , l2 - 2},
+ {lCentre , l1 - 1},
+ {lCentre + 1, l1 - 1},
+ {lCentre + 1, l2 - 2},
+ /* bottom (V) or right (H) arrow */
+ {lCentre , l2 - 3},
+ {lCentre - 2, l2 - 1},
+ {lCentre + 3, l2 - 1},
+ {lCentre + 1, l2 - 3},
+ };
+ hOldPen = SelectObject(hDC, hPen);
+ PolyPolyline(hDC, aptInsertMark, adwPolyPoints, sizeof(adwPolyPoints)/sizeof(adwPolyPoints[0]));
+ SelectObject(hDC, hOldPen);
+ DeleteObject(hPen);
+}
+
+/***********************************************************************
+ * MirrorIcon [COMCTL32.414]
+ *
+ * Mirrors an icon so that it will appear correctly on a mirrored DC.
+ *
+ * PARAMS
+ * phicon1 [I/O] Icon.
+ * phicon2 [I/O] Icon.
+ *
+ * RETURNS
+ * Success: TRUE.
+ * Failure: FALSE.
+ */
+BOOL WINAPI MirrorIcon(HICON *phicon1, HICON *phicon2)
+{
+ FIXME("(%p, %p): stub\n", phicon1, phicon2);
+ return FALSE;
+}
+
+static inline int IsDelimiter(WCHAR c)
+{
+ switch(c)
+ {
+ case '/':
+ case '\\':
+ case '.':
+ case ' ':
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static int CALLBACK PathWordBreakProc(LPWSTR lpch, int ichCurrent, int cch, int code)
+{
+ if (code == WB_ISDELIMITER)
+ return IsDelimiter(lpch[ichCurrent]);
+ else
+ {
+ int dir = (code == WB_LEFT) ? -1 : 1;
+ for(; 0 <= ichCurrent && ichCurrent < cch; ichCurrent += dir)
+ if (IsDelimiter(lpch[ichCurrent])) return ichCurrent;
+ }
+ return ichCurrent;
+}
+
+/***********************************************************************
+ * SetPathWordBreakProc [COMCTL32.384]
+ *
+ * Sets the word break procedure for an edit control to one that understands
+ * paths so that the user can jump over directories.
+ *
+ * PARAMS
+ * hwnd [I] Handle to edit control.
+ * bSet [I] If this is TRUE then the word break proc is set, otherwise it is removed.
+ *
+ * RETURNS
+ * Result from EM_SETWORDBREAKPROC message.
+ */
+LRESULT WINAPI SetPathWordBreakProc(HWND hwnd, BOOL bSet)
+{
+ return SendMessageW(hwnd, EM_SETWORDBREAKPROC, 0,
+ (LPARAM)(bSet ? PathWordBreakProc : NULL));
+}