如何创建一个纯WinAPI窗口。

6

目标是在两个线程之间创建通讯,其中一个线程是主线程。我正在寻找的是创建一个窗口,它需要更少的资源,并且只用于接收信息。

你能给我提供一些参考吗?


2
你可能想要查看AllocateHWnd - Sertac Akyuz
@Sertac Akyuz,抱歉,我无意中劫持了您的建议,在写完自己的答案后才注意到这一点 :-( - Premature Optimization
AllocateHwnd 的缺点是它不是线程安全的。当然,这可以通过解决方法来解决。 - David Heffernan
1
@Downvoter - 不需要道歉或删除答案。答案与评论不同。我发表评论是因为我没有跟进、代码示例等意图。实际上,我认为这可能是问题的一个可能解决方案。 - Sertac Akyuz
3个回答

7

这种情况下,这个问题有点像一个重复的问题,不过链接到的问题是如此具体,而这个问题是一般性的,因此这个问题更有用。也许在这种情况下最好将整个代码示例(重复)粘贴在这里……你的想法是什么? - Warren P

7
您需要在线程中设置一个消息循环,并在主线程中使用AllocateHWnd来进行双向消息传递。这很简单。在您的线程执行函数中添加以下内容:
procedure TMyThread.Execute;
begin
  // this sets up the thread message loop
  PeekMessage(LMessage, 0, WM_USER, WM_USER, PM_NOREMOVE);

  // your main loop
  while not terminated do
  begin
    // look for messages in the threads message queue and process them in turn.
    // You can use GetMessage here instead and it will block waiting for messages
    // which is good if you don't have anything else to do in your thread.
    while PeekMessage(LMessage, 0, WM_USER, $7FFF, PM_REMOVE) do
    begin
      case LMessage.Msg of
      //process the messages
      end;
    end;

    // do other things. There would probably be a wait of some 
    // kind in here. I'm just putting a Sleep call for brevity
    Sleep(500);

  end;
end;

要向您的线程发送消息,请执行以下操作:

PostThreadMessage(MyThread.Handle, WM_USER, 0, 0);

在主线程方面,使用Classes单元中的AllocateHWnd方法设置窗口句柄,并传递一个WndProc方法。AllocateHWnd非常轻量级且易于使用:

TMyMessageReciever = class
private
  FHandle: integer;

  procedure WndProc(var Msg: TMessage);

public
  constructor Create;
  drestructor Destroy; override;

  property Handle: integer read FHandle;

end;

implementation

constructor TMyMessageReciever.Create;
begin
  inherited Create;
  FHandle := Classes.AllocateHWnd(WndProc);
end;

destructor TMyMessageReciever.Destroy;
begin
  DeallocateHWnd(FHandle);
  inherited Destroy;
end;

procedure TMyMessageReciever.WndProc(var Msg: TMessage);
begin
  case Msg.Msg of
  //handle your messages here
  end;
end;

您可以使用SendMessagePostMessage发送消息,前者会阻塞直到消息被处理,后者则是异步的。

希望这能帮助您。


3
如果你想减少资源占用,那么在主线程上其实并不需要使用AllocateHwnd()方法。相反,你可以使用PostThreadMessage()将消息直接发送到主线程的消息队列中,使用MainThreadID变量作为目标线程ID。然后使用TApplication.OnMessage事件来接收这些消息。你可以通过查看TMsg.hwnd成员来区分一个线程消息和一个窗口消息,因为对于线程消息来说,它将为零。 - Remy Lebeau
都试过了,但在控制台应用程序上都不起作用。我的代码 --> http://pastebin.com/jm5K4EHN - netboy
我没有意识到你在一个控制台应用程序中...我看到了你代码中的问题...你没有定期检查消息队列以查看是否有任何消息...你的代码只是停留在Readln上。对于“非控制台”应用程序,你需要定期调用Application.ProcessMessage。在控制台版本中,你需要一个消息泵。我认为你应该看一下Andreas的例子,它正是你想要做的事情。 - Nat

2
在Gabr的OmniThread Library中,提供了一个很好的小单元DSiWin32,您可以使用它来创建消息窗口,或者您也可以直接使用OmniThread来进行通信。

这比进行低级别的黑客行为要好得多。 - Warren P

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接