A
awfigsk
Unregistered / Unconfirmed
GUEST, unregistred user!
作者 消息传递的问题
awfigsk 发帖: 40
于2006-01-13 17:00
--------------------------------------------------------------------------------
为什么单击主窗体Form1的消息会被Application.onMessage先捕获到?单击主窗体Form1时,消息的句柄值是否应该是Form1句柄,那么消息应该是主窗体的回调函数先捕获到,为何Application的回调函数先得到该消息?
还请各位大侠指点,谢谢!
=========================================================
小雨哥
文心雕龙
版主
发帖: 818
来自: 浙江杭州
于2006-01-13 18:58
----------------------------------------------------------------
============================================================================
awfigsk
发帖: 40
于2006-01-14 08:13
--------------------------------------------------------------------------------
操作系统是如何知道Form1是属于哪个Application的呢?
当FORM1上某个事件发生时,操作系统是根据什么将这个消息发往Application的消息队列?难道是根据句柄?那如果这个Application有多个Form窗口,发生在这些Form窗口的消息都是操作系统根据各自的句柄都将消息发往该Applicaiton的消息队列中吗?那操作系统是如何知道含有这些句柄的消息都应当发往这个Application的消息队列呢?
这些消息都是经过Application中的ProcessMessage方法发送到各自的窗口吗?
Application.processmessage(..)
begin
......
if PeekMessage(...) then
...
TranslateMessage(...)
DispatchMessage(...)
end
end
但DispatchMessage应该调用Application的回调函数来处理消息,也就是Application.WndProc这个方法呀,那如何将属于form窗口的消息发往form窗口的回调函数MainWndProc方法呢?
还请小雨哥和各位侠客指点,谢谢!
awfigsk 编辑于 2006-01-14 09:10
===============================================================================
小雨哥
文心雕龙
版主
发帖: 818
来自: 浙江杭州
于2006-01-14 12:00
--------------------------------------------------------------------------------
awfigsk 你好,我记得你在看李维的 inside vcl 。上面你提到的问题,其实是
VCL的重要核心之一,李维的书上应该有更精彩的描述,你可以仔细看看。
WndProc在VCL体系中,并不是TWinControl控件才有的,也就是说,你要尽快
走出Windows的消息体系,进入到VCL的架构中来。其中与WndProc有关的内
容,在Delphi7版本上,你可以在Classes.pas中找到MakeObjectInstance,在
Controls.pas中你可以找到InitWndProc等重要的函数或过程。
这些内容跨越了好几个单元文件,而且有好几种具体的应用。归结到你的问题,
你首先要阅读TWinControl的Create方法,并理解TWinControl是在什么时候才
有了一个Hendle的,以至于它看起来就象是Windows体系中的一员。如果能够
理顺这些流程,你的问题就迎刃而解了。这是VCL体系中的一个难点,也是希望
学懂VCL的必由之路。
=============================================================================
awfigsk
发帖: 40
于2006-01-16 09:40
--------------------------------------------------------------------------------
小雨哥,你好!
我是看到Inside vcl关于消息的章节,才遇到上述这个问题。
我现在就是对发生在窗体的事件,操作系统是如何将这个消息放入到该应用程序的消息队列当中感到糊涂.
例如:当有一个应用程序Application1,一个主窗体Form1,上面有一个按钮Button1,当单击该按钮时发生单击事件,操作系统将其转为消息来处理,消息中应该含有该控件的句柄,也就是Button1的句柄,但操作系统如何知道这个消息就应该放到Application1的消息队列中呢?
MakeObjectInstance和InitWndProc都是在应用程序创建时,将类的方法转换为Windows的标准回调函数,让系统可以调用。
我现在不明白就是当应用程序的事件发生时,操作系统是根据什么将该事件消息放到应用程序的消息队列中?根据书上所描述,每个应用程序都有一个消息队列,当应用程序发生某个事件后,系统都会将该事件转换为消息,但是根据什么将消息放到该消息队列的呢?系统是如何知道这个消息就是这个应用程序的呢?Getmessage和PeekMessage是如何取得应用程序消息的?
实在是感到糊涂,还请指点,谢谢!
awfigsk 编辑于 2006-01-16 09:50
============================================================================
小雨哥
文心雕龙
版主
发帖: 818
来自: 浙江杭州
于2006-01-17 03:20
--------------------------------------------------------------------------------
这个情况你得去看看Windows源代码,我还没有看到过Windows源代码,所以
我所说的,只能是猜测。
帖子http://www.01cn.net/cgi-bin/topic_show.cgi?id=2870中我讲到过,程
序一旦运行,Windows就会记录下这个应用程序的一些信息。为了便于说明,
我们简单地讨论你帖子里讲到的例子(实际上还有一些不同的例子):
不知你是否知道"BUTTON"这个Windows预定义窗口类,简单地说,我们程序
里的一个BUTTON控件,它的工作代码不在我们的程序里,而在Windows的源
代码里,一旦按下按钮,Windows就会装配一个消息结构并把它发送到系统消
息队列,而它装配的最原始的消息结构是怎么样的,也在Windows的源代码里
没有公开过,从猜测来看,它应该会查找这个"BUTTON"是由哪个应用程序实
例创建的,也就是通常我们所说的,这个"BUTTON"的父是谁,并把相关的信
息填充到最原始的消息结构中。
我们的应用程序总会有一个GetMessage的调用,这个调用的目的就是从系统消
息队列中检索与调用进程有关的消息,这个GetMessage也在Windows源代码中
没有公开过,不过我们通过对它的观察可以猜到,它确实能够正确地把与调用
进程相关的消息取出来这点来看,可以肯定它能够识别出正确的消息,这也就
意味着它能够解释最原始的Windows消息,并且能够把无关的信息剔除,只填
充一个对应用程序有用的tagMSG回来。tagMSG如何工作,我想你已经理解了。
如果上面所说的与你的理解相同的话,那么我们再进一步看消息是怎么来的:
当你看到你按下按钮的时候,那个按钮一样的东西真的凹陷下去,你就以为这
个时候是这个按钮发送了消息的话,那么你就忽视了鼠标的存在。实质是鼠标
发生了点击动作,而按钮凹陷下去只是Windows给我们的一种视觉效果。
Windows只是把鼠标点击事件与按钮所在的实例进程等信息进行了一番妥善的
包装以后,生成一条最原始的、未公开结构的Windows内部消息,并把它放到
系统消息队列。一个应用程序正是利用Windows提供给我们的GetMessage函数
去取,才能取到正确的消息,任何自定义的函数好像都是不能完成这个工作的。
等到获得了tagMSG后,后面的工作大家都经常在利用也很容易理解,但我还是
要提醒你注意二个很重要的TranslateMessage和DispatchMessage,我不打算多
说这二个函数,只是希望你有空的时候也去考虑一下这二个函数:既然GetMessage
已经返回了消息,为什么还要这二个函数?按照字面理解,TranslateMessage
应该是对消息的转换和翻译,但我们不是已经知道有消息来了吗?而且我们从
返回的消息中也已经有了HWND,还要转化翻译什么呢?随后就是DispatchMessage,
按照字面理解,这里应该是把消息发送到处理这个消息的WndProc去。我没有
看到源代码,假设它们真的有事情要做的话,TranslateMessage就是寻找真正
的WndProc的地方。也就是说,只有通过TranslateMessage才真正找出处理这
个消息的WndProc,那,它能找到什么依据来认为找到的WndProc才是处理这
条消息的正确位置呢?答案应该是程序启动时在Windows中利用RegisterClass
函数登记的窗口类信息,这个信息中包含了最原始的WndProc。只有这样,后
面的DispatchMessage才不会把消息投错地方。
如果真的是这样的话,假如我们在利用RegisterClass注册了这个窗口类信息,并
利用CreateWindow(或者CreateWindowEx)创建了这个窗口后,我们又通过
某种手段把已经登记的窗口类中的WndProc改换成另外的指针的话,Windows
就会“错误”地把这个改变以后的指针当做“真”的指针(即原始WndProc),并
把消息投放进去。这种偷梁换柱的做法就是中途截获,也称钩子。
在理解这些东西的时候,应该不要涉及到Application,而用纯粹的Windows消
息体系去理解会比较方便些。如果李维没有在Inside vcl中没有说到这些内容,
我认为应该是正确的,因为这些内容应该仅仅属于Windows,而不属于VCL。
最后,我想,这个问题比较适合初学者,所以建议你是否能把这个帖子放到Delphi
基础那个板块去,以利于更多的初学者能够检索到。
============================================================================
小雨哥
文心雕龙
版主
发帖: 818
来自: 浙江杭州
于2006-01-17 03:45
--------------------------------------------------------------------------------
最后补充一下进入了Application后面的内容,这个内容前人已经做了大量探索,
其中比较优秀的一篇,是savetime发表在大富翁的文章:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=2403549
学习VCL的话,这一篇一定要仔细读。
awfigsk 发帖: 40
于2006-01-13 17:00
--------------------------------------------------------------------------------
为什么单击主窗体Form1的消息会被Application.onMessage先捕获到?单击主窗体Form1时,消息的句柄值是否应该是Form1句柄,那么消息应该是主窗体的回调函数先捕获到,为何Application的回调函数先得到该消息?
还请各位大侠指点,谢谢!
=========================================================
小雨哥
文心雕龙
版主
发帖: 818
来自: 浙江杭州
于2006-01-13 18:58
----------------------------------------------------------------
============================================================================
awfigsk
发帖: 40
于2006-01-14 08:13
--------------------------------------------------------------------------------
操作系统是如何知道Form1是属于哪个Application的呢?
当FORM1上某个事件发生时,操作系统是根据什么将这个消息发往Application的消息队列?难道是根据句柄?那如果这个Application有多个Form窗口,发生在这些Form窗口的消息都是操作系统根据各自的句柄都将消息发往该Applicaiton的消息队列中吗?那操作系统是如何知道含有这些句柄的消息都应当发往这个Application的消息队列呢?
这些消息都是经过Application中的ProcessMessage方法发送到各自的窗口吗?
Application.processmessage(..)
begin
......
if PeekMessage(...) then
...
TranslateMessage(...)
DispatchMessage(...)
end
end
但DispatchMessage应该调用Application的回调函数来处理消息,也就是Application.WndProc这个方法呀,那如何将属于form窗口的消息发往form窗口的回调函数MainWndProc方法呢?
还请小雨哥和各位侠客指点,谢谢!
awfigsk 编辑于 2006-01-14 09:10
===============================================================================
小雨哥
文心雕龙
版主
发帖: 818
来自: 浙江杭州
于2006-01-14 12:00
--------------------------------------------------------------------------------
awfigsk 你好,我记得你在看李维的 inside vcl 。上面你提到的问题,其实是
VCL的重要核心之一,李维的书上应该有更精彩的描述,你可以仔细看看。
WndProc在VCL体系中,并不是TWinControl控件才有的,也就是说,你要尽快
走出Windows的消息体系,进入到VCL的架构中来。其中与WndProc有关的内
容,在Delphi7版本上,你可以在Classes.pas中找到MakeObjectInstance,在
Controls.pas中你可以找到InitWndProc等重要的函数或过程。
这些内容跨越了好几个单元文件,而且有好几种具体的应用。归结到你的问题,
你首先要阅读TWinControl的Create方法,并理解TWinControl是在什么时候才
有了一个Hendle的,以至于它看起来就象是Windows体系中的一员。如果能够
理顺这些流程,你的问题就迎刃而解了。这是VCL体系中的一个难点,也是希望
学懂VCL的必由之路。
=============================================================================
awfigsk
发帖: 40
于2006-01-16 09:40
--------------------------------------------------------------------------------
小雨哥,你好!
我是看到Inside vcl关于消息的章节,才遇到上述这个问题。
我现在就是对发生在窗体的事件,操作系统是如何将这个消息放入到该应用程序的消息队列当中感到糊涂.
例如:当有一个应用程序Application1,一个主窗体Form1,上面有一个按钮Button1,当单击该按钮时发生单击事件,操作系统将其转为消息来处理,消息中应该含有该控件的句柄,也就是Button1的句柄,但操作系统如何知道这个消息就应该放到Application1的消息队列中呢?
MakeObjectInstance和InitWndProc都是在应用程序创建时,将类的方法转换为Windows的标准回调函数,让系统可以调用。
我现在不明白就是当应用程序的事件发生时,操作系统是根据什么将该事件消息放到应用程序的消息队列中?根据书上所描述,每个应用程序都有一个消息队列,当应用程序发生某个事件后,系统都会将该事件转换为消息,但是根据什么将消息放到该消息队列的呢?系统是如何知道这个消息就是这个应用程序的呢?Getmessage和PeekMessage是如何取得应用程序消息的?
实在是感到糊涂,还请指点,谢谢!
awfigsk 编辑于 2006-01-16 09:50
============================================================================
小雨哥
文心雕龙
版主
发帖: 818
来自: 浙江杭州
于2006-01-17 03:20
--------------------------------------------------------------------------------
这个情况你得去看看Windows源代码,我还没有看到过Windows源代码,所以
我所说的,只能是猜测。
帖子http://www.01cn.net/cgi-bin/topic_show.cgi?id=2870中我讲到过,程
序一旦运行,Windows就会记录下这个应用程序的一些信息。为了便于说明,
我们简单地讨论你帖子里讲到的例子(实际上还有一些不同的例子):
不知你是否知道"BUTTON"这个Windows预定义窗口类,简单地说,我们程序
里的一个BUTTON控件,它的工作代码不在我们的程序里,而在Windows的源
代码里,一旦按下按钮,Windows就会装配一个消息结构并把它发送到系统消
息队列,而它装配的最原始的消息结构是怎么样的,也在Windows的源代码里
没有公开过,从猜测来看,它应该会查找这个"BUTTON"是由哪个应用程序实
例创建的,也就是通常我们所说的,这个"BUTTON"的父是谁,并把相关的信
息填充到最原始的消息结构中。
我们的应用程序总会有一个GetMessage的调用,这个调用的目的就是从系统消
息队列中检索与调用进程有关的消息,这个GetMessage也在Windows源代码中
没有公开过,不过我们通过对它的观察可以猜到,它确实能够正确地把与调用
进程相关的消息取出来这点来看,可以肯定它能够识别出正确的消息,这也就
意味着它能够解释最原始的Windows消息,并且能够把无关的信息剔除,只填
充一个对应用程序有用的tagMSG回来。tagMSG如何工作,我想你已经理解了。
如果上面所说的与你的理解相同的话,那么我们再进一步看消息是怎么来的:
当你看到你按下按钮的时候,那个按钮一样的东西真的凹陷下去,你就以为这
个时候是这个按钮发送了消息的话,那么你就忽视了鼠标的存在。实质是鼠标
发生了点击动作,而按钮凹陷下去只是Windows给我们的一种视觉效果。
Windows只是把鼠标点击事件与按钮所在的实例进程等信息进行了一番妥善的
包装以后,生成一条最原始的、未公开结构的Windows内部消息,并把它放到
系统消息队列。一个应用程序正是利用Windows提供给我们的GetMessage函数
去取,才能取到正确的消息,任何自定义的函数好像都是不能完成这个工作的。
等到获得了tagMSG后,后面的工作大家都经常在利用也很容易理解,但我还是
要提醒你注意二个很重要的TranslateMessage和DispatchMessage,我不打算多
说这二个函数,只是希望你有空的时候也去考虑一下这二个函数:既然GetMessage
已经返回了消息,为什么还要这二个函数?按照字面理解,TranslateMessage
应该是对消息的转换和翻译,但我们不是已经知道有消息来了吗?而且我们从
返回的消息中也已经有了HWND,还要转化翻译什么呢?随后就是DispatchMessage,
按照字面理解,这里应该是把消息发送到处理这个消息的WndProc去。我没有
看到源代码,假设它们真的有事情要做的话,TranslateMessage就是寻找真正
的WndProc的地方。也就是说,只有通过TranslateMessage才真正找出处理这
个消息的WndProc,那,它能找到什么依据来认为找到的WndProc才是处理这
条消息的正确位置呢?答案应该是程序启动时在Windows中利用RegisterClass
函数登记的窗口类信息,这个信息中包含了最原始的WndProc。只有这样,后
面的DispatchMessage才不会把消息投错地方。
如果真的是这样的话,假如我们在利用RegisterClass注册了这个窗口类信息,并
利用CreateWindow(或者CreateWindowEx)创建了这个窗口后,我们又通过
某种手段把已经登记的窗口类中的WndProc改换成另外的指针的话,Windows
就会“错误”地把这个改变以后的指针当做“真”的指针(即原始WndProc),并
把消息投放进去。这种偷梁换柱的做法就是中途截获,也称钩子。
在理解这些东西的时候,应该不要涉及到Application,而用纯粹的Windows消
息体系去理解会比较方便些。如果李维没有在Inside vcl中没有说到这些内容,
我认为应该是正确的,因为这些内容应该仅仅属于Windows,而不属于VCL。
最后,我想,这个问题比较适合初学者,所以建议你是否能把这个帖子放到Delphi
基础那个板块去,以利于更多的初学者能够检索到。
============================================================================
小雨哥
文心雕龙
版主
发帖: 818
来自: 浙江杭州
于2006-01-17 03:45
--------------------------------------------------------------------------------
最后补充一下进入了Application后面的内容,这个内容前人已经做了大量探索,
其中比较优秀的一篇,是savetime发表在大富翁的文章:
http://www.delphibbs.com/delphibbs/dispq.asp?lid=2403549
学习VCL的话,这一篇一定要仔细读。