/// <summary>
/// 窗体句柄附加数据长度
/// </summary>
#define CTRLWINDOWEXTRA 32
/// <summary>
/// 声明回调函数的宏
/// </summary>
#define DECLARE_WNDPROC(ProcName) LRESULT CALLBACK ProcName(HWND, UINT, WPARAM, LPARAM);
/// <summary>
/// 声明钟表组件的消息回调函数
/// </summary>
DECLARE_WNDPROC(ClockCtrlProc)
/// <summary>
/// 注册窗体类
/// </summary>
static
ATOM _RegistCtrlClass(HINSTANCE hInst, LPCTSTR lpszClsName, WNDPROC pWndProc)
{
WNDCLASSEX wcex = {
sizeof(WNDCLASSEX),
CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS,
pWndProc,
0, CTRLWINDOWEXTRA, hInst, NULL, NULL,
(HBRUSH)(COLOR_BTNFACE + 1),
0, lpszClsName, NULL
};
return RegisterClassEx(&wcex);
}
/// <summary>
/// 初始化用户自定义控件
/// </summary>
BOOL InitializeUserControls()
{
ATOM atom = _RegistCtrlClass(_INSTANCE, _T("ClockCtrl"), (WNDPROC)ClockCtrlProc);
_ASSERT(atom);
if (atom == 0)
return FALSE;
return TRUE;
}
/// <summary>
/// 保存绘图对象的结构体
/// </summary>
typedef struct tagCLK_GDIOBJ
{
HBRUSH brushBackground, // 控件背景画刷
brushDigitalDark, // 数字表盘暗色画刷
brushDigitalLight, // 数字表盘亮色画刷
brushClockBackground; // 表盘背景
LOGFONT fontDate, // 控件全局字体
fontClockNumber; // 表盘数字字体
HPEN penBorder, // 控件边框画笔
penDigitalBorder, // 数字边框画笔
penClockBorder, // 表盘边框画笔
penClockArrow; // 表盘箭头画笔
} CLK_GDIOBJ, *LPCLK_GDIOBJ;
/// <summary>
/// 保存运行时信息的结构体
/// </summary>
typedef struct tagCLK_RUNTIME
{
SYSTEMTIME stimNow; // 当前时间
BOOL isDigitalSecondDark; // 数字表盘的秒针是否为灰色
UINT_PTR timSecond; // 按秒进行的定时器句柄
} CLK_RUNTIME, *LPCLK_RUNTIME;
/// <summary>
/// 表示数据位置的常量
/// </summary>
#define CLKP_GDIOBJ 0 // 0~3字节存放CLK_GDIOBJ结构体变量地址
#define CLKP_RUNTIME (CLKP_GDIOBJ + sizeof(LPCLK_GDIOBJ)) // 4~7字节存放CLK_RUNTIME结构体变量地址 这里定义了两个结构体,一个用于存储GDI对象,一个用于存储运行时状态,这两个结构体的变量都应该和对应的窗口(HWND)句柄进行绑定,这样才能做到令窗体类为“ClockCtrl”的不同窗体都能取到正确的,属于自己的数据。/// <summary>
/// 窗口创建消息
/// </summary>
static
int _OnCreate(HWND hCtrl, LPCREATESTRUCT lpcs)
{
LPCLK_GDIOBJ pGdi;
LPCLK_RUNTIME pRunTm;
HFONT fontDef;
if (!_LOCHEAP)
_LOCHEAP = HeapCreate(0, 0, 0); // 创建本地堆句柄
fontDef = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
/// 设置默认的GDI对象
pGdi = HeapAlloc(_LOCHEAP, HEAP_ZERO_MEMORY, sizeof(CLK_GDIOBJ));
GetObject(fontDef, sizeof(LOGFONT), &pGdi->fontDate);
GetObject(fontDef, sizeof(LOGFONT), &pGdi->fontClockNumber);
pGdi->brushBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
pGdi->brushClockBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
pGdi->brushDigitalDark = CreateSolidBrush(RGB(0xEE, 0xEE, 0xEE));
pGdi->brushDigitalLight = CreateSolidBrush(RGB(0xFF, 0, 0));
pGdi->penBorder = CreatePen(PS_SOLID, 1, RGB(0x90, 0xC4, 0xE8));
pGdi->penClockArrow = (HPEN)GetStockObject(BLACK_PEN);
pGdi->penClockBorder = (HPEN)GetStockObject(BLACK_PEN);
pGdi->penDigitalBorder = (HPEN)GetStockObject(WHITE_PEN);
SetWindowLongPtr(hCtrl, CLKP_GDIOBJ, (LONG_PTR)pGdi); // 存储GDI对象结构体指针
/// 设置默认的运行时状态
pRunTm = HeapAlloc(_LOCHEAP, HEAP_ZERO_MEMORY, sizeof(CLK_RUNTIME));
pRunTm->isDigitalSecondDark = FALSE;
GetLocalTime(&pRunTm->stimNow);
SetWindowLongPtr(hCtrl, CLKP_RUNTIME, (LONG_PTR)pRunTm); // 存储运行时状态结构体指针
SendMessage(hCtrl, WM_START, 0, 0); // 发送启动消息
return 0;
} 可以看到,上述代码使用SetWindowLongPtr函数,在0(CLKP_GDIOBJ)位置存储了CLK_GDIOBJ结构体的指针,在4(CLKP_RUNTIME)位置存储了CLK_RUNTIME结构体的指针,这样就相当于我们扩展了HWND句柄,在其中存储了我们所需的数据。/// <summary>
/// 窗口销毁消息
/// </summary>
static
void _OnDestory(HWND hCtrl)
{
LPCLK_GDIOBJ pGdi;
LPCLK_RUNTIME pRunTm;
pGdi = (LPCLK_GDIOBJ)GetWindowLongPtr(hCtrl, CLKP_GDIOBJ); // 获取GDI对象结构体
if (pGdi)
{
/// 删除所有的GDI对象
DeleteObject(pGdi->brushBackground);
DeleteObject(pGdi->brushClockBackground);
DeleteObject(pGdi->brushDigitalDark);
DeleteObject(pGdi->brushDigitalLight);
DeleteObject(pGdi->penBorder);
DeleteObject(pGdi->penClockArrow);
DeleteObject(pGdi->penClockBorder);
HeapFree(_LOCHEAP, 0, pGdi); // 从内存中删除结构体
}
pRunTm = (LPCLK_RUNTIME)GetWindowLongPtr(hCtrl, CLKP_RUNTIME); // 获取运行时状态结构体
if (pRunTm)
{
KillTimer(hCtrl, pRunTm->timSecond); // 停止定时器
HeapFree(_LOCHEAP, 0, pRunTm); // 从内存中删除结构体
}
} 可以看到,上述代码使用GetWindowLongPtr函数,在0(CLKP_GDIOBJ)位置获取了CLK_GDIOBJ结构体的指针,在4(CLKP_RUNTIME)位置获取了CLK_RUNTIME结构体的指针,这样就取到了我们之前存储的数据。关于WNDCLASSEX结构体中cbWndExtra成员的作用,布布扣,bubuko.com
关于WNDCLASSEX结构体中cbWndExtra成员的作用
原文:http://blog.csdn.net/mousebaby808/article/details/20299571