⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 classxp.c

📁 AutoNetFidelio酒店管理系统增加智能门锁进行入住发卡及退房收卡。
💻 C
📖 第 1 页 / 共 3 页
字号:



////////////////////////////////////////////////////////////////////////////////////////////////////
// 说明: ClassXP.c 文件
// 更新: 2003-3-10
////////////////////////////////////////////////////////////////////////////////////////////////////



////////////////////////////////////////////////////////////////////////////////////////////////////
// 编译预处理
#if _WIN32_WINNT < 0x0400
#define _WIN32_WINNT 0x0400
#endif
//#include "stdafx.h"
#include <Windows.h>
#include "ClassXP.h"
#pragma warning(disable: 4311)
#pragma warning(disable: 4312)
#pragma comment(lib, "Msimg32.lib")

// 导出函数
#ifdef CXP_DLLMODE
#pragma comment(linker, "/EXPORT:ClassXP=_ClassXP@8")
#endif // CXP_DLLMODE

// 强制使用 C 语言方式编译
#ifdef __cplusplus
extern "C"
{
#endif // __cplusplus
	////////////////////////////////////////////////////////////////////////////////////////////////////
	
	
	
	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 宏定义
	
	// 窗口类型
#define CXPT_UNKNOWN		-1	// 不能处理的类型
#define CXPT_PUSHBUTTON		0	// 按钮
#define CXPT_CHECKBOX		1	// 复选框
#define CXPT_RADIOBOX		2	// 单选框
#define CXPT_EDITBOX		3	// 编辑框
#define CXPT_COMBOBOX		4	// 组合框
	
	
	// 窗口状态
#define CXPS_DISABLED		0x00000001L		// 禁用状态
#define CXPS_PRESSED		0x00000002L		// 按下状态
#define CXPS_HOTLIGHT		0x00000004L		// 高亮状态 (鼠标在该窗口上)
#define CXPS_FOCUS			0x00000008L		// 具有键盘输入焦点
#define CXPS_DEFAULT		0x00000010L		// 默认状态 (用于按钮)
#define CXPS_CHECKED		0x00000020L		// 选中状态 (用于复选框)
#define CXPS_INDETERMINATE	0x00000040L		// 未确定状态 (用于复选框)
#define CXPS_READONLY		0x00000080L		// 只读状态 (用于编辑框)
	
	
	// 设置窗口状态
#define CXPM_SETSTATE(Data, Mask, IsSet)	((IsSet) ? (Data |= Mask) : (Data &= ~Mask))
	////////////////////////////////////////////////////////////////////////////////////////////////////
	
	
	
	////////////////////////////////////////////////////////////////////////////////////////////////////
	// CLASSXP 结构,所有的代码都是围绕这个结构而编写的
	typedef struct tagCLASSXP
	{
		HWND hWnd;					// 窗口句柄
		DWORD dwType;				// 窗口的类型
		DWORD dwState;				// 窗口的状态
		WNDPROC wpPrev;				// 子类化之前的窗口回调函数地址
		struct tagCLASSXP * pNext;	// 指向下一个 CLASSXP 结构,这里采用单向链表结构
	}
	CLASSXP, * PCLASSXP;
	////////////////////////////////////////////////////////////////////////////////////////////////////
	
	
	
	////////////////////////////////////////////////////////////////////////////////////////////////////
	// MEMDCXP 结构,为了方便使用内存兼容设备场景而设计
	typedef struct tagMEMDCXP
	{
		HWND hWnd;					// 窗口句柄,输入参数
		HDC hDC;					// 窗口设备场景,输出参数
		HDC hMemDC;					// 窗口内存兼容设备场景,输出参数
		BOOL bTransfer;				// 是否要用在 hDC 和 hMemDC 间传送数据,输入参数
		HBITMAP hBitmap;			// 位图句柄,输入和输出参数
	}
	MEMDCXP, * LPMEMDCXP;
	////////////////////////////////////////////////////////////////////////////////////////////////////
	
	
	
	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 函数声明
	PCLASSXP WINAPI CreateClassXP(HWND hWnd);
	PCLASSXP WINAPI DeleteClassXP(HWND hWnd);
	PCLASSXP WINAPI GetClassXP(HWND hWnd);
	
	DWORD WINAPI GetWindowTypeXP(HWND hWnd);
	HDC WINAPI GetMemDCXP(LPMEMDCXP pMdcxp);
	VOID WINAPI ReleaseMemDCXP(LPMEMDCXP pMdcxp);
	VOID WINAPI GradientRectXP(HDC hDC, LPRECT pRect,COLORREF crColor[4]);
	VOID WINAPI DrawDropGripXP(HDC hDC, LPRECT pRect);
	
	BOOL CALLBACK EnumWndProcXP(HWND hWnd, LPARAM lParam);
	LRESULT CALLBACK HookProcXP(int iCode, WPARAM wParam, LPARAM lParam);
	LRESULT CALLBACK WindowProcXP(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
	
	VOID WINAPI DrawPushButtonXP(PCLASSXP pCxp);
	VOID WINAPI DrawCheckBoxXP(PCLASSXP pCxp);
	VOID WINAPI DrawRadioBoxXP(PCLASSXP pCxp);
	VOID WINAPI DrawEditBoxXP(PCLASSXP pCxp);
	VOID WINAPI DrawComboBoxXP(PCLASSXP pCxp);
	////////////////////////////////////////////////////////////////////////////////////////////////////
	
	
	
	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 全局变量
	HHOOK g_hPrevHookXP = NULL;		// 窗口消息 HOOK 句柄
	PCLASSXP g_pClassXP = NULL;		// 窗口的 CLASSXP 结构指针
	
#ifdef CXP_DLLMODE
	HINSTANCE g_hModuleXP = NULL;	// 动态连接库模块句柄
#endif // CXP_DLLMODE
	////////////////////////////////////////////////////////////////////////////////////////////////////
	
	
	
#ifdef CXP_DLLMODE
	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 动态连接库主函数
	BOOL WINAPI DllMain(HMODULE hModule, DWORD dwReason, LPVOID pvReserved)
	{
		if (dwReason == DLL_PROCESS_ATTACH)
		{
			g_hModuleXP = hModule;
			DisableThreadLibraryCalls(hModule);
		}
		return TRUE;
	}
	////////////////////////////////////////////////////////////////////////////////////////////////////
#endif // CXP_DLLMODE
	
	
	
	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 设置或取消窗口的 ClassXP 风格
	BOOL WINAPI ClassXP(HWND hWnd, BOOL bEnable)
	{
		BOOL bReturn;
		
		bReturn = FALSE;
		
		// 如果是影响当前进程中的所有窗口
		if (hWnd == NULL)
		{
			// 如果是取消当前进程中的所有窗口
			if ((bEnable == FALSE) && (g_hPrevHookXP != NULL))
			{
				// 枚举当前线程的窗口并取消 ClassXP 风格
				EnumThreadWindows(GetCurrentThreadId(), EnumWndProcXP, FALSE);
				
				// 取消窗口消息 HOOK
				bReturn = UnhookWindowsHookEx(g_hPrevHookXP);
				g_hPrevHookXP = NULL;
			}
			// 如果是设置当前进程中的所有窗口
			else if ((bEnable == TRUE) && (g_hPrevHookXP == NULL))
			{
				// 枚举当前线程中已存在的窗口并设置为 ClassXP 风格
				EnumThreadWindows(GetCurrentThreadId(), EnumWndProcXP, TRUE);
				
				// 安装窗口消息 HOOK
				g_hPrevHookXP = SetWindowsHookEx(WH_CALLWNDPROC, HookProcXP, 0, GetCurrentThreadId());
				bReturn = (BOOL) g_hPrevHookXP;
			}
		}
		else
		{
			// 如果是取消指定窗口的 ClassXP 风格
			if (bEnable == FALSE)
				bReturn = (BOOL) DeleteClassXP(hWnd);
			// 如果是设置指定窗口的 ClassXP 风格
			else
				bReturn = (BOOL) CreateClassXP(hWnd);			
		}
		return bReturn;
	}
	////////////////////////////////////////////////////////////////////////////////////////////////////
	
	
	
	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 创建并初始化 CLASSXP 数据结构;子类化窗口
	// 如果返回 NULL,表示没有创建;否则返回新创建节点的指针,同时 g_pClassXP 指向新创建的节点
	PCLASSXP WINAPI CreateClassXP(HWND hWnd)
	{
		LONG lStyle;
		DWORD dwType;
		PCLASSXP pCxp;
		
		// 是否已经是 ClassXP 风格
		if (GetClassXP(hWnd) == NULL)
		{
			// 获取窗口类型,如果并判断是否能设置为 ClassXP 风格
			dwType = GetWindowTypeXP(hWnd);
			if ((dwType >= CXPT_PUSHBUTTON) && (dwType <= CXPT_COMBOBOX))
			{
				lStyle = GetWindowLong(hWnd, GWL_STYLE);
				
				// 分配存储空间,增加一个节点
				pCxp = (PCLASSXP) HeapAlloc(GetProcessHeap(), 0, sizeof(CLASSXP));
				pCxp->pNext = g_pClassXP;
				g_pClassXP = pCxp;
				
				// 子类化窗口并初始化 CLASSXP 数据结构
				pCxp->hWnd = hWnd;
				pCxp->dwType = dwType;
				pCxp->dwState = (lStyle & WS_DISABLED) ? CXPS_DISABLED : 0;
				if (hWnd == GetFocus())
					pCxp->dwState |= CXPS_FOCUS;
				pCxp->wpPrev = (WNDPROC) SetWindowLong(hWnd, GWL_WNDPROC, (LONG) WindowProcXP);
				
				// 按窗口类型分别 CLASSXP 数据结构
				switch (dwType)
				{
				case CXPT_PUSHBUTTON:
				case CXPT_CHECKBOX:
				case CXPT_RADIOBOX:
					if ((lStyle & SS_TYPEMASK) == BS_DEFPUSHBUTTON)
						pCxp->dwState |= CXPS_DEFAULT;
					
					lStyle = (LONG) SendMessage(hWnd, BM_GETCHECK, 0, 0);
					if (lStyle == BST_CHECKED)
						pCxp->dwState |= CXPS_CHECKED;
					else if (lStyle == BST_INDETERMINATE)
						pCxp->dwState |= CXPS_INDETERMINATE;
					break;
					
				case CXPT_EDITBOX:
					if (lStyle & ES_READONLY)
						pCxp->dwState |= CXPS_READONLY;
					break;
				}
				
				// 重画窗口
				RedrawWindow(hWnd, NULL, NULL,
					RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ERASENOW | RDW_UPDATENOW);
				return pCxp;
			}
		}
		return NULL;
	}
	////////////////////////////////////////////////////////////////////////////////////////////////////
	
	
	
	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 取消窗口子类化;销毁窗口的 CLASSXP 数据结构
	// 如果返回值不为 NULL 表示成功删除,返回值为指向上一个节点指针;
	// 如果返回 NULL 且 g_pClassXP 为 NULL,表全部节点被删除;
	// 否则表示没有找到该节点。
	// 致谢: 感谢 dREAMtHEATER 改进此函数!
	PCLASSXP WINAPI DeleteClassXP(HWND hWnd)
	{
		PCLASSXP pDel;
		PCLASSXP pCxp;
		// 获取待删除的节点指针
		pDel = GetClassXP(hWnd);
		if (pDel != NULL)
		{
			// 如果待删除的节点就是 g_pClassXP 节点
			if (pDel == g_pClassXP)
				pCxp = g_pClassXP = pDel->pNext;
			else
			{
				// 循环查找待删除节点的上一个节点
				for (pCxp = g_pClassXP; pCxp != NULL; pCxp = pCxp->pNext)
				{
					// 如果找到
					if (pCxp->pNext == pDel)
					{
						// 使链表跳过待删除的节点
						pCxp->pNext = pDel->pNext;
						break;
					}
				}
			}
			
			// 取消窗口子类化并重画窗口
			SetWindowLong(hWnd, GWL_WNDPROC, (LONG) pDel->wpPrev);
			
			// 删除堆内存
			HeapFree(GetProcessHeap(), 0, pDel);
			
			// 重画窗口
			RedrawWindow(hWnd, NULL, NULL,
				RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ERASENOW | RDW_UPDATENOW);
			return pCxp;
		}
		return NULL;
	}
	////////////////////////////////////////////////////////////////////////////////////////////////////
	
	
	
	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 获取窗口的 CLASSXP 数据结构
	// 如果返回 NULL,表示没有找到;否则返回节点的指针
	PCLASSXP WINAPI GetClassXP(HWND hWnd)
	{
		PCLASSXP pCxp;
		
		for (pCxp = g_pClassXP; pCxp != NULL; pCxp = pCxp->pNext)
		{
			if (pCxp->hWnd == hWnd)
				return pCxp;
		}
		return FALSE;
	}
	////////////////////////////////////////////////////////////////////////////////////////////////////
	
	
	
	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 获取窗口类型
	DWORD WINAPI GetWindowTypeXP(HWND hWnd)
	{
		DWORD lReturn;
		char szTemp[MAX_PATH];
		static char s_szClass[][32] = 
		{
			"Button",					// 按钮类
				"Edit",						// 编辑框类
				"ComboBox",					// 组合框类
				
#ifdef CXP_DLLMODE
				"TButton",					// VCL TButton 类
				"ThunderCommandButton",		// Visual Basic Command Button 类
				"ThunderRT6CommandButton",	// Visual Basic Command Button 类
				"TCheckBox",
				"ThunderCheckBox",
				"ThunderRT6CheckBox",
				"TEdit",
				"TNumberEdit",
				"ThunderTextBox",
				"ThunderRT6TextBox",
				"TComboBox",
				"ThunderComboBox",
				"ThunderRT6ComboBox"
#endif // CXP_DLLMODE
		};
		
		// 查找判断匹配的类名称
		GetClassName(hWnd, szTemp, sizeof(szTemp));
		for (lReturn = 0; lReturn < (sizeof(s_szClass) / sizeof(s_szClass[0])); lReturn++)
			if (lstrcmpi(szTemp, s_szClass[lReturn]) == 0)
				break;
			
			switch (lReturn)
			{
			case 0:
				lReturn = GetWindowLong(hWnd, GWL_STYLE);
				switch (lReturn & SS_TYPEMASK)
				{
				case BS_DEFPUSHBUTTON:		// 默认按钮
				case BS_PUSHBUTTON:			// 普通按钮
					lReturn = CXPT_PUSHBUTTON;
					break;
					
				case BS_CHECKBOX:			// 复选框
				case BS_AUTOCHECKBOX:		// 自动复选框
				case BS_3STATE:				// 三状态复选框
				case BS_AUTO3STATE:			// 自动三状态复选框
					if (lReturn & BS_PUSHLIKE)
						lReturn = CXPT_PUSHBUTTON;
					else
						lReturn = CXPT_CHECKBOX;
					break;
					
				case BS_RADIOBUTTON:		// 单选框
				case BS_AUTORADIOBUTTON:	// 自动单选框
					if (lReturn & BS_PUSHLIKE)
						lReturn = CXPT_PUSHBUTTON;
					else
						lReturn = CXPT_RADIOBOX;
					break;
					
				default:	// 未知类型
					lReturn = CXPT_UNKNOWN;
				}
				break;
				
				case 1:			// 编辑框
					lReturn = CXPT_EDITBOX;
					break;
					
				case 2:			// 组合框
					if ((GetWindowLong(hWnd, GWL_STYLE) & 0x00000003) == CBS_SIMPLE)
						lReturn = CXPT_UNKNOWN;
					else
						lReturn = CXPT_COMBOBOX;
					break;
					
#ifdef CXP_DLLMODE
					// VB 和 VCL 的控件,只有在动态连接库方式下才有可能出现这种情况
				case 3:
				case 4:
				case 5:
					lReturn = CXPT_PUSHBUTTON;
					break;
					
				case 6:
				case 7:
				case 8:
					lReturn = CXPT_CHECKBOX;
					break;
					
				case 9:
				case 10:
				case 11:
				case 12:
					lReturn = CXPT_EDITBOX;
					break;
					
				case 13:
				case 14:
				case 15:
					lReturn = CXPT_COMBOBOX;
					break;
					
#endif // CXP_DLLMODE
					

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -