线程消息循环为一个隐藏窗口的线程? [英] Thread message loop for a thread with a hidden window?

查看:192
本文介绍了线程消息循环为一个隐藏窗口的线程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Delphi 6应用程序,它具有专门用于与使用SendMessage()和WM_COPYDATA消息的外部应用程序进行通信的线程,以与外部程序接口。因此,由于SendMessage()函数只接受窗口句柄而不是线程ID,因此线程消息队列不能正常工作,因此使用AllocateHWND()创建一个隐藏窗口。我不知道什么是在线程Execute()方法。



我假设如果我使用GetMessage()循环或创建一个循环使用WaitFor *()函数调用线程将阻塞,因此线程的WndProc()将永远不会从外部程序处理SendMessage()消息?如果是这样,那么输入Execute()循环的正确代码是不会不必要地消耗CPU周期的,但一旦接收到WM_QUIT消息就会退出?我可以随时使用Sleep()循环,但是我想知道是否有更好的方法。

解决方案

AllocateHWnd()(更具体地说, MakeObjectInstance())不是线程安全的,所以你必须小心它。更好地直接使用 CreatWindow / Ex()



无论如何, HWND 绑定到创建它的线程上下文,因此您必须在 Execute()中创建并销毁 HWND 方法,不在线程的构造函数/析构函数中。此外,即使 SendMessage()正在用于向您发送消息,它们来自另一个进程,因此它们将不会被您的 HWND 直到其拥有的线程执行消息检索操作,因此线程需要自己的消息循环。



您的 Execute()方法应该如下所示:

  procedure TMyThread.Execute; 
var
消息:TMsg;
begin
FWnd:= AllocateHWnd(WndProc);
尝试
而不是终止do
begin
如果MsgWaitForMultipleObjects(0,nil ^,False,1000,QS_ALLINPUT)= WAIT_OBJECT_0然后
begin
,而PeekMessage (消息,0,0,0,PM_REMOVE)do
begin
TranslateMessage(Message);
DispatchMessage(Message);
结束
结束
结束
finally
DeallocateHWnd(FWnd);
结束
结束

程序TMyThread.WndProc(var Message:TMessage);
begin
如果Message.Msg = WM_COPYDATA然后
begin
...
Message.Result:= ...;
end else
Message.Result:= DefWindowProc(FWnd,Message.Msg,Message.WParam,Message.LParam);
结束


I have a Delphi 6 application that has a thread dedicated to communicating with a foreign application that uses SendMessage() and WM_COPYDATA messages to interface with external programs. Therefore, I create a hidden window with AllocateHWND() to service that need since a thread message queue won't work due to the SendMessage() function only accepting window handles, not thread IDs. What I'm not sure about is what to put in the thread Execute() method.

I assume that if I use a GetMessage() loop or a create a loop with a WaitFor*() function call in it that the thread will block and therefore the thread's WndProc() will never process the SendMessage() messages from the foreign program right? If so, what is the correct code to put in an Execute() loop that will not consume CPU cycles unnecessarily but will exit once a WM_QUIT message is received? I can always do a loop with a Sleep() if necessary but I'm wondering if there is a better way.

解决方案

AllocateHWnd() (more specifically, MakeObjectInstance()) is not thread-safe, so you have to be careful with it. Better to use CreatWindow/Ex() directly instead.

In any case, an HWND is tied to the thread context that creates it, so you have to create and destroy the HWND inside your Execute() method, not in the thread's constructor/destructor. Also, even though SendMessage() is being used to send the messages to you, they are coming from another process, so they will not be processed by your HWND until its owning thread performs message retrieval operations, so the thread needs its own a message loop.

Your Execute() method should look something like this:

procedure TMyThread.Execute;
var
  Message: TMsg;
begin
  FWnd := AllocateHWnd(WndProc);
  try
    while not Terminated do
    begin
      if MsgWaitForMultipleObjects(0, nil^, False, 1000, QS_ALLINPUT) = WAIT_OBJECT_0 then
      begin
        while PeekMessage(Message, 0, 0, 0, PM_REMOVE) do
        begin
          TranslateMessage(Message);
          DispatchMessage(Message);
        end;
      end;
    end;
  finally
    DeallocateHWnd(FWnd);
  end;
end;

procedure TMyThread.WndProc(var Message: TMessage);
begin
  if Message.Msg = WM_COPYDATA then
  begin
    ...
    Message.Result := ...;
  end else
    Message.Result := DefWindowProc(FWnd, Message.Msg, Message.WParam, Message.LParam);
end;

这篇关于线程消息循环为一个隐藏窗口的线程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