長時間運算 (如大量資料匯入、複雜演算法) 時,UI 執行緒被阻塞,使用者無法透過一般訊息迴路接收按鍵。需在計算迴圈中主動輪詢訊息佇列,偵測 Esc 鍵終止作業。
GetMessage/PeekMessage 取出處理
void CMyClass::LongRunningTask()
{
MSG msg;
for (int i = 0; i < TotalSteps; ++i) {
// 執行單一計算步驟
DoOneStep(i);
// 每 N 步或固定時間輪詢一次,避免過度消耗 CPU
if (i % 100 == 0) {
// 檢查鍵盤訊息範圍 WM_KEYFIRST ~ WM_KEYLAST
if (::PeekMessage(&msg, m_hWnd, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)) {
if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE) {
// 使用者按下 ESC,中斷作業
AfxMessageBox(_T("作業已由使用者取消"));
break;
}
// 非 ESC 鍵可選擇 DispatchMessage 讓系統處理
::DispatchMessage(&msg);
}
}
}
}
| 參數 | 值 | 說明 |
|---|---|---|
| hwnd | m_hWnd | 僅檢查屬於本視窗的訊息 |
| wMsgFilterMin | WM_KEYFIRST (0x0100) | 鍵盤訊息範圍起始 |
| wMsgFilterMax | WM_KEYLAST (0x0109) | 鍵盤訊息範圍結束 |
| wRemoveMsg | PM_REMOVE | 取出後從佇列移除;若用 PM_NOREMOVE 則僅檢查不移除 |
PumpMessage() 或完整訊息迴圈PostMessage/Event 通訊,架構更乾淨kbhit() 行為包含 MFC Dialog 專案示範:進度條模擬長時間作業、ESC 取消、訊息泵處理 WM_PAINT 保持介面不凍結。