线程内也有自己的消息循环,并且在线程中创建的窗口也是通过消息循环来接受消息的。通过窗口开启定时器,这个定时器就是属于线程的定时器。
头文件:
#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; } }