SHostDialog¶
Warning
The current page still doesn't have a translation for this language.
You can read it through google translate.
概述¶
SHostDialog 是 SOUI 框架中专门用于创建模态和非模态对话框的类,它继承自 SHostWnd,在保留原有宿主窗口功能的基础上,增加了对话框特有的功能。
架构设计¶
graph TD
A[CSimpleWnd] --> B[SHostWnd]
B --> C[SHostDialog]
C --> D[自定义对话框]
核心特性¶
1. 对话框类型¶
class SOUI_EXP SHostDialog : public SHostWnd
{
public:
// 构造函数
SHostDialog(LPCTSTR pszXmlName = NULL);
// 模态对话框
INT_PTR DoModal(HWND hParent = NULL);
// 非模态对话框
BOOL Create(HWND hParent = NULL);
};
2. 消息处理¶
// 对话框消息处理
class CMyDialog : public SHostDialog
{
protected:
// 初始化处理
BOOL OnInitDialog(HWND wndFocus, LPARAM lInitParam);
// 关闭处理
void OnCancel();
void OnOK();
// 消息映射
BEGIN_MSG_MAP_EX(CMyDialog)
MSG_WM_INITDIALOG(OnInitDialog)
MSG_WM_CLOSE(OnClose)
CHAIN_MSG_MAP(SHostDialog)
REFLECT_NOTIFICATIONS_EX()
END_MSG_MAP()
};
使用指南¶
1. 创建模态对话框¶
// 对话框定义
class CSettingsDialog : public SHostDialog
{
public:
CSettingsDialog()
: SHostDialog(_T("LAYOUT:XML_SETTINGS_DLG"))
{}
protected:
// 初始化对话框
BOOL OnInitDialog(HWND wndFocus, LPARAM lInitParam) {
// 初始化控件
m_pEditName = FindChildByName2<SEdit>(L"edit_name");
m_pCbxType = FindChildByName2<SComboBox>(L"cbx_type");
return TRUE;
}
// 确定按钮处理
void OnOK() {
if (m_pEditName && m_pEditName->GetWindowTextLength() == 0) {
SMessageBox(m_hWnd, _T("请输入名称"), _T("提示"), MB_OK | MB_ICONWARNING);
return;
}
EndDialog(IDOK);
}
// 取消按钮处理
void OnCancel() {
EndDialog(IDCANCEL);
}
private:
SEdit* m_pEditName;
SComboBox* m_pCbxType;
};
// 使用示例
void ShowSettingsDialog() {
CSettingsDialog dlg;
if (IDOK == dlg.DoModal()) {
// 处理确定操作
}
}
2. 创建非模态对话框¶
class CInfoDialog : public SHostDialog
{
public:
CInfoDialog()
: SHostDialog(_T("LAYOUT:XML_INFO_DLG"))
{}
// 创建非模态对话框
BOOL CreateDialog(HWND hParent) {
return Create(hParent);
}
protected:
void OnClose() {
DestroyWindow();
}
BEGIN_MSG_MAP_EX(CInfoDialog)
MSG_WM_CLOSE(OnClose)
CHAIN_MSG_MAP(SHostDialog)
END_MSG_MAP()
};
// 使用示例
CInfoDialog* ShowInfoDialog(HWND hParent) {
CInfoDialog* pDlg = new CInfoDialog();
if (pDlg->CreateDialog(hParent)) {
return pDlg;
}
delete pDlg;
return NULL;
}
3. 对话框布局¶
<SOUI title="设置对话框"
width="400"
height="300"
appwin="0"
resizable="0"
translucent="1">
<root skin="_skin.sys.wnd.bkgnd">
<caption pos="0,0,-0,30">
<text pos="10,8">设置</text>
<imgbtn id="2"
skin="_skin.sys.btn.close"
pos="-45,0"
tip="关闭"/>
</caption>
<window pos="10,40,-10,-50">
<!-- 对话框内容 -->
<text pos="10,10">名称:</text>
<edit name="edit_name"
pos="100,10,-10,35"/>
<text pos="10,50">类型:</text>
<combobox name="cbx_type"
pos="100,50,-10,75"/>
</window>
<!-- 按钮区域 -->
<window pos="10,-40,-10,-10">
<button name="btn_ok"
pos="-150,-30,-80,0"
class="normalbtn">确定</button>
<button name="btn_cancel"
pos="-70,-30,0,0"
class="normalbtn">取消</button>
</window>
</root>
</SOUI>
高级特性¶
1. 对话框数据交换¶
class CDataDialog : public SHostDialog
{
public:
// 对话框数据结构
struct DialogData {
SStringT strName;
int nType;
BOOL bEnabled;
};
void SetData(const DialogData& data) {
m_data = data;
}
const DialogData& GetData() const {
return m_data;
}
protected:
// 数据到控件
void DataToUI() {
if (m_pEditName)
m_pEditName->SetWindowText(m_data.strName);
if (m_pCbxType)
m_pCbxType->SetCurSel(m_data.nType);
if (m_pChkEnabled)
m_pChkEnabled->SetCheck(m_data.bEnabled);
}
// 控件到数据
void UIToData() {
if (m_pEditName)
m_data.strName = m_pEditName->GetWindowText();
if (m_pCbxType)
m_data.nType = m_pCbxType->GetCurSel();
if (m_pChkEnabled)
m_data.bEnabled = m_pChkEnabled->IsChecked();
}
private:
DialogData m_data;
};
2. 对话框状态管理¶
class CStateDialog : public SHostDialog
{
protected:
// 保存对话框状态
void SaveState() {
SStringT strConfig;
// 保存窗口位置
CRect rcWnd;
GetWindowRect(&rcWnd);
strConfig.Format(_T("pos:%d,%d,%d,%d"),
rcWnd.left, rcWnd.top,
rcWnd.right, rcWnd.bottom);
// 保存选项状态
if (m_pCbxType)
strConfig.AppendFormat(_T(";type:%d"), m_pCbxType->GetCurSel());
// 写入配置
SStringT strApp = _T("DialogState");
WritePrivateProfileString(strApp, _T("MainDlg"),
strConfig, _T("config.ini"));
}
// 恢复对话框状态
void LoadState() {
TCHAR szBuf[MAX_PATH] = {0};
SStringT strApp = _T("DialogState");
GetPrivateProfileString(strApp, _T("MainDlg"),
_T(""), szBuf, MAX_PATH, _T("config.ini"));
SStringT strConfig = szBuf;
// 解析配置...
}
};
最佳实践¶
1. 对话框基类¶
class CBaseDialog : public SHostDialog
{
protected:
// 通用初始化
BOOL OnInitDialog(HWND wndFocus, LPARAM lInitParam) {
// 初始化基础功能
InitControls();
LoadState();
return TRUE;
}
// 通用清理
void OnFinalMessage(HWND hWnd) {
SaveState();
__super::OnFinalMessage(hWnd);
}
// 公共事件处理
bool OnCommonCommand(EventArgs* e) {
EventCmd* eCmd = sobj_cast<EventCmd>(e);
if (!eCmd) return false;
SStringW strName = eCmd->sender->GetName();
if (strName == L"btn_ok")
OnOK();
else if (strName == L"btn_cancel")
OnCancel();
return true;
}
EVENT_MAP_BEGIN()
EVENT_HANDLER(EventCmd::EventID, OnCommonCommand)
EVENT_MAP_END()
};
2. 对话框工厂¶
class CDialogFactory
{
public:
// 创建对话框
static SHostDialog* CreateDialog(const SStringT& strType) {
if (strType == _T("settings"))
return new CSettingsDialog();
else if (strType == _T("info"))
return new CInfoDialog();
return NULL;
}
// 显示模态对话框
static INT_PTR ShowModalDialog(const SStringT& strType,
HWND hParent = NULL) {
SAutoRefPtr<SHostDialog> pDlg(CreateDialog(strType));
if (!pDlg) return IDCANCEL;
return pDlg->DoModal(hParent);
}
};
注意事项¶
- 内存管理
- 非模态对话框需要正确处理内存释放
- 使用智能指针管理对话框对象
-
注意子控件的生命周期
-
状态管理
- 合理保存和恢复对话框状态
- 处理窗口位置和大小变化
-
管理控件数据
-
性能优化
- 避免频繁创建销毁对话框
- 合理使用缓存机制
- 优化数据交换过程
调试技巧¶
// 对话框调试助手
class CDialogDebugger
{
public:
static void TraceDialogInfo(SHostDialog* pDlg) {
STRACE(_T("Dialog[%s] State:"), pDlg->GetWindowText());
// 输出窗口信息
CRect rcWnd;
pDlg->GetWindowRect(&rcWnd);
STRACE(_T("Position: (%d,%d,%d,%d)"),
rcWnd.left, rcWnd.top,
rcWnd.right, rcWnd.bottom);
// 输出控件状态
// ...
}
};