关于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;
函数!
http://www.cnblogs.com/DxSoft/archive/2011/09/27/2192795.html
关于Delphi XE2的FMX的一点点研究之消息篇的更多相关文章
- Delphi XE2 新控件 布局Panel TGridPanel TFlowPanel
Delphi XE2 新控件 Firemonkey 布局Panel Windows平台VCl TGridPanel TFlowPanel FMX 跨平台 TLayout TGridLayout TFl ...
- Delphi XE2 之 FireMonkey 入门(45Finally) - 结题与问题
Delphi XE2 之 FireMonkey 入门(45Finally) - 结题与问题 很喜欢 FMX 的一些新控件, 如: TExpander.TArcDial.TComboTrackBar.T ...
- Delphi XE2 之 FireMonkey 入门(44) - 控件基础: TTreeView、TTreeViewItem
Delphi XE2 之 FireMonkey 入门(44) - 控件基础: TTreeView.TTreeViewItem TScrollBox -> TCustomTreeView -> ...
- Delphi XE2 之 FireMonkey 入门(39) - 控件基础: TScrollBox、TVertScrollBox、TFramedScrollBox、TFramedVertScrollBox
Delphi XE2 之 FireMonkey 入门(39) - 控件基础: TScrollBox.TVertScrollBox.TFramedScrollBox.TFramedVertScrollB ...
- Delphi XE2 之 FireMonkey 入门(38) - 控件基础: TPopupMenu、TMenuItem、TMenuBar、TMainMenu
Delphi XE2 之 FireMonkey 入门(38) - 控件基础: TPopupMenu.TMenuItem.TMenuBar.TMainMenu 相关控件: TMenuBar.TPopup ...
- Delphi XE2 之 FireMonkey 入门(36) - 控件基础: TForm
Delphi XE2 之 FireMonkey 入门(36) - 控件基础: TForm 当我第一次读取 Form1.StyleLookup 并期待出现 "formstyle" 时 ...
- Delphi XE2 之 FireMonkey 入门(33) - 控件基础: TFmxObject: SaveToStream、LoadFromStream、SaveToBinStream、LoadFromBinStream
Delphi XE2 之 FireMonkey 入门(33) - 控件基础: TFmxObject: SaveToStream.LoadFromStream.SaveToBinStream.LoadF ...
- Delphi XE2 之 FireMonkey 入门(31) - 数据绑定: 绑定数据库
Delphi XE2 之 FireMonkey 入门(31) - 数据绑定: 绑定数据库 一.全设计时操作: 先在窗体上放置控件: DataSource1 : TDataSource; Clie ...
- Delphi XE2 之 FireMonkey 入门(30) - 数据绑定: TBindingsList: TBindExpression 的 OnAssigningValue 事件
Delphi XE2 之 FireMonkey 入门(30) - 数据绑定: TBindingsList: TBindExpression 的 OnAssigningValue 事件 表达式中的函数有 ...
随机推荐
- 多个线程怎样操作同一个epoll fd
自己曾经做一个接口server时候,这样的场景下我的设计是多个线程操作同一个epoll fd.彼时,我的理由是epoll的系列函数是线程安全的. 当然有人不理解为什么会有多个线程操作同一个epoll ...
- 【转】C++类-内存分布
C++类内存分布 - 转载自Jerry19880126 - 博客园 的文章 在上面这篇文章的基础上做了些整理. 主要讨论了C++类对象的内存分布结构. 来看看编译器是怎么处理类成员内存分布的,特别是在 ...
- 解决打包时IsCmdBld.exe出错的问题
1.查看环境变量是否配置了 2.查看是否是使用administrator登陆的,要求使用administrator登陆否则可能会出现权限不足的现象
- LVS--什么是LVS?
1.什么是LVS? 首先简单介绍一下LVS (Linux Virtual Server)到底是什么东西,其实它是一种集群(Cluster)技术,采用IP负载均衡技术和基于内容请求分发技术.调度器具有很 ...
- Qt信号槽的一些事(第一次知道信号还有返回值,以及Qt::UniqueConnection)
注:此文是站在Qt5的角度说的,对于Qt4部分是不适用的. 1.先说Qt信号槽的几种连接方式和执行方式. 1)Qt信号槽给出了五种连接方式: Qt::AutoConnection 0 自动连接:默认的 ...
- Qt核心剖析:信息隐藏(三篇)
http://devbean.blog.51cto.com/448512/335550 http://devbean.blog.51cto.com/448512/325581 http://devbe ...
- C# MVC 自学笔记—5 添加模型
==============================翻译============================== 在本节中,您将添加一些类来管理数据库中的电影.这些类将 ASP.NET M ...
- Tomcat与web程序结构与Http协议
telnet 一:打开telnet服务: 控制面板------> 程序和功能---> 打开或关闭windows功能---> 选中 Telnet客户端--->确定 二:测试tel ...
- 手游接入Facebook的那些坑
之前工作须要在手游中接入了facebook,并以此写了<手游接入Facebook功能>的博文.当时facebook sdk的版本号还是3.x.代码集成度比較低.集成起来也比較麻烦.文中仅仅 ...
- Libgdx环境搭建及介绍
Libgdx简单介绍: libgdx是一个跨平台的2D/3D的游戏开发框架,它由Java/C/C++语言编写而成.ibgdx兼容大多数微机平台(标准JavaSE实现,能执行在Mac.Linux.Win ...