C Builderr中如何利用消息

规范的BCB过程利用Application->Run()进去消息循环,在Application的ProcessMessage措施中,利用PeekMessage措施从消息队列中提取消息,并将此消息从消息队列中移除。然后ProcessMessage措施察看是否存在Application->OnMessage措施。存在则转入此措施处理消息。尔后再将处理过的消息发放给过程中的各个对象。至此,WndProc措施收到消息,并举行处理。万一有无法处理的交给重载的Dispatch措施来处理。要是还不能处理的话,再交给父类的Dispatch措施处理。最后Dispatch措施切实上将消息转入DefaultHandler措施来处理。(嘿嘿,切实上,你一样能够重载DefaultHandler措施来处理消息,然而太晚了一点,我想未曾人甘心最后一个处理消息吧)。

1.TApplication的OnMessage事件的利用
在C++Builder开发的利用过程中,任何窗体接收到一个Windows消息都会引发顺次OnMessage事件,因而,能够穿越相应TApplication对象的OnMessage事件来捉拿任何发送给本过程的Windows消息。

OnMessage的事件的处理函数原型如下:
typedef void __fastcall (__closure *TMessageEvent ) (tagMsg &Msg,bool &Handled );
这个处理函数有两个参数,其中参数Msg表示的是被截获的消息,而参数Handled则用来指示本消息是否曾经处理告终。在过程中能够穿越设置参数Handled为true,以避免后续的过程处理这个消息,反之把Handled设为false则批准后继过程继续处理这个消息。
必需当心的是,OnMessage事件仅仅接受发送到消息队列的消息,而直接穿越API函数SendMessage()发送给窗口函数的消息将不会被截获。另外,当过程运行的时候,OnMessage事件被引发的频率有可能极其高,因而这个事件的处理函数代码厉行工夫将直接波及到全副过程的运行效率。

2.利用消息照射截获消息
C++Builder的VCL供给了对大多数Windows消息的处理机制,对于等闲的利用过程是足够了。然而,VCL也不是森罗万象的。有的情形下,过程必需处理那些VCL处理未曾处理的Windows消息,可能过程必需屏障某些特定的消息时,则就必需过程员自己捉拿Windows消息。
为此C++Builder供给了一种消息照射机制,穿越消息照射过程能将特定的Windows消息与对应的处理函数联系起来,当窗口捉拿到这个消息时就会积极调用对应的处理函数。
利用消息照射有一下几个环节:
(1) 消息照射表,把某些消息的处理权交给自定义的消息处理函数。
这么的消息照射列表该当位于一个组件类的定义中,它以一个未曾参数的BEGIN_MESSAGE_MAP 宏开始,以END_MESSAGE_MAP宏告终。END_MESSAGE_MAP宏的单一参数该当是组件的父类的名字。通常情形下,这个所谓的父类指的即便TForm。在宏BEGIN_MESSAGE_MAP和END_MESSAGE_MAP之间插入一个可能是多个MESSAGE_HANDLER 宏。
MESSAGE_HANDLER宏将一个消息句柄和一个消息处理函数联系在同时。
MESSAGE_HANDLER宏有三个参数:Windows消息名、消息构造体名和对应的消息处理函数名。其中,消息构造体名既能够是通用的消息构造体TMessage,也能够是特定的消息构造体,例如TWMMouse。
在利用消息照射的时候要当心以下两点:
a.一个窗口类定义中只能有一个消息照射表。
b.消息照射定然位于它所引用的所有消息处理函数声明的后面。
(2) 在窗口类中声明消息处理函数
这里的消息处理函数名和参数都定然和对应的MESSAGE_HANDLER宏统一。
一个标兵的消息处理函数的声明如下:
void __fastcall 消息处理函数名(消息构造体名 &Message);
例如:
void __fastcall WMNchitTest(TMessage &message);
(3) 告终消息处理函数
消息处理函数的编制和等闲的函数没什么太大的差异,单一不同的是,等闲在此函数的最后要加上一条语句 TForm::Dispatch(&Message),以告终VCL对于消息的默认处理。万一未曾这一句,消息将会被全面堵截;在某些情形下,VCL可能会因为得不到消息而无法工作。

