線程內也有自己的消息循環,並且在線程中創建的窗口也是通過消息循環來接受消息的。通過窗口開啟定時器,這個定時器就是屬於線程的定時器。
頭文件:
#pragma once #define WM_CHILDTHREAD_TIMERID1 (1001) class CTestDemo { public: CTestDemo(void); ~CTestDemo(void); void StartThread(); void CloseThread(); void StartTreadTimer(int iTimerID = WM_CHILDTHREAD_TIMERID1,int iDurationMs = 1000); //開啟線程定時器,定時器id,定時器間隔 private: static DWORD WINAPI WorkThreadFunc(LPVOID lpParam); static LRESULT CALLBACK WorkWindowMessage(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam); //處理線程中類的消息 void OnThreadTimerCheck(int iTimerID); static HWND TfxWorkWindow(const char* asz_name, WNDPROC WndProc, const char* asz_wnd_name = NULL ); private: DWORD m_dwWorkThread; HANDLE m_hWorkThread; HANDLE m_hEvent; HANDLE m_hExit; };
CPP文件:
#include "StdAfx.h" #include "TestDemo.h" #define WM_CHILDTHREAD_CLOSETHREAD (WM_USER + 66) //關閉線程 #define WM_CHILDTHREAD_STARTTIMER (WM_USER + 67) //開啟線程定時器 CTestDemo::CTestDemo(void) { m_hWorkThread = NULL; m_hEvent = NULL; m_hExit = NULL; m_dwWorkThread = 0; } CTestDemo::~CTestDemo(void) { CloseThread(); } LRESULT CALLBACK CTestDemo::WorkWindowMessage(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam) { CTestDemo* pTestDemo = (CTestDemo*)GetProp(hWnd,"CTestDemo"); if(pTestDemo) { switch(message) { case WM_TIMER: pTestDemo->OnThreadTimerCheck(wParam); break; } } return ::DefWindowProc(hWnd,message,wParam,lParam); } DWORD WINAPI CTestDemo::WorkThreadFunc(LPVOID lpParam) { CTestDemo* pTestDeom = (CTestDemo*)lpParam; if(NULL == pTestDeom) { return 1; } HWND hWorkWnd = TfxWorkWindow(_T("WorkThreadWindow"),CTestDemo::WorkWindowMessage); SetProp(hWorkWnd,"CTestDemo",pTestDeom);
MSG msg={0};
::PeekMessage(&msg,0,0,0,PM_NOREMOVE); //創建消息隊列
SetEvent(pTestDeom->m_hEvent); bool bThreadRunning = true; while (bThreadRunning) { if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { switch (msg.message) { case WM_CHILDTHREAD_CLOSETHREAD: bThreadRunning = false; break; case WM_CHILDTHREAD_STARTTIMER: { ::KillTimer(hWorkWnd,msg.wParam); ::SetTimer(hWorkWnd,msg.wParam,msg.lParam,NULL); } break; default: { TranslateMessage(&msg); DispatchMessage(&msg); } break; } } } if(hWorkWnd) DestroyWindow(hWorkWnd); SetEvent(pTestDeom->m_hExit); return 0; } HWND CTestDemo::TfxWorkWindow(const char* asz_name, WNDPROC WndProc, const char* asz_wnd_name) { HWND hWnd=NULL; WNDCLASSEX wcex={0}; //獲得當前應用程序的句柄 HINSTANCE hInstance = GetModuleHandle(NULL); if ( hInstance == NULL ) return NULL; wcex.cbSize = sizeof(WNDCLASSEX); //設置回調函數 wcex.lpfnWndProc = (WNDPROC)WndProc; wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); wcex.lpszClassName = asz_name; WNDCLASS wndclass={0}; if ( GetClassInfo(hInstance, asz_name, &wndclass) == NULL ) if ( RegisterClassEx(&wcex) == NULL ) return (NULL); if ( ( asz_wnd_name == NULL ) || ( strcmp(asz_wnd_name, "" ) == 0 ) ) hWnd = CreateWindow(asz_name, "", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); else hWnd = CreateWindow(asz_name, asz_wnd_name, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); return hWnd; } void CTestDemo::StartThread() { if(NULL == m_hExit) { m_hExit = CreateEvent(NULL, FALSE, FALSE, ""); } if(NULL == m_hEvent) { m_hEvent = CreateEvent(NULL, FALSE, FALSE, ""); } if(NULL == m_hWorkThread) { m_hWorkThread = ::CreateThread(NULL,0,CTestDemo::WorkThreadFunc,(LPVOID)this,0,&m_dwWorkThread); WaitForSingleObject(m_hEvent,5000); } } void CTestDemo::CloseThread() { if(m_hWorkThread && m_dwWorkThread) { ::PostThreadMessage(m_dwWorkThread,WM_CHILDTHREAD_CLOSETHREAD,0,0); ::CloseHandle(m_hWorkThread); m_hWorkThread = NULL; m_dwWorkThread = 0; } WaitForSingleObject(m_hExit,INFINITE); if(m_hEvent) { ::CloseHandle(m_hEvent); m_hEvent = NULL; } if(m_hExit) { ::CloseHandle(m_hExit); m_hExit = NULL; } } void CTestDemo::StartTreadTimer(int iTimerID,int iDurationMs) { if(m_hWorkThread && m_dwWorkThread) { ::PostThreadMessage(m_dwWorkThread,WM_CHILDTHREAD_STARTTIMER,iTimerID,iDurationMs); } } void CTestDemo::OnThreadTimerCheck(int iTimerID) { switch(iTimerID) { case WM_CHILDTHREAD_TIMERID1: { } break; } }