http://delphi.about.com/od/windowsshellapi/a/receive-windows-messages-in-custom-delphi-class-nonwindowed-control.htm

Windows messages are a key ingredient in communication
between Windows and (your) applications and also in communication between (two) applications.

Even "without your knowledge" Windows messages are being posted and handled by forms in your application.

For example, when the user closes the form in your application,

the WM_CLOSE message is sent to the window/form and the form gets closed (if you do not react programmatically).

For an application to receive a Window message, the application must provide a "window" a message will be sent to.

In normal situation this window is the (main) form in your application.

You write a procedure to handle a specific message, like WM_NCHitTest, and you are done.

BUT, what is you do NOT have a window to receive a message?

What if you want to handle messages in your custom class derived from TObject?

Handle Windows Messages in TMyObject = class(TObject)

A Delphi control that has a window handle (derives from TWinControl) can receive Windows messages.

The TObject does not expose a window handle, and therefore any of your custom classes (deriving from TObject)

cannot receive and handle Windows messages, at least not "by default".

To enable your custom class to receive Windows messages you must provide a window handle to the message sender.

The trick is in using the following methods (defined in classes.pas - therefore straightforward to use):

  • AllocateHWnd(WndMethod : TWndMethod). AllocateHWnd is used to create a window that is not associated with a windowed control.
  • The WndMethod : TWndMethod specifies the window procedure that the generated window uses to respond to messages.
  • DeallocateHWnd. DeallocateHWnd destroys window that was created using the AllocateHWnd function.
// The TMsgReceiver skeleton below is a custom class derived from TObject capable of receiving and handling Windows messages.

interface 

TMsgReceiver =  class(TObject)
private
fMsgHandlerHWND : HWND;
procedure WndMethod( var Msg: TMessage);
public
constructor Create;
destructor Destroy; override;
end; implementation constructor TMsgReceiver.Create;
begin
inherited Create; fMsgHandlerHWND := AllocateHWnd(WndMethod);
end; destructor TMsgReceiver.Destroy;
begin
DeallocateHWnd(fMsgHandlerHWND);
inherited;
end; procedure TMsgReceiver.WndMethod(var Msg: TMessage);
begin
if Msg.Msg = WM_MY_UNIQUE_MESSAGE then
begin
//do something
end
else
Msg.Result := DefWindowProc(fMsgHandlerHWND, Msg.Msg, Msg.wParam, Msg.lParam);
end;

In the WndMethod procedure (the window procedure for the hidden window) you handle all the messages you are interested in.

For all other mesages a call to DefWindowProc is needed to ensure default processing for any messages that your code does not process.

Handle a Message From Another Application

With the above skeleton, you can now handle messages sent from other applications.

Suppose some application registers Windows message using RegisterWindowMessage API call.

The RegisterWindowMessage function is typically used to register messages for communicating between two cooperating applications.

The "sending" application would have a line like:

WM_MY_APP_MESSAGE := RegisterWindowMessage('MSG_MY_APP_MESSAGE');

Where WM_MY_APP_MESSAGE is a cardinal value field used when posting the message to (all) windows.

Let's say we post this message in a form's OnMouseDown event:

procedure TClickSendForm.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
PostMessage(HWND_BROADCAST, WM_MY_APP_MESSAGE, x, y);
end;

The HWND_BROADCAST parameter ensures that our WM_MY_APP_MESSAGE is posted to all top-level windows in the system,

including disabled or invisible unowned windows, overlapped windows, and pop-up windows AND our TMsgReceiver hidden window.

To handle the message in the TMsgReceiver instance have the WndMethod as:

procedure TMsgReceiver.WndMethod( var Msg: TMessage);
begin
if Msg.Msg = WM_MY_UNIQUE_MESSAGE then
begin
Point.X := Msg.LParam;
Point.Y := Msg.WParam;
// just to have some "output"
Windows.Beep(Point.X, Point.Y);
end
else
Msg.Result := DefWindowProc(fMsgHandlerHWND, Msg.Msg, Msg.wParam, Msg.lParam);
end;

The "Point" is a field in the TMsgReceiver.

And there you have it - TMsgReceiver receiving where the user has clicked on the form in some other application.

The WM_MY_UNIQUE_MESSAGE also needs to be registered in TMsgReceiver.

Download full source code to explore.

Receive Windows Messages In Your Custom Delphi Class - NonWindowed Control - AllocateHWnd的更多相关文章

  1. 启动windows的服务--《用delphi开发共享软件》-15.2桌面提示器

    在dos 下用命令启动一个服务:NET START "Windows Desktop Reminder" 一下为用delphi启动服务: Function RunProcess(s ...

  2. (5)LoraWAN:Join procedure、Receive Windows

    网络在建立之初,终端设备启动后需要向服务端发起Jion请求(接入请求),只有在接入请求得到成功答复,并根据答复配置相关参数后,终端才算成功加入网络.Jion成功后才能进行数据的上行.下行通信. Jio ...

  3. Sending messages to non-windowed applications -- AllocateHWnd, DeallocateHWnd

    http://delphi.about.com/od/windowsshellapi/l/aa093003a.htm Page 1: How Delphi dispatches messages in ...

  4. Custom Roles Based Access Control (RBAC) in ASP.NET MVC Applications - Part 1 (Framework Introduction)

    https://www.codeproject.com/Articles/875547/Custom-Roles-Based-Access-Control-RBAC-in-ASP-NET Introd ...

  5. Windows API 的数据类型与 Delphi 数据类型对照表

    Windows 数据类型 Delphi 数据类型 描述 LPSTR PAnsiChar 字符串指针 LPCSTR PAnsiChar 字符串指针 DWORD LongWord 整数 BOOL Long ...

  6. Windows Azure Virtual Network (10) 使用Azure Access Control List(ACL)设置客户端访问权限

    <Windows Azure Platform 系列文章目录> 本文介绍的是国内由世纪互联运维的China Azure. 我们在创建完Windows Azure Virtual Machi ...

  7. 获取windows进程信息及CListCtrl控件(List Control)练习

    环境:VS2010/MFC/对话框 效果图: 目录: 1.  关于windows进程信息获取 2.  CListCtrl的使用 ------------------------------------ ...

  8. 针对Windows 64位系统中Matlab没有LED Control Activex控件的解决方法

    Win 10 64bits系统中Matlab 64位软件没有LED Control Activex控件,LED ActiveX Control控件位于Gauges Blockset模块中,而Gauge ...

  9. [Angular2 Form] Create custom form component using Control Value Accessor

    //switch-control component import { Component } from '@angular/core'; import { ControlValueAccessor, ...

随机推荐

  1. C#中的枚举类型(enum type)

    ylbtech 原文 C#中的枚举类型(enum type) 概念 枚举类型(enum type)是具有一组命名常量的独特的值类型.在以下示例中: enum Color { Red, Green, B ...

  2. J2EE事务

    一.J2EE 事务处理方式 1. 本地事务:紧密依赖于底层资源管理器(例如数据库连接 ),事务处理局限在当前事务资源内.此种事务处理方式不存在对应用服务器的依赖,因而部署灵活却无法支持多数据源的分布式 ...

  3. app如何节省流量

    前言:“客户端上传时间戳”的玩法,你玩过么?一起聊聊时间戳的奇技淫巧! 缘起:无线时代,流量敏感.APP在登录后,往往要向服务器同步非常多的数据,很费流量,技术上有没有节省流量的方法呢?这是本文要讨论 ...

  4. 2015-10-27 js

    1.声明变量: 2.prompt属性的使用: prompt("提示框的标题","提示框的输入提示内容"); prompt的调用结果就是他输入框内的内容!!! 3 ...

  5. ubuntu 错误 & 解决

    1.ssh时出现“段错误(核心已转储)” 原因:说明与ssh有关的内核代码被修改过并且部分代码访问内存过界 解决:1.将内核代码被修改过的部分修改回来        2.sudo apt-get re ...

  6. HDU5874:Friends and Enemies

    题目链接: Friends and Enemies 分析: 是一道想法题,我们假设x个人互相敌对,然后有y个人与这x个人都是朋友,而这y个人互相敌对. 则有 x+y=m x*y<=n 举个例子: ...

  7. 第三百三十六天 how can I 坚持

    家里断网了,忘交网费了,连的手机网络,也挺好,吃完饭就可以睡觉了. 不知道怎的,昨天和家人聊天,一提对象的事就很容易着急生气,然后就会后悔..哎,这脾气得改. 确实不知道自己的另一半是啥样,想象不出来 ...

  8. binarySearch二分查找——Javascript实现

    在很早之前,我就写过了一篇也关于二分法的相关博文:JavaScript快排与原生sort的测试.当时是用二分法进行快速排序,其实和这次思路大致相当.二分查找最重要的一个条件,就是需要将数组先按照从小到 ...

  9. 自定义元素 – 在 HTML 中定义新元素

    本文翻译自 Custom Elements: defining new elements in HTML,在保证技术要点表达准确的前提下,行文风格有少量改编和瞎搞. 原译文地址 本文目录 引言 用时髦 ...

  10. 创建一个EMS 扩展包

    EMS Package 向导: File > New > Other > Delphi projects > EMS > EMS Package Empty packag ...