规范的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
);

转载于:https://www.cnblogs.com/hanny/p/7782935.html

C Builder中如何利用消息相关推荐

  1. 在C++Builder中可以利用FireMonkey的函数实现RGB与HSL之间的转换

    RGB转换为HSL的算法一般需要自己编写,但是在C++Builder中可以利用FireMonkey的函数实现RGB与HSL之间的转换. 下面是利用FireMonkey的RGBtoHSL和HSLtoRG ...

  2. ocx控件 postmessage消息会消失_通过HackerOne漏洞报告学习PostMessage漏洞实战场景中的利用与绕过...

    0x00 前言 这是一篇关于postMessage漏洞分析的文章,主要通过hackerone平台披露的Bug Bounty报告,学习和分析postMessage漏洞如何在真实的场景中得到利用的. 0x ...

  3. 消息队列中:消息可靠性、重复消息、消息积压、利用消息实现分布式事务

    点击下方"Java编程鸭"关注并标星 更多精彩 第一时间直达 一.如何确保消息不丢失? 1.检测消息丢失的方法 可以利用消息队列的有序性来验证是否有消息丢失.在Producer端给 ...

  4. 利用消息机制实现.NET AOP(面向方面编程)--基本概念和实现

    本系列文章主要讲述如何利用.NET的Remoting消息框架实现AOP 本系列文章试图实现三种AOP实现 本系列文章以示例代码为主,对一些概念和原理不会进行过于深入的讨论 这里不谈论AOP在现实开发中 ...

  5. 命令行参数在VB中的利用

    分享到 一键分享 QQ空间 新浪微博 百度云收藏 人人网 腾讯微博 百度相册 开心网 腾讯朋友 百度贴吧 豆瓣网 搜狐微博 百度新首页 QQ好友 和讯微博 更多... 百度分享 相册 广场 游戏 kf ...

  6. 在Scrapy中如何利用Xpath选择器从网页中采集目标数据——详细教程(下篇)

    点击上方"Python爬虫与数据挖掘",进行关注 回复"书籍"即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 二十四桥明月夜, 玉人何处教吹箫. ...

  7. 利用fputc函数写一个putw(w,fp)函数,将整数w写入fp所指文件中; 利用fgetc函数写一函数getw(fp)从所指文件读出一整数

    <程序设计基础-c语言>杨莉 刘鸿翔 ISBN-978-7-03-032903-5 p257 习题8 5.利用fputc函数写一个putw(w,fp)函数,将整数w写入fp所指文件中: 利 ...

  8. C#中的MessageBox消息对话框

    关键字:C# MessageBox 消息对话框 在程序中,我们经常使用消息对话框给用户一定的信息提示,如在操作过程中遇到错误或程序异常,经常会使用这种方式给用于以提示.在C#中,MessageBox消 ...

  9. java 2d划线 刷子_Java图形设计中,利用Bresenham算法实现直线线型,线宽的控制(NO2DGRAPHICS)...

    Java图形设计中,利用Bresenham算法实现直线线型,线宽的控制(NO2DGRAPHICS) (2007-04-05 23:37:39) Java 2D Graphics提供了强大的画线功能,可 ...

最新文章

  1. IOS开发之----异常处理
  2. 【转载】优秀文章转载集合
  3. virtio 网络的演化:原始virtio > vhost-net(内核态) > vhost-user(DPDK) > vDPA
  4. java学生奖学金管理系统_EasyUI+JavaWeb奖助学金管理系统[6]-登录功能实现
  5. 3.深度学习的实用层面
  6. 计算机等级考试网络工程师题库,计算机等级考试4级网络工程师习题库要点
  7. 论文阅读|《用强化学习求解带插单的动态FJSP》
  8. Wifi网络共享----Connectify 使用
  9. 不信谣,不传谣,不造谣
  10. J-Link 下载程序 接线图
  11. Linux 进行yum 安装是出现文件 conflicts 解决方法
  12. linux卸载veil,Kali Linux中的VEIL Framework绕过防病毒软件实验
  13. java使用pinyin4j实现汉字到拼音转换
  14. 北邮复试 | 北邮机试往年题汇总 | 计算机院 | 网研院 | 网安院 | 软院
  15. 手机音视频流媒体开发一些有用资料(2010.03.09更新)
  16. Pytorch训练模型损失Loss为Nan或者无穷大(INF)原因
  17. 随机数与随机序列生成
  18. 程序员专属的免费编程文本编辑器-----PSPad
  19. 国内高精地图哪家强?商业化落地的高德地图领先一步
  20. tcpdump 详细解读

热门文章

  1. mysql concat $_mysql concat 的诡异问题
  2. resnet152训练_Resnet-152的图像预处理
  3. python绘制图像的参数_图像绘制.draw.line():系统错误:新样式getargs格式,但参数不是tup...
  4. java可达性_java垃圾回收机制--可达性算法
  5. mysql存储过程触发器游标_MySQL存储过程,触发器,游标
  6. Python多线程下实现单例模式,以及limit实例模式
  7. LeetCode 1742. 盒子中小球的最大数量
  8. LeetCode 1379. 找出克隆二叉树中的相同节点(二叉树遍历)
  9. 程序员面试金典 - 面试题 16.02. 单词频率(哈希表/Trie树)
  10. 处理器指令编码可重定义的方法_从零开始设计四位栈处理器(2)——结构与指令集...