3.重载WndProc()函数
在某些情形下,过程必需捉拿可能屏障某些特定的消息,这时能够用前面推荐的消息照射的措施。当然,这种措施也不是单一的,也能够穿越重载窗口函数WndProc()来告终。因为系统将在调用函数Dispatch()派发消息之前调用窗口函数WndProc(),因而,能够穿越重载函数WndProc()获得一个在分配消息之前过滤消息的时机。
这个消息处理的窗口函数的原型如下:
virtual void __fastcall WndProc(TMessage &Message);
例如:(翔实请看NowCane452.com的例子)
void __fastcall TForm1::WndProc(TMessage &Message)
{
PCOPYDATASTRUCT pMyCDS;
if(Message.Msg==g_MyMsg)
{
ShowMessage("收到登记消息,wParam="+IntToStr(Message.WParam)+" lParam="+IntToStr(Message.LParam));
Message.Result=0;//消息处理的收获,当然在本例中没故含义。
}
else if(Message.Msg==g_MyMsg1)
{
Application->MessageBoxA((char *)Message.LParam,"收到发送方的字符串",MB_OK);
}
else if(Message.Msg==WM_COPYDATA)
{
pMyCDS = (PCOPYDATASTRUCT)Message.LParam;
Application->MessageBoxA((char *)pMyCDS->lpData,"收到发送方的字符串",MB_OK);
}

TForm::WndProc(Message);//其他的消息继续递交下去
}
乍看起来,这和重载Dispatch措施好象差不多。但切实上还是有差异的。差异就在前后次序上,消息是先交给WndProc来处理,最后才调用Dispatch措施的。这么,重载WndProc措施能够比重载Dispatch措施更早一点点获得消息并处理消息。

4.Application->HookMainWindow措施
万一您计划利用Application->OnMessage来捉拿所有发送至您的利用过程的消息的话,您可能要绝望了。它无法捉拿利用SendMessage直接发送给窗口的消息,因为这不穿越消息队列。您可能会说我能够直接重载TApplication的WndProc措施。呵呵,不能够。因为TApplication的WndProc措施被Borland声明为静态的,从而无法重载。显而易见,这么做的起因很可能是Borland担心其所带来的副作用。那该如何是好呢?察看TApplication的WndProc的pascal源码能够看到:
procedure TApplication.WndProc(var Message: TMessage);
... // 节俭篇幅,这里与主题无关代码略去
begin
try
Message.Result := 0;
for I := 0 to FWindowHooks.Count - 1 do
if TWindowHook(FWindowHooks[I]^)(Message) then Exit;
... // 节俭篇幅,这里与主题无关代码略去
WndProc措施一开始先调用HookMainWindow挂钩的自定义消息处理措施,然后再调用缺省过程处理消息。这么利用HookMainWindow就能够在WndProc其中接加入自己的消息处理措施。利用这个措施响应SendMessage发送来的消息很管用。最后提醒一下,利用HookMainWindow挂钩尔后定然要对应的调用UnhookMainWindow卸载钩子过程。给个例子:

