用戶點擊 × (右上角)
│
▼
WM_SYSCOMMAND (SC_CLOSE) → DefWindowProc → PostMessage(WM_CLOSE)
│
▼
WM_CLOSE (OnClose) → 可攔截、可銷毀視窗
│
▼
DestroyWindow → WM_DESTROY → PostQuitMessage → 消息循環結束
void CMyDialog::OnCancel() {
// 1. 確認對話框
if (AfxMessageBox(_T("確定要退出並關閉攝像頭嗎?"), MB_YESNO | MB_ICONQUESTION) != IDYES)
return; // 用戶取消,不關閉
// 2. 釋放攝像頭資源 (必須在 DestroyWindow 前)
if (m_hCamera) {
Camera_Stop(m_hCamera);
Camera_Close(m_hCamera);
m_hCamera = NULL;
}
// 3. 釋放其他資源 (線程、句柄、GDI...)
// 4. 調用基類實際銷毀視窗
CDialogEx::OnCancel(); // 內部調用 EndDialog(IDCANCEL) / DestroyWindow
}
void CMyDialog::OnClose() {
// 同樣邏輯...
// 最後必須調用基類
CDialogEx::OnClose(); // 內部調用 DestroyWindow()
}
// 若為非模態對話框 (Create + ShowWindow),OnClose 基類會 DestroyWindow
// 若為模態 (DoModal),基類 OnClose 會 EndDialog(0)
| 場景 | 推薦重寫 | 基類行為 |
|---|---|---|
| 模態對話框 (`DoModal`) | `OnCancel` / `OnOK` | `EndDialog` |
| 非模態對話框 (`Create`) | `OnClose` | `DestroyWindow` |
| 主框架視窗 (`CFrameWnd`) | `OnClose` | `DestroyWindow` → `PostQuitMessage` |
// 必須按順序釋放
1. 停止預覽/錄像: Camera_StopPreview / Camera_StopRecord
2. 關閉設備句柄: Camera_Close(hCam)
3. 釋放 SDK 庫: Camera_Cleanup() (若有)
4. 等待工作線程結束: WaitForSingleObject(hThread, 5000)
5. 關閉線程句柄: CloseHandle(hThread)
6. 釋放 GDI: DeleteObject(hBitmap), DeleteDC(hMemDC)
**重寫 `OnCancel()` (模態) 或 `OnClose()` (非模態/框架)**,在其中**先彈確認框、再釋放攝像頭/線程/GDI 資源、最後調用基類**。切勿在 `WM_NCMOUSEMOVE` 處理關閉邏輯,那是滑鼠移動而非點擊。