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.
  1. // The TMsgReceiver skeleton below is a custom class derived from TObject capable of receiving and handling Windows messages.
  2.  
  3. interface
  4.  
  5. TMsgReceiver = class(TObject)
  6. private
  7. fMsgHandlerHWND : HWND;
  8. procedure WndMethod( var Msg: TMessage);
  9. public
  10. constructor Create;
  11. destructor Destroy; override;
  12. end;
  13.  
  14. implementation
  15.  
  16. constructor TMsgReceiver.Create;
  17. begin
  18. inherited Create;
  19.  
  20. fMsgHandlerHWND := AllocateHWnd(WndMethod);
  21. end;
  22.  
  23. destructor TMsgReceiver.Destroy;
  24. begin
  25. DeallocateHWnd(fMsgHandlerHWND);
  26. inherited;
  27. end;
  28.  
  29. procedure TMsgReceiver.WndMethod(var Msg: TMessage);
  30. begin
  31. if Msg.Msg = WM_MY_UNIQUE_MESSAGE then
  32. begin
  33. //do something
  34. end
  35. else
  36. Msg.Result := DefWindowProc(fMsgHandlerHWND, Msg.Msg, Msg.wParam, Msg.lParam);
  37. 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:

  1. 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:

  1. procedure TClickSendForm.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  2. begin
  3. PostMessage(HWND_BROADCAST, WM_MY_APP_MESSAGE, x, y);
  4. 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:

  1. procedure TMsgReceiver.WndMethod( var Msg: TMessage);
  2. begin
  3. if Msg.Msg = WM_MY_UNIQUE_MESSAGE then
  4. begin
  5. Point.X := Msg.LParam;
  6. Point.Y := Msg.WParam;
  7. // just to have some "output"
  8. Windows.Beep(Point.X, Point.Y);
  9. end
  10. else
  11. Msg.Result := DefWindowProc(fMsgHandlerHWND, Msg.Msg, Msg.wParam, Msg.lParam);
  12. 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. 用xsd验证xml

    using System; using System.Text; using System.Xml; namespace WebApplication1 { public partial class ...

  2. 基于CentOS与VmwareStation10搭建Oracle11G RAC 64集群环境:4.安装Oracle RAC FAQ-4.4.无法图形化安装Grid Infrastructure

    无法图形化安装: [grid@linuxrac1 grid]$ ./runInstaller Starting Oracle Universal Installer... Checking Temp ...

  3. cppunit使用详解

    cppunit使用详解 第一步:如何安装 (我的运行环境: fc7 Linux, gcc4)    cppunit 的安装是相当标准的linux的安装过程    a. 下载cppunit的源文件    ...

  4. 数学概念 z

    数学是很难的科学,但因为它是科学家用数学来解释宇宙的语言,我们无可避免的要学习它.看看下面的这些 GIF 动图,它们提供了视觉的方式来帮助你理解各种数学技巧. 1.椭圆的画法 2.杨辉三角问题(Pas ...

  5. 单机版搭建Hadoop环境图文教程详解

    安装过程: 一.安装Linux操作系统二.在Ubuntu下创建hadoop用户组和用户三.在Ubuntu下安装JDK四.修改机器名五.安装ssh服务六.建立ssh无密码登录本机七.安装hadoop八. ...

  6. VS2013 调试MVC源码[MVC5.2.3+MVC4Web项目]

    1.目前MVC源码版本为5.2.3,下回来后用VS2013打开,把System.Web.Mvc项目的版本号改为4.0.0.1 2.在解决方案下建一个MVC4项目,.NET选4.5,修改根目录以及Vie ...

  7. 设计模式 命令-Command

    命令-Command 当要向不同类的对象发出相同的请求时,可以将接收者和他的动作封装进一个命令对象.这样调用者只和命令产生依赖.而不会和众多的接收者发生依赖. Head First例子 要设计一款遥控 ...

  8. 最小高度的BST

    加深对BST的构建过程及递归思想的理解. /***************************************************** * \file MinimalBST.cpp * ...

  9. 分享一些前端chm文档

    分享地址:http://yun.baidu.com/share/link?shareid=39230983&uk=1008683945 对于网络不好的人来说,离线文档更加方便.打开速度更快. ...

  10. Mono 之 Jexus

    Jexus web server for linux 是运行在Linux上的Web服务器.其安装和部署及其简单,直接支持Asp.net . 下载Jexus wget http://linux.j66. ...