///////////////////////////////////////////
1。“一个进程只有一个消息队列,无论进程创建了多少线程”----对嘛??2。getmessage的参数只能指定窗口句柄,那么得到的是整个应用程序里面那个窗口的消息还是属于本线程所创建的handle匹配的窗口?
如果时后者,那么创建窗口的时候createwindowex函数好像没有规定线程id!3。如果用peekmessage如何?4。application.processmessages又如何?
下面是代码:在一个线程execute的时候创建一个窗体,///////////////////////////
unit Main;//主窗体单元。interfaceuses
Windows,wndthreadunit, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.dfm}procedure TForm1.Button1Click(Sender: TObject);
var
t:TWndThread;
begin
t:=TWndThread.Create(false);end;end.
/////////////////////////////
unit wndthreadunit;//线程单元。interfaceuses
Classes,windows,forms,controls;type
TWndThread = class(TThread)
private
{ Private declarations }
form:tform;
protected
procedure Execute; override;
public
constructor Create(ASuspend:boolean);
end;implementation{ WndThread }constructor TWndThread.Create(ASuspend: boolean);
begin
inherited create(asuspend);
end;procedure TWndThread.Execute;
var
msg:tmsg;
begin
form:=tform.Create(nil);
form.Left:=0;
form.Top:=0;
form.Width:=300;
form.Height:=100;
form.Caption:='Thread Form';
form.Show; while not terminated do
begin
//application.ProcessMessages; 去掉注释,注释下面三行也不会有问题。
getMessage(Msg, form.Handle, 0, 0);
translatemessage(msg);
dispatchmessage(msg); end;end;end.
//////////////////////////////////////////////////////
2、线程有自己的消息队列,在消息循环
getMessage(Msg, form.Handle, 0, 0);
translatemessage(msg);
dispatchmessage(msg);
中getMessage得到的当然是自己线程的消息
3、getMessage和PekkMessage当然是有区别的,如果消息队列里没有消息,PeekMessage就会返回FALIE,不会等待继续获取消息;而GetMessage则会一直等待消息队列,等到里面有消息为止,才返回。
4、所以,如果你用getMessage(Msg, form.Handle, 0, 0)取得消息,application.ProcessMessages最好能用上,它可以强制一个消息,因为如果没有取得消息的话,getMessage就会一直等待消息。虽然你的程序没有错:)
以上仅是我对消息运行机制的一点理解。
好棒!拍马屁中。
To: stanely (俺是邢她汉子)
我认为线程中带Form总是不太好吧,我认为线程一般是用来进行大量数据的并行辅助运算。一个主进程中有多个线程Form同时运行,你用没有试过线程同步?(我试过,效果不理想)。
帮你up
目的不是要在线程里面实现什么,就是想借助这个例子,高明白windows 消息机制。
“如果你一定要去掉application.ProcessMessages,你就用PeekMessage来获取消”。
我曾经式过,但是会出现问题,只能用getmessage那套组合。。不知道为什么: peekMessage(Msg, form.Handle, 0, 0);
translatemessage(msg);
dispatchmessage(msg);
/////////////////////
另外, getMessage(Msg, form.Handle, 0, 0);
translatemessage(msg);
dispatchmessage(msg);
不要translatemessage(msg);仿佛也可以。不知道为什么??
还有,如果消息是队列跟线程一一对应的,那么如果我要给一个工作线程发消息,用什么?
sendmessage?那么句柄是谁呢?谢谢!
function TApplication.ProcessMessage(var Msg: TMsg): Boolean;
var
Handled: Boolean;
begin
Result := False;
if PeekMessage(Msg, 0, 0, 0, PM_REMOVE) then
begin
Result := True;
if Msg.Message <> WM_QUIT then
begin
Handled := False;
if Assigned(FOnMessage) then FOnMessage(Msg, Handled);
if not IsHintMsg(Msg) and not Handled and not IsMDIMsg(Msg) and
not IsKeyMsg(Msg) and not IsDlgMsg(Msg) then
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
end
else
FTerminate := True;
end;
PeekMessage(Msg, 0, 0, 0, PM_REMOVE),它有五个参数,如果你要知道PM_REMOVE和PeekMessage里参数的意思,可以云看看MSDN。
如果你不要translatemessage(msg)当然可以运行程序,但用来“派送消息”的函数都没有,你的消息循环做来干什么?
DELPHI中的大部份VCL是线程不安全的,为此Borland为线程提供了一个Synchronize函数来处理消息,当然你也可以自己做,用SendMessage来实现,句柄是你的线程窗口句柄,不过用PostMessage来发送消息是不行的。你可以试试
var
msg:tmsg;
begin
form:=tform.Create(nil);
form.Left:=0;
form.Top:=0;
form.Width:=300;
form.Height:=100;
form.Caption:='Thread Form';
form.Show; while not terminated do
begin
//application.ProcessMessages; 去掉注释,注释下面三行也不会有问题。
getMessage(Msg, form.Handle, 0, 0);
translatemessage(msg);
dispatchmessage(msg); end;
以上程序中的消息循环是你自己线程的消息循环,不知道你是否这样认为
sendmessage?那么句柄是谁呢?SendMessage的句柄当然是0了,也可以用postthreadmessage了。
看看msdn吧。delphi fans也可以看看嘛
进程建立了一个主线程,一个线程拥有一个消息队列,所以在主线程中的ProcessMessages可以通过: PeekMessage进行取发给这个线程的消息
如果你建立的线程需要建立消息队列,这样做:
PeekMessage(msg, 0, 0, 0, PM_NOREMOVE);
参数: PeekMessage的PM_NOREMOVE就是创建一个消息队列,help写的很明白,PeekMessage即可以从消息队列中取消息也可以创建消息队列,关键就是:PM_REMOVE, 和 PM_NOREMOVE,记住,在自已的线程创建消息队列必须在线程的运行中进行,即:
procedure TMyThread.Execute;
begin
PeekMessage(msg, 0, 0, 0, PM_NOREMOVE);
...
while PeekMessage(msg, 0, 0, 0, PM_REMOVE) do
DispatchMessage(msg); //
end;
PostThreadMessage(MyThread.ThreadID, WM_MyMsg, wParam, lParam);也就是PostThreadMessage, 那个Handle参数是消息队列线程的ThreadID,记住这很重要。
"版主兄,我是说translatemessage可以不用,但是dispatchmessage要用啊。
因为我试验过,去掉translatemessage也没有什么不一样的阿。"
不好意思,看错函数了,但不管你的程序是否编译通过,没有正确的消息循环,你是得到不你要获取的线程消息的。
如果楼主要得到更多的线程方面的东西,请参看北京大学出版社《Windows程序设计》
我觉得我也没错吧,难道sendmessage(0,....)不给线程, 我去看看msdn先