关于Delphi XE2的FMX的一点点研究之消息篇 - 不得闲 - 博客园

2024-02-14 07:08

本文主要是介绍关于Delphi XE2的FMX的一点点研究之消息篇 - 不得闲 - 博客园,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


常用链接我的标签

关注站点

积分与排名最新评论阅读排行榜评论排行榜

   Delphi XE2出来了一阵子了,里面比较抢眼的东西,除了VCLStyle这个换肤的东西之外,另外最让人眼亮的应该是FMX这个东西了。万一的博客上都连载了一票的关于FMX的使用心得了。我还是没咋去关注,因为技术这个东西,天天在变,跟着他跑,俺伤不起啊!直到今天,看了一下盒子,然后群中也有人说关于FMX在Windows下面如何来发送消息的问题,说发送不了。实际上,FMX这个东西是一套跨平台机制的GUI类库,消息这个东西只是Windows下面的,所以发送消息这个说法应该不算通用。不过加以研究应该可以让Windows,Linux的综合到一个能通用的库中。

   随便创建一个FMX的应用程序,上面放几个按钮什么的,然后我们跟踪一下,先看看Application这个东西,可以找到他的实现在FMX.Forms单元中,他和VCL的Application的实现不是一个东西了地。发送消息,那么首先我们应该想到几个常用的函数ProcessMessages,HandleMessage,跟进去看就直到了,然后可以发现HandleMessage的实现

function TApplication.HandleMessage: Boolean;
begin
Result := Platform.HandleMessage;
if not Result then
Idle;
end;

里面有一个Platform的玩意,很显然这个应该是运行时期根据不同的系统平台调用不同的实现机制,俺们是Windows平台,所以跑到他的源码目录看一下,可以发现一个很明显的名称FMX.Platform.Win,对咯,就在这个实现中了。看看TPlatformWin这个玩意的实现,我想如果熟悉Win32编程的,这个应该很明了了。不再多说,然后咱们看窗体的创建找到FMX.Forms中的CreateHandle这个东西,和上面的HandleMessage差不多的一个实现

procedure TCommonCustomForm.CreateHandle;
begin
FHandle := Platform.CreateWindow(Self);
if TFmxFormState.fsRecreating in FormState then
Platform.SetWindowRect(Self, RectF(Left, Top, Left + Width, Top + Height));
end;

都与platform这个平台相关了。不过话说,FMX的这个封装结构是相当的合理的,看代码让人能够一目了然,不说废话,再去看TPlatformWin的CreateWindow的实现。这个的实现和咱们VCL的实现差不多,然后我们最主要的是看看他的最后面有一个

Result := NewFmxHandle;

FHWndMap.Add(Result, Wnd);这样的实现,也就是说CreateHandle之后返回的并不是创建的窗体句柄,而是FMX管理的一个句柄索引。所以这下,咱们可直到了,FMX的Form的Handle不是这个窗口句柄而是FMX自己管理的一个索引。至于要如何获得窗口的真实句柄,在FMX.Platform.Win的最开头提供了一个函数,可实现。function FmxHandleToHWND(FmxHandle: TFmxHandle): HWND;就是这个,这个就可通过这个索引获得真实的Win32的窗口句柄。这些都说完了,那么下面我们就可以开始考究,FMX的这个消息机制了,首先发挥我们的大脑想一想,在Windows下,你所做的任何事情都要通过消息来传递的。所以说FMX这个肯定还是有消息流通的,这个是必须的。但是好多人却说,FMX的消息发送不了,为啥,呵呵这个最主要的,我前面已经说了,首先这个Win32的句柄,你换出来了没得,换出来了的话,那么你这个消息肯定是发送成功了的,否则,肯定失败了。然后我们看看最简单的一个鼠标单击消息,鼠标点窗体上的按钮会触发单击事件,那么这个按钮的鼠标消息是怎么流通的,我们先找Button的基类,一直跟下去,可以发现FMX的Control都是他自身的一套实现方式,但是没见到Win32的消息封装函数,此时俺们在发挥大脑思考一下,FMX的控件从上到下都没有再通过Win32来创建的标准方法,而且FMX的控件都没有句柄,那么我们就应该可以想到了,FMX的一整套控件的消息都是通过他的父Form来作为媒介进行传递转换而实现的,所以我们直接找到FMX的Form实现中的MouseDown过程,可以看到他的实现方式

