SOUI消息过滤机制¶
本文介绍SOUI框架中的消息过滤机制,这类似于MFC中的PreTranslateMessage
功能。
消息过滤概述¶
消息过滤机制允许在消息到达目标窗口之前对其进行预处理或拦截,常用于: - 实现工具提示(Tooltip)控制 - 快捷键处理 - 特殊消息拦截 - 全局消息监控
实现消息过滤器¶
1. 定义消息过滤器接口¶
struct IMessageFilter
{
virtual BOOL PreTranslateMessage(MSG* pMsg) = 0;
};
2. 实现消息过滤器¶
class SMyMessageFilter : public IMessageFilter
{
public:
// 实现PreTranslateMessage接口
virtual BOOL PreTranslateMessage(MSG* pMsg) override
{
// 返回TRUE表示消息已被处理
// 返回FALSE表示继续传递消息
switch(pMsg->message)
{
case WM_KEYDOWN:
// 处理按键消息
return TRUE;
}
return FALSE;
}
};
3. 注册消息过滤器¶
在SOUI中需要将消息过滤器注册到MessageLoop:
// 在SHostWnd中
SMessageLoop* pLoop = GetMsgLoop();
pLoop->AddMessageFilter(pMessageFilter);
// 在SWindow中
SMessageLoop* pLoop = GetContainer()->GetMsgLoop();
pLoop->AddMessageFilter(pMessageFilter);
4. 注销消息过滤器¶
pLoop->RemoveMessageFilter(pMessageFilter);
使用场景示例¶
1. 工具提示控制¶
class STooltipFilter : public IMessageFilter
{
public:
virtual BOOL PreTranslateMessage(MSG* pMsg) override
{
switch(pMsg->message)
{
case WM_MOUSEMOVE:
// 控制工具提示显示
UpdateTooltip(pMsg->pt);
return FALSE; // 继续传递消息
case WM_MOUSEWHEEL:
// 隐藏工具提示
HideTooltip();
return FALSE;
}
return FALSE;
}
private:
void UpdateTooltip(POINT pt)
{
// 实现工具提示更新逻辑
}
void HideTooltip()
{
// 实现工具提示隐藏逻辑
}
};
2. 快捷键处理¶
class SHotkeyFilter : public IMessageFilter
{
public:
virtual BOOL PreTranslateMessage(MSG* pMsg) override
{
if(pMsg->message == WM_KEYDOWN)
{
// 检查Ctrl+C快捷键
if(pMsg->wParam == 'C' && (GetKeyState(VK_CONTROL) & 0x8000))
{
OnCopy();
return TRUE; // 消息已处理
}
}
return FALSE;
}
private:
void OnCopy()
{
// 实现复制功能
}
};
3. 下拉窗口示例¶
class SDropDownWnd : public SHostWnd, public IMessageFilter
{
public:
SDropDownWnd()
{
// 构造函数中注册消息过滤器
GetMsgLoop()->AddMessageFilter(this);
}
~SDropDownWnd()
{
// 析构函数中注销消息过滤器
GetMsgLoop()->RemoveMessageFilter(this);
}
// 实现消息过滤
virtual BOOL PreTranslateMessage(MSG* pMsg) override
{
// 处理鼠标消息
if(pMsg->message >= WM_MOUSEFIRST && pMsg->message <= WM_MOUSELAST)
{
// 检查鼠标是否在窗口区域内
POINT pt = {GET_X_LPARAM(pMsg->lParam), GET_Y_LPARAM(pMsg->lParam)};
if(!IsMouseInWindow(pt))
{
OnMouseLeave();
return TRUE;
}
}
return FALSE;
}
protected:
bool IsMouseInWindow(POINT pt)
{
CRect rcWnd;
GetWindowRect(&rcWnd);
return rcWnd.PtInRect(pt);
}
void OnMouseLeave()
{
// 处理鼠标离开事件
}
};
最佳实践¶
1. 合理使用¶
- 只过滤必要的消息
- 避免过多的消息过滤器
- 及时注销不需要的过滤器
2. 性能考虑¶
class SOptimizedFilter : public IMessageFilter
{
public:
virtual BOOL PreTranslateMessage(MSG* pMsg) override
{
// 快速检查消息类型
if(pMsg->message < WM_MOUSEFIRST || pMsg->message > WM_MOUSELAST)
return FALSE;
// 只处理感兴趣的消息
// ...
return FALSE;
}
};
3. 生命周期管理¶
class SMessageFilterManager
{
public:
void AddFilter(IMessageFilter* pFilter)
{
if(!m_filters.Find(pFilter))
{
m_pLoop->AddMessageFilter(pFilter);
m_filters.Add(pFilter);
}
}
void RemoveFilter(IMessageFilter* pFilter)
{
if(m_filters.Find(pFilter))
{
m_pLoop->RemoveMessageFilter(pFilter);
m_filters.Remove(pFilter);
}
}
private:
SArray<IMessageFilter*> m_filters;
SMessageLoop* m_pLoop;
};
调试技巧¶
-
消息跟踪
virtual BOOL PreTranslateMessage(MSG* pMsg) override { STRACE(_T("Message: %d, wParam: %d, lParam: %d"), pMsg->message, pMsg->wParam, pMsg->lParam); return FALSE; }
-
性能监控
virtual BOOL PreTranslateMessage(MSG* pMsg) override { DWORD dwStart = GetTickCount(); BOOL bRet = ProcessMessage(pMsg); DWORD dwEnd = GetTickCount(); if(dwEnd - dwStart > 100) { // 记录性能问题 STRACE(_T("Message processing too slow: %dms"), dwEnd - dwStart); } return bRet; }
注意事项¶
- 消息处理
- 返回TRUE表示消息已处理
- 返回FALSE继续传递消息
-
不要无故拦截消息
-
生命周期
- 构造时注册
- 析构时注销
-
避免内存泄漏
-
性能影响
- 减少不必要的处理
- 优化处理逻辑
- 监控处理时间