SOUI中的定时器¶
定时器是GUI编程中实现动画效果的重要工具。本文介绍SOUI框架中定时器的使用方法和注意事项。
定时器类型¶
SOUI框架提供了三种类型的定时器:
- SWND定时器(SWindow::SetTimer)
- 扩展定时器(SWindow::SetTimer2)
- 宿主窗口定时器(::SetTimer/CSimpleWnd::SetTimer)
SWND定时器¶
定时器ID结构¶
SOUI使用32位定时器ID,按位划分:
class SOUI_EXP STimerID
{
public:
DWORD Swnd:24; // 窗口句柄,最大支持16777215个窗口
DWORD uTimerID:7; // 定时器ID,支持0-127
DWORD bSwndTimer:1; // 标志位,1表示SWND定时器
};
创建定时器¶
// 创建一个ID为0-127的定时器
BOOL SWindow::SetTimer(char id, UINT uElapse);
销毁定时器¶
// 删除指定ID的定时器
void SWindow::KillTimer(char id);
响应定时器消息¶
// 在消息映射表中使用MSG_WM_TIMER_EX
SOUI_MSG_MAP_BEGIN()
MSG_WM_TIMER_EX(OnTimer) // 定时器消息
SOUI_MSG_MAP_END()
// 处理函数
void OnTimer(char cTimerID)
{
// 处理定时器消息
}
扩展定时器(SetTimer2)¶
当需要使用32位定时器ID时,可以使用SetTimer2:
创建定时器¶
// 创建一个支持完整32位ID的定时器
BOOL SWindow::SetTimer2(UINT_PTR id, UINT uElapse);
销毁定时器¶
// 删除SetTimer2创建的定时器
void SWindow::KillTimer2(UINT_PTR id);
响应定时器消息¶
// 在消息映射表中使用MSG_WM_TIMER2
SOUI_MSG_MAP_BEGIN()
MSG_WM_TIMER2(OnTimer2) // Timer2消息
SOUI_MSG_MAP_END()
// 处理函数
void OnTimer2(UINT_PTR id)
{
// 处理Timer2消息
}
宿主窗口定时器¶
在应用层可以直接使用Win32定时器:
创建定时器¶
// 使用Win32 API
::SetTimer(hwnd, timerID, interval, NULL);
// 或使用CSimpleWnd类方法
CSimpleWnd::SetTimer(UINT_PTR nIDEvent, UINT nElapse);
响应定时器消息¶
// 在宿主窗口消息映射中
void OnTimer(UINT_PTR idEvent)
{
// 处理自己的定时器
if(idEvent == myTimerID)
{
// 处理定时器逻辑
}
else
{
// 不是自己的定时器,交给基类处理
SetMsgHandled(FALSE);
// 或者调用基类
// SHostWnd::OnTimer(idEvent);
}
}
最佳实践¶
1. 选择合适的定时器类型¶
- 控件开发时优先使用SWND定时器(SetTimer)
- 需要32位ID时使用SetTimer2
- 应用层可以直接使用Win32定时器
2. 定时器ID管理¶
- SWND定时器ID范围:0-127
- SetTimer2支持完整32位ID
- Win32定时器ID最高位必须为0
3. 性能考虑¶
- SetTimer效率最高
- SetTimer2在KillTimer2时效率较低
- 合理设置定时器间隔
4. 注意事项¶
- ID冲突避免
- 不同类型定时器ID要避免冲突
-
同一窗口的定时器ID要唯一
-
资源释放
- 窗口销毁前要清理定时器
-
使用完毕及时销毁定时器
-
消息处理
- 正确使用消息映射宏
- 注意消息传递链
使用示例¶
1. 动画效果实现¶
class SAnimationWindow : public SWindow
{
void OnCreate()
{
// 创建动画定时器
SetTimer(1, 16); // 约60fps
}
void OnTimer(char cTimerID)
{
if(cTimerID == 1)
{
// 更新动画
InvalidateRect(NULL);
}
}
void OnDestroy()
{
// 清理定时器
KillTimer(1);
}
SOUI_MSG_MAP_BEGIN()
MSG_WM_TIMER_EX(OnTimer)
SOUI_MSG_MAP_END()
};
2. 延时操作¶
void SMyWindow::DelayedOperation()
{
// 设置一次性定时器
SetTimer2(100, 1000); // 1秒后执行
}
void SMyWindow::OnTimer2(UINT_PTR id)
{
if(id == 100)
{
// 执行延时操作
KillTimer2(100); // 清理一次性定时器
}
}