procedure TCommonCustomForm.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Single);
var
P: TPointF;
R: TRectF;
Obj: IControl;
SG: ISizeGrip;
i: Integer;
begin
{ translate coord }
FMousePos := PointF(X, Y);
FDownPos := FMousePos;
{ event }
Obj := IControl(ObjectAtPoint(ClientToScreen(FMousePos)));
if (Obj <> nil) then
begin
if (IInterface(Obj).QueryInterface(ISizeGrip, SG) = 0) then
StartWindowResize
else
begin
P := Obj.ScreenToLocal(ClientToScreen(PointF(FMousePos.X, FMousePos.Y)));
Obj.MouseDown(Button, Shift, P.X, P.Y);
if (Obj.DragMode = TDragMode.dmAutomatic) then
Obj.BeginAutoDrag;
end;
end;
end;

很明确他会获得鼠标按下的位置的FMX控件,然后如果获得了这个控件就调用控件的MouseDown方法,所以到这里,应该就可以很明了的知道FMX的消息是通过Form作为媒介来传递的了,那么由此说来,我们只要通过Form来转我们的消息就可以实现消息的发送了,那么这样,我们先通过消息来触发一个Button的OnClick事件。放2个按钮,然后发送消息给窗体,发送一个Down消息然后发送一个Up消息,这就构成了一个单击事件

SendMessage(FmxHandleToHWND(Handle),WM_LBUttonDown,MK_LBUTTON,MakeLong(trunc(Button1.Position.X + 3),trunc(Button1.Position.Y + 3)));
SendMessage(FmxHandleToHWND(Handle),WM_LBUttonUP,MK_LBUTTON,MakeLong(trunc(Button1.Position.X + 3),trunc(Button1.Position.Y + 3)));

然后触发一下,俺们会发现貌似并没有触发这个OnClick事件,莫非猜测失败?然后我们在找找,找到Controls的MouseUp过程

procedure TControl.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Single);
begin
ReleaseCapture;
if Assigned(FOnMouseUp) then
FOnMouseUp(Self, Button, Shift, X, Y);
if FPressed and not(FDoubleClick) and PointInRect(PointF(X, Y), LocalRect) then
begin
FPressed := False;
Click;
end;
FPressed := False;
FDoubleClick := False;
end;

里面有一个判断PointInRect(PointF(X, Y), LocalRect),可以知道是这个东西限制了只有光标在鼠标控件位置的时候才会触发OnClick事件咯。这下,可以想一个办法,用一个Timer控件在Timer的OnTimer中加上上面的消息发送代码,然后运行将鼠标移动到按钮上,等一会就会触发Button的OnClick事件了。

我想到这里,大家应该都知道如何给FMX发送消息了把!总归一句话,模拟!

FMX的消息处理过程在FMX.Platform.Win中的

