首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

VC++ 對話框右上角關閉按鈕處理:重寫 OnCancel/OnClose、攝像頭資源釋放、WM_CLOSE 流程詳解

     編輯:程式設計綜合問答

消息流程圖

用戶點擊 × (右上角)
    │
    ▼
WM_SYSCOMMAND (SC_CLOSE) → DefWindowProc → PostMessage(WM_CLOSE)
    │
    ▼
WM_CLOSE (OnClose) → 可攔截、可銷毀視窗
    │
    ▼
DestroyWindow → WM_DESTROY → PostQuitMessage → 消息循環結束

正確重寫點:`OnCancel()` 或 `OnClose()`

方案一:重寫 `OnCancel()` (模態/非模態通用,最簡單)

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
}

方案二:重寫 `OnClose()` (需處理 `WM_CLOSE` 細節)

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`

常見誤區:`WM_MOUSEMOVE` (0x0100) ≠ 點擊關閉

  • `msg.message == 160 (0xA0)` 是 `WM_NCMOUSEMOVE` (非客戶區滑鼠移動)
  • **滑鼠懸停在 × 上會連續產生此消息**,非點擊
  • 點擊 × 產生 `WM_NCLBUTTONDOWN` (0xA1) + `WM_SYSCOMMAND` (SC_CLOSE)

攝像頭資源釋放檢查清單

// 必須按順序釋放
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` 處理關閉邏輯,那是滑鼠移動而非點擊。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved