主對話框同時啟動多個攝像頭,每個攝像頭專屬執行緒抓取影像並即時顯示於對應的 Picture Control。
// 參數結構
struct CameraParam {
int camIndex; // 或 CString rtspUrl
UINT picCtrlId; // 目標 Picture Control ID
HWND hMainWnd; // 主視窗接收訊息
volatile bool* pStop; // 停止旗標指標
HANDLE hEventStop; // 事件同步
};
// 執行緒函數
UINT __cdecl CameraThread(LPVOID pParam) {
CameraParam* p = (CameraParam*)pParam;
cv::VideoCapture cap(p->camIndex);
if (!cap.isOpened()) { PostMessage(p->hMainWnd, WM_CAM_ERROR, p->picCtrlId, 0); return 1; }
cv::Mat frame, bgr;
while (!(*p->pStop)) {
if (!cap.read(frame)) break;
cv::cvtColor(frame, bgr, cv::COLOR_BGR2RGB); // Picture Control 需 RGB
// 建立 HBITMAP (需深拷貝,因 frame 會被覆寫)
HBITMAP hBmp = CreateBitmap(bgr.cols, bgr.rows, 1, 24, bgr.data);
// 發送至主視窗,WPARAM=picCtrlId, LPARAM=hBmp
PostMessage(p->hMainWnd, WM_CAM_FRAME, p->picCtrlId, (LPARAM)hBmp);
Sleep(30); // 控制幀率 ~30fps
}
cap.release();
SetEvent(p->hEventStop);
return 0;
}
// 主視窗訊息處理
LRESULT CMainDlg::OnCamFrame(WPARAM wParam, LPARAM lParam) {
UINT ctrlId = (UINT)wParam;
HBITMAP hBmp = (HBITMAP)lParam;
CStatic* pPic = (CStatic*)GetDlgItem(ctrlId);
if (pPic) {
HBITMAP hOld = pPic->SetBitmap(hBmp);
if (hOld) DeleteObject(hOld); // 刪除舊位圖
}
return 0;
}
// 啟動多攝像頭
void CMainDlg::StartCameras() {
for (int i = 0; i < CAM_COUNT; ++i) {
CameraParam* p = new CameraParam{i, IDC_PIC_CAM1 + i, m_hWnd, &m_bStop[i], CreateEvent(NULL, TRUE, FALSE, NULL)};
m_threads[i] = AfxBeginThread(CameraThread, p, THREAD_PRIORITY_NORMAL, 0, CREATE_SUSPENDED);
m_threads[i]->m_bAutoDelete = FALSE;
m_threads[i]->ResumeThread();
}
}