Delphi中使用Win32 API创建内建消息循环的线程函数

来源:互联网 发布:Java配置变量后 编辑:程序博客网 时间:2024/05/17 02:03
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 identifier
    UINT 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
       Sleep(100);


  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()循环就退出了。

  
原创粉丝点击