📄 commctrl.c
字号:
/*
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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,%x,%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_PTR)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 ();
/* subclass user32 controls */
THEMING_Initialize ();
break;
case DLL_PROCESS_DETACH:
/* clean up subclassing */
THEMING_Uninitialize();
/* 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_PTR 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)(DWORD_PTR)lpInfo[1], uFlags, MF_BYCOMMAND) & MFS_CHECKED) {
/* uncheck menu item */
CheckMenuItem ((HMENU)(DWORD_PTR)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)(DWORD_PTR)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("(%p %p %p)\n",
hwnd, lpRect, 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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -