请问:那位哪儿有关于自定义、使用(发送、接受)消息的例程?急需!万分感谢!!(200分)

  • 主题发起人 主题发起人 greenbamboo
  • 开始时间 开始时间
G

greenbamboo

Unregistered / Unconfirmed
GUEST, unregistred user!
&nbsp;可以把代码帖上来,也可以给我发信:fziq@163.net<br><br>&nbsp; 谢谢!!
 
自定义消息:=registmessage('自定义消息名称')<br>然后sendmessage( 自己的消息,自己的消息参数)<br>收消息就是用自定义的消息,通过过程判断是否是你的消息和参数!<br>
 
好多呵<br>你可以自己搜索下啦!<br><br>DELPHI中的消息处理机制<br><br>Delphi是Borland公司提供的一种全新的WINDOWS编程开发工具.由于它采用了具有弹性的和可重用的面向对象Pascal(object-oriented pascal)语言,并有强大的数据库引擎(BDE),快速的代码编译器,同时又提供了众多出色的构件.受到广大编程人员的青睐.在众多的编程语言(如VB,PowerBuilder,Powerpoint等)中脱颖而出.<br>其中一个DELPHI强于其他编程语言(如VB4.0)的地方就是在DELPHI中可自定义消息,并可直接处理消息.这对于那些希望编写自己的构件(Component),或者希望截获.过滤消息的用户来说是必不可少的.因为编写构件一般要对相应的消息进行处理.下面就对Delphi中消息处理机制进行一下介绍。<br><br>一.DELPHIVCL中消息的传递<br>Delphi中每一个VCL(Visual Component Library)构件(如Tbutton,Tedit等)都有一内在的消息处理机制,其基本点就是构件类接收到某些消息并把它们发送给适当的处理方法,如果没有特定的处理方法,则调用缺省的消息处理句柄。<br><br>其中mainwndproc是定义在Twincontrol类中的一个静态方法,不能被重载(Override)。它不直接处理消息,而是交由wndproc方法处理,并为wndproc方法提供一个异常处理模块。Mainwndproc方法声明如下:<br>procedure MainWndProc(var Message: TMessage);<br><br>Wndproc是在Tcontrol类中定义的一个虚拟方法,由它调用dispatch方法来进行消息的分配,wndproc方法声明如下:<br><br>procedure WndProc(var Message: TMessage); virtual;<br><br>dispatch方法是在Tobject根类中定义的,其声明如下:<br><br>procedure Tobject.dispatch(var Message);传递给dispatch的消息参数必须是一个记录类型,且这个记录中第一个入点必须是一个cardinal类型的域(field),它包含了要分配的消息的消息号码.例如:<br><br>type<br>Tmessage=record<br>&nbsp; Msg:cardinal;<br>&nbsp; wparam:word;<br>&nbsp; lparam:longint; .<br>&nbsp; result:longint;<br>end;<br>而Dispatch方法会根据消息号码调用构件的最后代类中处理此消息的句柄方法.如果此构件和它的祖先类中都没有对应此消息的处理句柄,Dispatch方法便会调用Defaulthandler方法.Defaulthandler方法是定义于Tobject中的虚拟方法,其声明如下:<br>procedure Defaulthandler(var Message);virtual;<br><br>Tobject类中的Defaulthandler方法只是实现简单的返回而不对消息进行任何的处理.我们可以通过对此虚拟方法的重载,在子类中实现对消息的缺省处理.对于VCL中的构件而言,其Defaulthandler方法会启动windowsAPI函数Defwindowproc对消息进行处理.<br><br>二.DELPHI中的消息处理句柄<br>在DELPHI中用户可以自定义消息及消息处理句柄.消息处理句柄的定义有如下几个原则:<br>消息处理句柄方法必须是一个过程,且只能传递一个Tmessage型变量参数.<br>方法声明后要有一个message命令,后接一个在0到32767之间的消息标号(整型常数).<br>消息处理句柄方法不需要用override命令来显式指明重载祖先的一个消息处理句柄,另外它一般声明在构件的protected或private区.<br>在消息处理句柄中一般先是用户自己对消息的处理,最后用inherited命令调用祖先类中对应此消息的处理句柄(有些情况下可能正相反).由于可能对祖先类中对此消息的处理句柄的名字和参数类型不清楚,而调用命令inherited可以避免此麻烦,同样如果祖先类中没有对应此消息的处理句柄,inherited就会自动调用Defaulthandler方法.(当然如果要屏蔽掉此消息,就不用inherited命令了)。<br><br>消息处理句柄方法声明为:<br>procedure Mymsgmethod(var message:Tmessage); message Msgtype;<br><br>同样用户也可以定义自己的消息,用户自定义消息应从WM_USER开始.<br><br>自定义消息及消息处理句柄举例如下:<br><br>const my_paint=Wm_user+1;<br><br>type<br>Tmypaint=record<br>&nbsp; msgid:cardinal;<br>&nbsp; msize:word;<br>&nbsp; mcolor:longint;<br>&nbsp; msgresult:longint;<br>end;<br>type<br>Tmycontrol=class(TCustomControl)<br>protected<br>&nbsp; procedure change(var message:Tmypaint); message my_paint;<br>.....<br>end;<br>......<br>procedure Tmycontrol.change(var message:Tmypaint);<br>begin<br>&nbsp; size:=message.msize;{设置Tmybutton尺寸属性}<br>&nbsp; color:=message.mcolor;{设置Tmybutton颜色属性}<br>&nbsp; {do something else}<br>&nbsp; inherited; { 交 由Tcustomcontrol 处 理}<br>end;<br><br><br>三.过滤消息<br><br>过滤消息又称消息陷阱。在一定情况下,用户可能需要屏蔽某些消息.或者截获某些消息进行处理。由以上介绍可以看出过滤消息一般有三种途径:(1).重载构件继承的虚拟方法wndproc.(2).针对某<br>消息编写消息处理句柄.(3).重载构件继承的虚拟方法Defhandler,在其中对消息进行处理。其中常用的方法是方法(2),在上节中已介绍过了,方法(1)与方法(3)相似,这里只简单介绍一下方法(1)。<br><br>重 载 虚 拟 方 法wndproc 的 一 般 过 程 如 下:<br><br>procedure Tmyobject.wndproc(var message:Tmessage);<br>begin<br>{...判断此消息是否该处理..}<br>inheritedwndproc(message);<br>{未处理的消息交由父辈wndproc方法处理}<br>end;<br><br>由此可以看出在wndproc方法中处理消息的优势是可以过滤整个范围内的消息,而不必为每个消息指定一个处理句柄,事实上Tcontrol构件中就是利用它来过滤并处理所有的鼠标消息的(从WM_mousefirst到WM_mouselast,如下代码示).同样利用它也可以阻止某些消息被发送给处理句柄。<br><br>procedure TControl.WndProc(var Message: TMessage);<br>begin<br>&nbsp; if (Message.Msg&gt;=WM_MOUSEFIRST) and (Message.Msg &lt;= WM_MOUSELAST) then<br>&nbsp; &nbsp; if Dragging then{处理拖曳事件}<br>&nbsp; &nbsp; &nbsp; DragMouseMsg(TWMMouse(Message))<br>&nbsp; &nbsp; else<br>&nbsp; &nbsp; &nbsp; ...{处理其他鼠标消息}<br>&nbsp; end;<br>&nbsp; Dispatch(Message);<br>&nbsp; {否则正常发送消息}<br>end;<br><br>下例为一简单的自定义构件例子:<br><br>Tmyedit类是从Tedit类派生出的一个新类,它的特点是在运行中不能获得焦点,不能由键盘输入(有点类似Tlabel构件).我们可在其wndproc方法中过滤出WM_setfocus,WM_mousemove消息并进行处理来达到上述<br>要求,源程序如下:<br><br>unit myedit;<br><br>interface<br><br>uses<br>Windows, Messages, SysUtils, Classes, Graphics,Controls, Forms, Dialogs,<br><br>StdCtrls;<br><br>type<br><br>Tmyedit = class(TEdit)<br>private<br>{ Private declarations }<br>protected<br>{ Protected declarations }<br>{ other fields and methods}<br>procedure wndproc(var message:Tmessage);override;<br>public<br>{ Public declarations }<br>published<br>{ Published declarations }<br>end;<br><br>procedure Register;<br><br>implementation<br><br>procedure Register;<br>begin<br>&nbsp; RegisterComponents('Samples', [Tmyedit]);<br>end;<br>procedure Tmyedit.wndproc(var message:tmessage);<br>begin<br>&nbsp; if message.msg=wm_mousemove then<br>&nbsp; begin<br>&nbsp; &nbsp; cursor:=crarrow;<br>&nbsp; &nbsp; {设置光标为crarrow,而不是缺省的crBeam光标}<br>&nbsp; &nbsp; exit;<br>&nbsp; end;<br>&nbsp; if message.msg=wm_SetFocus then<br>&nbsp; &nbsp; exit;<br>&nbsp; {屏蔽掉WM_setfocus消息,不让Tmyedit控件获得输入焦点}<br>&nbsp; inherited wndproc(message);<br>&nbsp; {其他消息交父辈wndproc处理}<br>end;<br>end.<br><br>您可以将Tmyedit加到Component Palette中检验其性能。<br>由以上介绍可以看出,只有清楚了Delphi VCL中的消息处理机制,掌握好处理各种消息的方法和时机(必要时要借助各种工具,如winsight32,spy等),并结合OOP语言的特点,我们才可能编出高质量的构件。这当然要靠读者在实践中不断摸索,积累经验。<br>
 
哦,还忘了说了,在接收你自定义的消息的时候是在程序窗体中的回调函数中判断啊!<br>一定是回调函数中啊![8D]
 
谢谢!<br>&nbsp; &nbsp;其实,我想在两个VCl之间想通过互发消息来进行数据传递,当然了这个消息要包含<br>一定的数据信息。<br>&nbsp; &nbsp; 通过执行第一个控件一个动作,发一个消息,而第二个控件有随时<br>监收消息的功能。<br>&nbsp; &nbsp; 通过对消息的判断,是否是自己应该接受的消息(数据),<br>如果是,则执行相应的动作。<br><br>&nbsp; &nbsp; &nbsp; &nbsp;我的大致目的是这样的,不只各位有无什么对策。<br>不妨贴出来,以供小弟学习、参考和更好的解决此问题。谢谢!!<br>&nbsp;
 
谢谢!谢谢楼上的两位,我看看先。
 
re:vine<br>&nbsp; &nbsp;谢谢,我一看过你的文章的。<br>&nbsp; &nbsp;对于自己编写的控件可以接受并处理消息(不过我还没的及试验),但用现成Vcl呢?<br>&nbsp; 就像我要往在窗体上的panel发一个改变panel-&gt;caption的一个消息,对于panel来说,<br>&nbsp; 他应该怎样接受并处理这个消息呢?<br>&nbsp; <br>&nbsp; &nbsp;
 
在自定義控件中,若控件本身沒有窗口句柄,(例如繼承自TComponent).<br>但是又需要處理Windows消息(含自定義消息),這時需要給它分配一個句柄來接受消息.<br>舉例如下:<br><br>Interface<br>uses<br>&nbsp; Windows,Classes,Messages;<br>const <br>&nbsp; WM_MyMsg=WM_User+100;<br>type<br>&nbsp; TMyHwndComponent=Class(TComponent)<br>&nbsp; private<br>&nbsp; &nbsp; FHandle:Hwnd; &nbsp; //句柄<br>&nbsp; &nbsp; ...<br>&nbsp; &nbsp; procedure WndProc(var Message:TMessage);<br>&nbsp; public<br>&nbsp; &nbsp; constructor Create(Owner:TComponent);override;<br>&nbsp; &nbsp; Destructor Destroy;override;<br>&nbsp; &nbsp; property Handle:Hwnd read FHandle;<br>&nbsp; end;<br><br>implementation<br><br>procedure TMyHwndComponent.Create(Owner:TComponent);<br>begin<br>&nbsp; Inherited Create(Owner);<br>&nbsp; FHanlde:=AllocateHwnd(WndProc); &nbsp; //創建窗口句柄,所有的消息將進入WndProc處理程序.<br>&nbsp; ...<br>end;<br><br>Procedure TMyHwndComponent.Destroy;<br>begin<br>&nbsp; DeallocateHwnd(FHandle); &nbsp;//銷毀句柄<br>&nbsp; Inherited Destroy;<br>end;<br><br>procedure TMyHwndComponent.WndProc(Message:TMessage);<br>begin<br>&nbsp; //在這里對消息進行處理.<br>&nbsp; if Message.Msg=WM_MyMsg then &nbsp;//這個為自定義消息.<br>&nbsp; begin<br>&nbsp; &nbsp; ...<br>&nbsp; end else &nbsp; //調用默認處理.<br>&nbsp; &nbsp; Message.Result:=DefWindowProc(FHandle,Message.Msg,Message.WParam,Message.LParam); &nbsp;<br>end;<br><br>end.<br>&nbsp; &nbsp;
 
另外,發送自定義消如下:<br><br>var<br>&nbsp; Obj:TMyMsgComponent;<br><br>procedure TForm1.FormCreate(Sender:TObject);<br>begin<br>&nbsp; Obj:=TMyMsgComponent.Create(nil);<br>end;<br><br>procedure TForm1.FormDestroy(Sender:TObject);<br>begin<br>&nbsp; Obj.Free;<br>end;<br><br>procedure TForm1.Button1Click(Sender:TObject);<br>begin<br>&nbsp; SendMessage(Obj.Handle,WM_MyMsg,Button1.Handle,0);<br>//四個參數,第一個參數指向目標的窗口句柄,<br>//第二個參數為消息代號,用以區分是什麼類型的消息.<br>//第三,四個參數為兩個整型參數,可以為某個對象的指針,也可以為某個數據結構的指針,<br>// &nbsp; &nbsp; 對於自定義消息而言,這兩個參數可以自己靈活運用.<br>end;
 
接受答案了.
 
后退
顶部