void __fastcall TForm1::FormCreate(TObject *Sender)
{
Application->HookMainWindow(AppHookFunc);
}
//---------------------------------------------------------------------------
bool __fastcall TForm1::AppHookFunc(TMessage &Message)
{
bool Handled ;
switch (Message.Msg)
{
case WM_CLOSE:
mrYes==MessageDlg(xg.sy-xghg.com"Really Close??", mtWarning, TMsgDlgButtons() << mbYes <
Handled = false : Handled = true ;
break;
}
return Handled;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormDestroy(TObject *Sender)
{
Application->UnhookMainWindow(AppHookFunc);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
SendMessage(Application->Handle,WM_CLOSE,0,0);
}
//---------------------------------------------------------------------------

5.自己发送消息
利用过程也能够像Windows系统一样在窗口可能是组件之间发送消息。C++Builder为此供给了几种门径:利用函数TControl::Perform()可能API函数SendMessage()和PostMessage()向特定的窗体发送消息,可能是利用函数TWinControl::Broadcast()和API函数BroadcastSystemMessage()广播消息。

Perform()函数的作用即便将指定的消息递交给TControl的WndProc过程,实用于所有由TControl类派生的对象,Perform()原型如下:
int __fastcall Perform(unsigned Msg, int WParam, int LParam);
要等到消息处理尔后才归来。

在统一个利用过程的不同学体和控件之间利用函数Perform()是极其方便的。然而这个函数是TControl类的成员函数。也即便说,利用它时,过程定然懂得这个接受消息的控件的实例。而在众多情形下过程并不懂得这个接受消息的窗体的实例而只是懂得这个窗体的句柄,例如,在不同利用过程的窗体之间发送消息就属于这种情形。这时,函数Perform()显明无法利用,取而代之的该当是函数SendMessage()和PostMessage()。

函数SendMessage()和PostMessage()的功能大约上一样,它们都能够用来向一个特定的窗口句柄发送消息。重要的差异是,函数SendMessage()直接把一个消息发送给窗口函数,等消息被处理尔后才归来;而函数PostMessage()则只是把消息发送到消息队列,然后就即刻归来。
这两个函数的原型声明离别如下:
LRESULT SendMessage(HWND hWnd,UINRT Msg,WPARAM,wParam,LPARAM,lParam);
BOOL PostMessage(HWND hWnd,UINT Msg,WPARAM,wParam,LPARAM,lParam);
能够看到,这两个函数参数同函数Perform()极其相仿,只是添置了一个hWnd参数用以表示目标窗口的句柄。

Broadcast()和BroadcastSystemMessage()
函数Broadcast()实用于所有由TWinControl类派生的对象,它能够向窗体上的所有子控件广播消息。其函数原型如下:
void __fastcall Broadcast(void *Message);
能够看到,这个函数只有一个Message参数,它指向被广播的TMessage种类的消息构造体。
函数Broadcast()只能向C++Builder利用过程中的指定窗体上的所有子控件广播消息,万一要向系统中其他利用过程可能窗体广播消息,函数Broadcast()就无能为力了。这时能够利用API函数BroadcastSystemMessage(),这个函数能够向任意的利用过程可能组件广播消息。其函数原型如下:
long BroadcastSystemMessage(
DWORD dwFlags,
LPWORD lpdwRecipients,
UINT uiMessage,
WPAREM wParam,
LPARAM lParam
);

时间: 2024-11-02 17:02:24

C Builderr中如何利用消息的相关文章

Delphi中多线程用消息实现VCL数据同步显示

Delphi中多线程用消息实现VCL数据同步显示 Lanno Ckeeke 2006-5-12 概述: delphi中严格区分主线程和子主线程,主线程负责GUI的更新,子线程负责数据运算,当数据运行完毕后,子线程可以向主线程式发送消息,以便通知其将VCL中的数据更新. 实现: 关键在于消息的发送及接收.在消息结构Tmessage中wParam和lParam类型为Longint,而指针类型也定义为Longint,可以通过此指针来传递自己所感兴趣的数据.如传递字符数组: 数组定义: const MA

Floodlight中 处理packetin消息的顺序(1)

当Controller和SW建立连接之后,就可以处理来自SW的各种OF msg.当接收到 packetin 消息之后,会将其分发给各个监听了这个OFMessage的listeners,所以如果我们要设计自己的控制器模块,只需要实现相应的接口方法,约定执行顺序即可.接口IListener 主要抽象了监听器模块的名字,执行顺序,接口IOFMessageListener则抽象了我们的Controller如何处理具体的这个openflow消息.这里通过阅读代码来判断这些模块处理packetin消息的相对

Android中的Handler消息机制

转自:http://blog.csdn.net/liuhe688/article/details/6407225 在分析Android消息机制之前,我们先来看一段代码: public class MainActivity extends Activity implements View.OnClickListener { private TextView stateText; private Button btn; @Override public void onCreate(Bundle

Win32编程中如何处理控制台消息

这篇文章讨论如何处理所有的控制台消息. 第一步,首先要安装一个事件钩子,也就是说要建立一个回调函数.调用Win32 API,原型如下: BOOL SetConsoleCtrlHandler(PHANDLER_ROUTINE HandlerRoutine, // 回调函数BOOL Add // 表示添加还是删除): 参数HandlerRoutine是一个指向函数的指针,原型如下: BOOL WINAPI HandlerRoutine(DWORD dwCtrlType // 控制事件类型): 所有的

ZeroMQ接口函数之 :zmq_msg_recv - 从一个socket中接受一个消息帧

ZeroMQ 官方地址 :http://api.zeromq.org/4-2:zmq_msg_recv zmq_msg_recv(3) ØMQ Manual - ØMQ/3.2.5 Name zmq_msg_recv - 从一个socket中接受一个消息帧 Synopsis int zmq_msg_recv (zmq_msg_t *msg, void *socket, int flags); Description zmq_msg_recv()函数和zmq_recvmsg(3)函数是完全相同的,

从源码中浅析Android中如何利用attrs和styles定义控件

一直有个问题就是,Android中是如何通过布局文件,就能实现控件效果的不同呢?比如在布局文件中,我设置了一个TextView,给它设置了textColor,它就能够改变这个TextView的文本的颜色.这是如何做到的呢?我们分3个部分来看这个问题1.attrs.xml  2.styles.xml  3.看组件的源码. 1.attrs.xml: 我们知道Android的源码中有attrs.xml这个文件,这个文件实际上定义了所有的控件的属性,就是我们在布局文件中设置的各类属性 你可以找到attr

JSP中如何利用JS实现登录页面的跳转(JSP中如何利用JS实现跳转页面)

JSP中如何利用JS实现登录页面的跳转(JSP中如何利用JS实现跳转页面) 注:只是用到js中的setTimeout();具体使用方法:  setTimeout(函数名, 时间(毫秒)); setTimeout( ) 是属于 window 的 method, 但我们都是略去 window 这顶层物件名称, 这是用来设定一个时间, 时间到了, 就会执行一个指定的 method.setTimeout( ) 通常是与 function一起用. 样例: 1 <%@ page language="j

crm组织服务中的xRM消息

Microsoft.Xrm.Sdk.Messages 命名空间支持用于处理任何实体中所存储的数据的核心消息.此命名空间还包含可用来检索和自定义实体.属性和关系的元数据的消息. 这些消息可与 IOrganizationService.Execute 方法一起使用.Microsoft.Xrm.Sdk.Messages 命名空间中可用的所有消息适用于所有三种部署类型. 请求页面指出消息在联机(连接到服务器)或脱机(与服务器断开连接)时是否能够正常工作 crm组织服务中的xRM消息,布布扣,bubuko

stata中xtivreg利用ivreg实现办法

Stata中计量方法的函数非常强大,但是强大的函数对于理解计量原理是不利的,因此能够将高层次函数化解为简单函数实现便于理解强大函数.对于工具变量的方法,由面板工具变量变为截面工具变量方法见下面的stata实现过程. mat Int=I(N*T) mat In=I(N) mat Jt=J(T,T,1) mat P=In#Jt mat Q=Int-P #生成转换矩阵,消除面板固定效应 mkmat Y,matrix(Y) mkmat z1 z2 z3 z4 z5 ...,matrix(Zmat) mk