Delphi中使用Win32 API创建内建消息循环的线程函数
1.线程创建 HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, // pointer to thread security attributes DWORD dwStackSize, // initial thread stack size, in bytes LPTHREAD_START_ROUTINE lpStartAddress, // pointer to thread function LPVOID lpParameter, // argument for new thread DWORD dwCreationFlags, // creation flags LPDWORD lpThreadId // pointer to returned thread identifier ); 举例:var hMyThread: THandle; //线程句柄 iThreadID: DWORD = 0; //线程ID begin hMyThread := CreateThread(nil, 0, @ThreadFun, nil, 0, iThreadID); .. end; 其中,ThreadFun是你定义的线程函数或过程,注意,因为这里是使用Win32 API创建线程,所以这个ThreadFun函数必须设置成stdcall; 如: procedure ThreadFun; stdcall; 2.向子线程发消息 BOOL PostThreadMessage( DWORD idThread, // thread identifierUINT Msg, // message to post WPARAM wParam, // first message parameter LPARAM lParam // second message parameter ); 举例: const WM_MyMsg = WM_USER + 100; //用户自定义消息 PostThreadMessage(iThreadID, WM_MyMsg, 0, 0); 上面这句是主线程向iThreadID子线程发送WM_MyMsg消息。不过,在第1次向子线程发消息的时候,应该循环发,直到发送成功。这样: while not PostThreadMessage(iThreadID, WM_MyMsg, 0, 0) do 3. 销毁子线程 1. PostThreadMessage(iThreadID, WM_QUIT, 0, 0); 2.CloseHandle(hMyThread); BOOL CloseHandle( HANDLE hObject // handle to object to close ); 如果iThreadID子线程内建了消息循环,哪么当线程中的GetMessage收到这个WM_QUIT消息后,iThreadID子线程将销毁。 4.子线程内建消息循环。 需要用到下面几个API: a. 取得消息: GetMessage() 或 PeekMessage() BOOL GetMessage( LPMSG lpMsg, // address of structure with message HWND hWnd, // handle of window UINT wMsgFilterMin, // first message UINT wMsgFilterMax // last message ); BOOL PeekMessage( LPMSG lpMsg, // pointer to structure for message HWND hWnd, // handle to window UINT wMsgFilterMin, // first message UINT wMsgFilterMax, // last message UINT wRemoveMsg // removal flags ); 这2个取得消息函数还是有点不同的。 GetMessage()函数在线程消息队列中取消息的时候,如果这时候消息队列中没有消息,该线程将冻结,直到别的线程向该线程发送一条消息后才会重新激活。 PeekMessage()函数在线程消息队列中取消息的时候,如果这时候消息队列中没有消息,操作系统还是让该线程执行一段时间。换句话说,它的作用只是查看一下线程的消息队列中有没有消息。个人觉得,这个函数要比GetMessage()函数用处更大一点。当然,GetMessage()函数在有些情况下,也是另有妙用。 b.翻译和派遣消息。 TranslateMessage(msg); //翻译消息 DispatchMessage(msg); //派遣消息 BOOL TranslateMessage( CONST MSG *lpMsg // address of structure with message ); LONG DispatchMessage( CONST MSG *lpmsg // pointer to structure with message ); 上面这2个函数是消息循环的核心,它们和GetMessage() 或 PeekMessage()一齐构建消息循环---程序的心脏 举例: var msg: TMSG; fQuit: Boolean; begin while not fQuit do begin while PeekMessage(msg, 0, 0, 0, PM_REMOVE) do //while GetMessage(msg, 0, 0, 0) do begin if msg.message = WM_QUIT then begin fQuit := True; end else if msg.message = WM_MyMsg then begin .. end else begin TranslateMessage(msg); DispatchMessage(msg); end; end; end; end; 上面的例子我为了写着省事,把PeekMessage()和 GetMessage() 放在一齐了。当然,你要明白,如果实际用的是GetMessage() 循环,if msg.message = WM_QUIT then是无用的,它只是为了上面的PeekMessage()而存在。因为当线程GetMessage() 收到WM_QUIT时,GetMessage()循环就退出了。 |
|