在线程中如何响应消息?(100分)

  • 主题发起人 主题发起人 delscr
  • 开始时间 开始时间
D

delscr

Unregistered / Unconfirmed
GUEST, unregistred user!
在用VC++编程时,线程分为用户线程和工作线程,用户线程可有自己
的消息队列,可定义消息响应函数,而工作线程只有一个线程函数,没有
消息响应。
感觉DELPHI中的TTHREAD类只能实现工作线程,成员函数EXECUTE()
便是线程函数,是线程的执行体。
在DELPHI的子线程中如何实现消息响应呢?
 
ProcessMessage?
 
消息响应?
好像直接实现是不行,但可以用事件来模拟,或者干脆用全局变量来做.
btw:为什么一定要做用户子线程?
 
如果你是直接继承TThread对象的话,你不能进行消息响应。
如果你需要响应消息的话,你必须拥有自己的窗口,
自己做一个消息循环机制。
 
响应消息的话,必须拥有自己的窗口 可以通过AllocateHWnd函数来分配一个窗口
句柄,AllocateHWnd的参数中定义的wndproc函数来响应消息。
 
线程响应消息一定要窗口吗?No.
1)当前执行体是线程 (废话)
2)用GetMessage()/PeekMessage()在循环中接消息,
无须Translate 和 Dispatch
3)一旦收到立即处理(在循环中)
4)用PostThreadMessage()向该线程发消息。
这不得了。
不管SDK,MFC,C++ Builder,Delphi都一样.
 
你作一个隐藏的窗口,在这个窗口中响应
 
从写winproc不就行了!
 
请参看问题 <a href="/delphibbs/DispQ.asp?LID=122299">how to create message queue</A>的回答
 
在TThread中处理消息可以用以下方法:
type
TMyThread=class(TThread)
private
FOwner:TControl;
FOwnerProc:TWndMethod;
FMessage:TMessage;
FEvent :TSingleEvent;
procedure ThreadWndProc(var Message:TMessage);
constructor Create(AOwner:TControl);
destructor Destroy;
protect
procedure Execute;override;
end;

constructor TMyThread.Create(AOwner:TControl);
begin
inherited Create(True);
FOwner:=AOwner;
if Assigned(FOwner) then
begin
FOwenrProc:=AOwner.WindowProc;
FOwner.WindowProc:=ThreadWndProc;
end;
FEvent:=TSingleEvent.Create;
end;

destroy TMyThread.Destroy;
begin
if Assigned(FOwner) then
FOwner.WindowProc:=FOwnerProc;
FEvent.Free;
inherited Destroy;
end;

procedure TMyThread.ThreadWndProc(var Message:TMessage);
begin
if Message.Msg=WM_DESTROY then
begin
FOwner.WindowProc:=FOwnerProc;
FOwnerProc:=nil;
FOwner:=nil;
end;
FMessage:=Message;
SetEvent(FEvent);
if Assigned(FOwnerProc) then
FOwnerProc(Message);

end;

procedure TMyThread.Execute;
begin
while not Terminateddo
begin
WaitForSingleEvent(FEvent, INIFILE);
....//根据FMessage处理消息,
end;

end;
 
在上面中有一个小错误,
SetEvent(FEvent)应改为FEvent.SetEvent;
在WaitForSingleObject(...);
后应加上
FEvent.ResetEvent;
这个例子片段是我临时输入的,因为源程序很难找到了。
 
更正:
type
TMyThread=class(TThread)
private
FOwner:TControl;
FOwnerProc:TWndMethod;
FMessage:TMessage;
FEvent :TSimpleEvent;
procedure ThreadWndProc(var Message:TMessage);
constructor Create(AOwner:TControl);
destructor Destroy;
protect
procedure Execute;override;
end;

constructor TMyThread.Create(AOwner:TControl);
begin
inherited Create(True);
FOwner:=AOwner;
if Assigned(FOwner) then
begin
FOwenrProc:=AOwner.WindowProc;
FOwner.WindowProc:=ThreadWndProc;
end;
FEvent:=TSimpleEvent.Create;
end;
destroy TMyThread.Destroy;
begin
if Assigned(FOwner) then
FOwner.WindowProc:=FOwnerProc;

FEvent.Free;
inherited Destroy;
end;

procedure TMyThread.ThreadWndProc(var Message:TMessage);
begin
if Message.Msg=WM_DESTROY then

begin
FOwner.WindowProc:=FOwnerProc;
FOwnerProc:=nil;
FOwner:=nil;
end;
if Message.Msg=所要处理的消息 then
begin
FMessage:=Message;
FEvent.SetEvent;
end
else
if Assigned(FOwnerProc) then
FOwnerProc(Message);

end;
procedure TMyThread.Execute;
begin
while not Terminateddo
begin
FEvent.WaitFor(INIFILE);
FEvent.ResetEvent;
....//根据FMessage处理消息
end
end;
 
我在我的程序里面采用了Hexi同志的FEvent.WaitFor(INIFILE)语句,但是编译时提示错误信息:Undeclared Identifier "INIFILE",我查过帮助,TEvent.WaitFor方法所要的参数为TimeOut:DWORD,返回值为TWaitResult.也即必须要你设置一个超时值.此处INIFILE是否有误,设置INIFILE的目的是否为无限期等待?
 
改为:INFINITE
 
本例程有点问题,但程序关闭时,线程没有收到消息,将一直等待,
所以建议改为:
procedure TMyThread.ThreadWndProc(var Message:TMessage);
begin
if Message.Msg=WM_DESTROY then

begin
Terminate;
FMEssage:=Message;
FEvent.SetEvent;
FOwner.WindowProc:=FOwnerProc;
FOwnerProc:=nil;
FOwner:=nil;
end;
if Message.Msg=所要处理的消息 then
begin
FMessage:=Message;
FEvent.SetEvent;
end
else
if Assigned(FOwnerProc) then
FOwnerProc(Message);

end;
 
本例程有点问题,但程序关闭时,线程没有收到消息,将一直等待,
所以建议改为:
procedure TMyThread.ThreadWndProc(var Message:TMessage);
begin
if Message.Msg=WM_DESTROY then

begin
Terminate;
FMEssage:=Message;
FEvent.SetEvent;
FOwner.WindowProc:=FOwnerProc;
FOwnerProc:=nil;
FOwner:=nil;
end;
if Message.Msg=所要处理的消息 then
begin
FMessage:=Message;
FEvent.SetEvent;
end
else
if Assigned(FOwnerProc) then
FOwnerProc(Message);

end;
 
线程创建时时没有消息队列的,但是只要在改线程一调用 Win32 USER 或者 GDI
函数就会创建消息队列。
处理消息可以使用传统的处理方法:
MSG m;
while(GetMessage(&amp;m,0,0,0))
{
TranslateMessage(&amp;m);
DispatchMessage(&amp;m);
}
 
PostThreadMessage(YourThread,YourMessage,0,0)即可。
 
sorry,应是PostThreadMessage(YourThread.threadid,YourMessage,0,0),顺便问一下视窗王子,在线程中响应消息时,如果同时需要其处理自定义的消息处理程序,应该怎么做?是否应首先建一个消息队列,如果是这样,那么这个消息队列应什么建立?
mail:ydystory@163bj.com
 
后退
顶部