function WndProc(hwnd: HWND; uMsg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;

函数!




FeedBack:



引文来源   关于Delphi XE2的FMX的一点点研究之消息篇 - 不得闲 - 博客园

这篇关于关于Delphi XE2的FMX的一点点研究之消息篇 - 不得闲 - 博客园的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/707837

相关文章

ActiveMQ—消息特性(延迟和定时消息投递)

ActiveMQ消息特性:延迟和定时消息投递(Delay and Schedule Message Delivery) 转自:http://blog.csdn.net/kimmking/article/details/8443872 有时候我们不希望消息马上被broker投递出去,而是想要消息60秒以后发给消费者,或者我们想让消息没隔一定时间投递一次,一共投递指定的次数。。。 类似

一种改进的red5集群方案的应用、基于Red5服务器集群负载均衡调度算法研究

转自: 一种改进的red5集群方案的应用: http://wenku.baidu.com/link?url=jYQ1wNwHVBqJ-5XCYq0PRligp6Y5q6BYXyISUsF56My8DP8dc9CZ4pZvpPz1abxJn8fojMrL0IyfmMHStpvkotqC1RWlRMGnzVL1X4IPOa_  基于Red5服务器集群负载均衡调度算法研究 http://ww

生信圆桌x生信分析平台:助力生物信息学研究的综合工具

介绍 少走弯路,高效分析;了解生信云,访问 【生信圆桌x生信专用云服务器】 : www.tebteb.cc 生物信息学的迅速发展催生了众多生信分析平台,这些平台通过集成各种生物信息学工具和算法,极大地简化了数据处理和分析流程,使研究人员能够更高效地从海量生物数据中提取有价值的信息。这些平台通常具备友好的用户界面和强大的计算能力,支持不同类型的生物数据分析,如基因组、转录组、蛋白质组等。

开题报告中的研究方法设计:AI能帮你做什么?

AIPaperGPT,论文写作神器~ https://www.aipapergpt.com/ 大家都准备开题报告了吗?研究方法部分是不是已经让你头疼到抓狂? 别急,这可是大多数人都会遇到的难题!尤其是研究方法设计这一块,选定性还是定量,怎么搞才能符合老师的要求? 每次到这儿,头脑一片空白。 好消息是,现在AI工具火得一塌糊涂,比如ChatGPT,居然能帮你在研究方法这块儿上出点主意。是不

研究人员在RSA大会上演示利用恶意JPEG图片入侵企业内网

安全研究人员Marcus Murray在正在旧金山举行的RSA大会上公布了一种利用恶意JPEG图片入侵企业网络内部Windows服务器的新方法。  攻击流程及漏洞分析 最近,安全专家兼渗透测试员Marcus Murray发现了一种利用恶意JPEG图片来攻击Windows服务器的新方法,利用该方法还可以在目标网络中进行特权提升。几天前,在旧金山举行的RSA大会上,该Marcus现场展示了攻击流程,

Science Robotics 首尔国立大学研究团队推出BBEX外骨骼,实现多维力量支持!

重复性举起物体可能会对脊柱和背部肌肉造成损伤,由此引发的腰椎损伤是工业环境等工作场所中一个普遍且令人关注的问题。为了减轻这类伤害,有研究人员已经研发出在举起任务中为工人提供辅助的背部支撑装置。然而,现有的这类装置通常无法在非对称性的举重过程中提供多维度的力量支持。此外,针对整个人体脊柱的设备安全性验证也一直是一个缺失的环节。 据探索前沿科技边界,传递前沿科技成果的X-robot投稿,来自首尔国立

Java消息队列:RabbitMQ与Kafka的集成与应用

Java消息队列:RabbitMQ与Kafka的集成与应用 大家好,我是微赚淘客返利系统3.0的小编,是个冬天不穿秋裤,天冷也要风度的程序猿! 在现代的分布式系统中,消息队列是实现系统间通信、解耦和提高可扩展性的重要组件。RabbitMQ和Kafka是两个广泛使用的消息队列系统,它们各有特点和优势。本文将介绍如何在Java应用中集成RabbitMQ和Kafka,并展示它们的应用场景。 消息队

Kafka 分布式消息系统详细介绍

Kafka 分布式消息系统 一、Kafka 概述1.1 Kafka 定义1.2 Kafka 设计目标1.3 Kafka 特点 二、Kafka 架构设计2.1 基本架构2.2 Topic 和 Partition2.3 消费者和消费者组2.4 Replica 副本 三、Kafka 分布式集群搭建3.1 下载解压3.1.1 上传解压 3.2 修改 Kafka 配置文件3.2.1 修改zookeep

Android 友盟消息推送集成遇到的问题

友盟消息推送遇到的问题 集成友盟消息推送,步骤根据提供的技术文档接入便可。可是当你集成到项目中去的时候,可能并不是一帆风顺就搞定,因为你项目里面是可能集成了其他的sdk(比如支付宝,微信,七鱼等等三方的sdk)。那么这个时候,再加上友盟的消息推送sdk集成可能就会出现问题。 问题清单 友盟消息推送sdk和支付宝sdk冲突问题 后台配置了消息推送,也显示发送成功,但是手机没有收到消息通知

代码随想录训练营day37|52. 携带研究材料,518.零钱兑换II,377. 组合总和 Ⅳ,70. 爬楼梯

52. 携带研究材料 这是一个完全背包问题,就是每个物品可以无限放。 在一维滚动数组的时候规定了遍历顺序是要从后往前的,就是因为不能多次放物体。 所以这里能多次放物体只需要把遍历顺序改改就好了 # include<iostream># include<vector>using namespace std;int main(){int n,m;cin>>n>>m;std::vector<i