SHostWnd¶
Warning
The current page still doesn't have a translation for this language.
You can read it through google translate.
概述¶
SOUI 宿主窗口(SHostWnd)是 SOUI 框架中一个核心组件,它作为 DirectUI 系统与 Windows 原生窗口系统的桥梁,实现了:
- 托管 DirectUI 控件树
- 处理 Windows 消息
- 管理渲染过程
- 提供事件机制
宿主窗口层次¶
graph TD
A[CSimpleWnd] --> B[SHostWnd]
B --> C[DirectUI Root]
C --> D[DirectUI Controls]
核心功能¶
1. 窗口创建与销毁¶
class SHostWnd : public CSimpleWnd
{
public:
// 创建窗口
BOOL Create(LPCTSTR lpszResName, int nPosX = CW_USEDEFAULT, int nPosY = CW_USEDEFAULT,
int nWidth = CW_USEDEFAULT, int nHeight = CW_USEDEFAULT);
// 从资源 ID 创建窗口
BOOL CreateEx(HWND hWndParent, DWORD dwStyle = 0, DWORD dwExStyle = 0,
int nID = 0);
};
使用示例¶
class CMainDlg : public SHostWnd
{
public:
CMainDlg() : SHostWnd(_T("LAYOUT:XML_MAINWND")) {}
void OnInit() {
// 初始化窗口
Create(_T("main_window"),
CW_USEDEFAULT, CW_USEDEFAULT,
800, 600);
}
};
2. 消息处理¶
SHostWnd 提供了完整的 Windows 消息处理机制:
// 消息映射示例
BOOL OnCreate(LPCREATESTRUCT lpCreateStruct);
void OnDestroy();
void OnPaint(HDC dc);
void OnSize(UINT nType, CSize size);
LRESULT OnMouseEvent(UINT uMsg, WPARAM wParam, LPARAM lParam);
消息转发机制¶
graph LR
A[Windows Message] --> B[SHostWnd]
B --> C[Message Map]
C --> D[Event System]
D --> E[DirectUI Controls]
3. 渲染管理¶
宿主窗口负责管理整个 DirectUI 树的渲染过程:
void OnPaint(HDC dc) {
SPainter painter;
BeforePaint(dc, painter);
// 渲染 DirectUI 控件树
OnRedraw(dc, NULL);
AfterPaint(dc, painter);
}
4. 布局管理¶
// 布局更新
void UpdateLayout();
// 调整窗口大小
void UpdateAutoSizeCount();
// 获取客户区大小
CRect GetClientRect() const;
高级特性¶
1. 动画支持¶
// 动画控制
class SOUI_EXP IAnimation {
virtual void Start(IAnimationListener* pListener) = 0;
virtual void Stop() = 0;
};
2. 透明窗口¶
// 设置窗口透明度
void SetWindowAlpha(BYTE byAlpha);
// 开启分层窗口
BOOL EnableLayeredWindow(BOOL bEnable);
3. 事件系统¶
// 事件映射
EVENT_MAP_BEGIN()
EVENT_ID_COMMAND(btnID, OnBtnClick)
EVENT_NAME_HANDLER("edit", EventRENotify::EventID, OnEditNotify)
EVENT_MAP_END()
最佳实践¶
1. 窗口创建¶
class CCustomWindow : public SHostWnd
{
public:
CCustomWindow(LPCTSTR pszResName = NULL)
: SHostWnd(pszResName)
{
m_bLayeredWindow = TRUE; // 启用分层窗口
}
protected:
// 处理窗口初始化
void OnInit() {
// 加载布局资源
SetXMLFromRes(L"LAYOUT:XML_MAINWND");
// 设置窗口属性
SetWindowLongPtr(GWL_STYLE,
GetWindowLongPtr(GWL_STYLE) | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
}
// 处理窗口销毁
void OnFinalMessage(HWND hWnd) {
__super::OnFinalMessage(hWnd);
delete this;
}
// 注册消息处理
BEGIN_MSG_MAP_EX(CCustomWindow)
MSG_WM_CREATE(OnCreate)
MSG_WM_DESTROY(OnDestroy)
MSG_WM_SIZE(OnSize)
CHAIN_MSG_MAP(SHostWnd)
REFLECT_NOTIFICATIONS_EX()
END_MSG_MAP()
};
2. 窗口优化¶
// 缓存管理
void EnableCache(BOOL bEnable) {
GetRoot()->EnableCache(bEnable);
}
// 渲染优化
void OptimizeDrawing() {
// 开启双缓存
ModifyStyle(0, WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
// 设置更新区域
CRect rcClient;
GetClientRect(&rcClient);
InvalidateRect(rcClient);
}
3. 事件处理¶
// 事件处理示例
class CMainWindow : public SHostWnd
{
protected:
// 按钮点击事件
void OnBtnClick(EventArgs *e) {
EventCmd *eCmd = sobj_cast<EventCmd>(e);
if(eCmd) {
// 处理命令事件
}
}
// 编辑框通知
void OnEditNotify(EventArgs *e) {
EventRENotify *eNotify = sobj_cast<EventRENotify>(e);
if(eNotify) {
// 处理编辑框通知
}
}
// 注册事件处理
EVENT_MAP_BEGIN()
EVENT_NAME_COMMAND(L"btnOK", OnBtnClick)
EVENT_NAME_HANDLER(L"editContent", EventRENotify::EventID, OnEditNotify)
EVENT_MAP_END()
};
注意事项¶
- 窗口生命周期
- 正确处理窗口创建和销毁
- 管理子窗口资源
-
清理事件订阅
-
消息处理
- 避免阻塞消息循环
- 合理使用消息过滤
-
注意消息优先级
-
性能优化
- 合理使用缓存机制
- 控制重绘区域
- 优化事件处理
调试技巧¶
// 调试辅助类
class CWindowDebugger {
public:
static void DumpWindowInfo(SHostWnd* pWnd) {
STRACE(_T("Window Handle: 0x%08x"), pWnd->m_hWnd);
STRACE(_T("Window Style: 0x%08x"), GetWindowLong(pWnd->m_hWnd, GWL_STYLE));
STRACE(_T("Window Rect: (%d,%d,%d,%d)"),
pWnd->m_rcWindow.left, pWnd->m_rcWindow.top,
pWnd->m_rcWindow.right, pWnd->m_rcWindow.bottom);
}
};
示例代码¶
完整的窗口实现示例¶
class CMainWindow : public SHostWnd
{
public:
CMainWindow() : SHostWnd(_T("LAYOUT:XML_MAINWND"))
{
m_bLayeredWindow = TRUE;
}
~CMainWindow() {}
protected:
// 窗口初始化
BOOL OnInitDialog(HWND wndFocus, LPARAM lInitParam) {
// 初始化控件
m_pTabMain = FindChildByName2<STabCtrl>(L"tab_main");
m_pEditInput = FindChildByName2<SEdit>(L"edit_input");
// 注册事件处理
if(m_pTabMain) {
m_pTabMain->GetEventSet()->subscribeEvent(
EVT_TAB_SELCHANGED,
Subscriber(&CMainWindow::OnTabChanged, this));
}
return TRUE;
}
// 事件处理
bool OnTabChanged(EventArgs *e) {
EventTabSelChanged *ev = sobj_cast<EventTabSelChanged>(e);
if(ev) {
// 处理标签切换
UpdateLayout();
return true;
}
return false;
}
// 消息映射
BEGIN_MSG_MAP_EX(CMainWindow)
MSG_WM_INITDIALOG(OnInitDialog)
MSG_WM_CLOSE(OnClose)
CHAIN_MSG_MAP(SHostWnd)
REFLECT_NOTIFICATIONS_EX()
END_MSG_MAP()
// 事件映射
EVENT_MAP_BEGIN()
EVENT_NAME_COMMAND(L"btn_ok", OnOKClick)
EVENT_NAME_COMMAND(L"btn_cancel", OnCancelClick)
EVENT_MAP_END()
private:
STabCtrl* m_pTabMain;
SEdit* m_pEditInput;
};