現象
對話框 A 中創建模態/無模對話框 B,移動 A 時 B 不跟隨移動。
原因
B 是**獨立頂層窗口** (WS_POPUP + WS_CAPTION),不屬於 A 的子窗口鏈,系統不自動移動它。
解決:SetParent 設置父子關係
// 在對話框 A 的 OnInitDialog 或創建 B 後調用
::SetParent(hWndB, hWndA); // hWndA 為 A 的 m_hWnd
// 若 B 是模態對話框 (DoModal),需在創建前修改模板或用無模對話框
// 推薦:B 定義為 Child 樣式 (WS_CHILD | WS_VISIBLE | DS_CONTROL)
// 資源編輯器中:Style → Child, Border → None
// 代碼創建:
CDialogEx dlgB;
dlgB.Create(IDD_DIALOG_B, this); // this 指針自動作為 pParentWnd
// 或
dlgB.Create(IDD_DIALOG_B, this->GetSafeHwnd());
關鍵樣式組合
| 樣式 | 含義 |
| WS_CHILD | 子窗口,隨父窗口移動/裁剪/銷毀 |
| WS_VISIBLE | 初始可見 |
| DS_CONTROL | 對話框模板標誌,使其表現為控件 (Tab 順序、鍵盤導航正常) |
| 無 WS_CAPTION / WS_SYSMENU | 去掉標題欄/系統菜單,避免雙重標題 |
完整示例 (MFC)
// A 對話框頭文件
class CDlgA : public CDialogEx {
CDlgB m_dlgB; // 成員變量保證生命周期
// ...
};
// A.cpp OnInitDialog
BOOL CDlgA::OnInitDialog() {
CDialogEx::OnInitDialog();
m_dlgB.Create(IDD_DLG_B, this); // 關鍵:this 作為父窗口
// 定位在某 Static 控件位置
CRect rect;
GetDlgItem(IDC_STATIC_PLACEHOLDER)->GetWindowRect(&rect);
ScreenToClient(&rect);
m_dlgB.SetWindowPos(NULL, rect.left, rect.top, 0, 0, SWP_NOSIZE | SWP_NOZORDER);
m_dlgB.ShowWindow(SW_SHOW);
return TRUE;
}
// 移動同步自動生效,無需額外代碼
注意事項
- **不要對模態對話框 (DoModal) 使用 SetParent**,會導致消息循環死鎖。
- 若需模態行為,可在 A 中禁用輸入
EnableWindow(FALSE),B 關閉時恢復。
- 跨線程 UI 禁止,所有窗口必須在同一 UI 線程創建。
- 上一篇文章: 瀏覽器將 POST 表單改為 GET:服務端決定成敗
- 下一篇文章: Java 登錄加密:MD5、SHA、加鹽與現代最佳實踐
Copyright ©
程式碼之家 All Rights Reserved