怎么让一个非窗口组件可以接受来自Windows的消息

为什么要这样做?

有时候我们需要一个非窗口组件(比如一个非继承自TWinContrl的组件)可以接受Windows消息。要接受消息就需要一个窗口句柄,但是非窗口组件却没有句柄。这篇文章将讲述怎么让一个没有句柄的组件如何通过一个隐藏的窗口接受消息

这是怎么做到的?

例如
我的剪贴板查看组件就是一个不可视的组件。这个窗体可以接收提供信息关于更改剪贴板的消息。

Delphi库里面的AllocateHWnd函数可以帮助我们创建一个隐藏的窗口,同时与之相关的DeallocateHWnd函数可以释放当我们使用完的隐藏窗口。

这个隐藏的窗口将命令窗口过程。

通常当Windows调用一个stdcall函数时,AllocateHWnd函数能让我们像窗体过程一样的使用方法。

我们通过一个引用allocatehwnd函数所需的方法来并将它注册为一个窗口过程的方法来解决问题。

在这个被注册的方法内部我们可以处理我们感兴趣的消息同时传递给Windows

下面的代码清单2停工了一个如何使用AllocateHWnd函数的框架。尽管如此,我们的代码清单1定义一个组件类的轮廓:

------------------代码清单1------------------
type
  {*******************************
   Our class derived from TComponent 
    or another ancestor class
  ********************************}
  TMyClass = class(TComponent)
  private
    fHWnd: HWND;
      {*******************************
       field to store the window handle
       存储窗口句柄的字段 
      ********************************}
    ...
  protected
    procedure WndMethod(var Msg: TMessage); virtual;
    {*******************************  
     window proc - called by Windows    窗口过程(window proc) 由windows系统调用
     to handle messages passed to our
     hidden window    该窗口过程是用来处理传递到我们的隐藏窗口的

********************************}
    ...
  public
     constructor Create(AOwner: TComponent); override;
     {*******************************
      create hidden window here: 
      store handle in fHWnd
      在这里创建隐藏窗体,并且把它的句柄存储在fHWnd字段。

********************************}
     destructor Destroy; override;
     {*******************************
      free hidden window here
      销毁隐藏窗口过程
     ********************************}
     ...
  end;
------------------代码清单1------------------

同时下面将是实现部分的详细代码:

------------------代码清单2------------------
constructor TMyClass.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  ...
  //创建一个隐藏窗体并且用WndMethod过程
  fHWnd := AllocateHWnd(WndMethod);
  ...
end;

destructor TMyClass.Destroy;
begin
  ...
  //销毁隐藏窗口
  DeallocateHWnd(fHWnd);
  ...
  inherited Destroy;
end;

procedure TMyClass.WndMethod(var Msg : TMessage);
var
  Handled: Boolean;
begin
  //假定我们可以处理消息
  Handled := True;
  case Msg.Msg of
    WM_SOMETHING: DoSomething;
       //处理消息的代码

WM_SOMETHINGELSE: DoSomethingElse;
       //处理另一个消息的代码
    //这里处理其他的消息
    else
      //我们不再处理消息
      Handled := False;
  end;

if Handled then
    //我们在消息记录里处理消息
    Msg.Result := 0
  else
    //我们通过DefWindowProc函数
    //不处理的消息同时记录结果
    Msg.Result := DefWindowProc(fHWnd,
                                Msg.Msg, 
                                Msg.WParam,
                                Msg.LParam);
end;
------------------代码清单2------------------

原文:Of course, we could just use the Windows API to create a window the hard way and provide a windows procedure.

But it is more difficult to use a method as a window procedure if we do it this way.

The clever features about AllocateHWnd are that (a) it creates the hidden window for us and (b) it allows us to use a method, rather than a simple procedure,

as the window procedure – and a method is more useful since it has access to the class‘s private data.

译文:当然,我们仅使用 Windows API提供的比较难的方式创建了一个window(窗口)并提供窗口过程。
但是,如果我们采用这种方式,那么把一个方法作为窗口过程来使用的话将是困难的。

关于AllocateHWnd灵活的特性有:
(a)它创建一个隐藏窗口给我们使用
(b)它允许我们使用一个方法,而不是一个简单的过程(procedure),作为该窗口过程——当使用这个方法来访问该类的私有数据的时候更加有用。

后记:第一次翻译文章,可能有些地方理解的不是很透彻,所以附录原文地址如下.

原文:http://www.delphidabbler.com/articles?article=1

时间: 2024-10-27 03:51:56

怎么让一个非窗口组件可以接受来自Windows的消息的相关文章

一步步玩pcDuino3--uboot下的ping,添加命令可以接受来自host的ping

uboot是一个非常优秀的开源项目.不仅仅可以学习bootloader,嵌入式,各种总线协议.还可以了解网络协议栈.在嵌入式开发中,经常使用uboot的tftp和nfs来加快开发的效率.那么在tftp可以使用之前,我们要保证host和pcDuino3可以ping通.在uboot下可以ping通host,但是host不能ping通uboot,这是因为uboot不是操作系统,我们需要做了个命令来循环等待来自host的ping命令. 在为uboot添加命令接受来自host的ping之前,我们先了解一下

使用OTP原理构建一个非阻塞的TCP服务器(转)

经测试可用! 原文地址:http://www.iucai.com/?paged=8 Erlang OTP设计原理已经被shiningray兄翻译透了.请参见.http://erlang.shiningray.cn/otp-design-principles/index.html 这里翻译了一篇余锋老大和lzy.je老大推荐的文章,闲话不说,奉上. 使用OTP原理构建一个非阻塞的TCP服务器 原文网址:(打不开的同学请自觉FQ) http://www.trapexit.org.nyud.net:8

一步步玩pcDuino3--uboot下的ping,加入命令能够接受来自host的ping

uboot是一个很优秀的开源项目.不只能够学习bootloader.嵌入式,各种总线协议. 还能够了解网络协议栈.在嵌入式开发中,常常使用uboot的tftp和nfs来加快开发的效率.那么在tftp能够使用之前,我们要保证host和pcDuino3能够ping通. 在uboot下能够ping通host.可是host不能ping通uboot,这是由于uboot不是操作系统,我们须要做了个命令来循环等待来自host的ping命令. 在为uboot加入命令接受来自host的ping之前.我们先了解一下

Netty:一个非阻塞的客户端/服务器框架

Netty:一个非阻塞的客户端/服务器框架 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs Netty是一个异步事件驱动的网络应用框架,为Java网络应用的开发带来了一些新活力.Netty由协议服务器和客户端所组成,可用于快速开发可维护的高性能软件.Netty应用框架及其工具简化了网络编程,而且由Netty社区进行维护. Netty还被归类为NIO客户端/服务器框架,用它能够快速.简易地开发网络应用,使得TCP和UDP套接字服务器的网络编程得以简化和

hdu 1066 Last non-zero Digit in N! (数论——n!中的最后一个非0数字)

Last non-zero Digit in N! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 6432    Accepted Submission(s): 1593 Problem Description The expression N!, read as "N factorial," denotes the pro

找第一个非0元素的位置

DATA SEGMENTARR DB 0,0,34H,56H,89H,0CNT EQU $-ARRRES DB 0DATA ENDSCODE SEGMENTASSUME CS:CODE,DS:DATABEGIN: MOV AX,DATA MOV DS,AX XOR AX,AX MOV CX,CNT MOV BX,0NEXT: CMP ARR[BX],0 JNZ NEXT1 INC BX LOOP NEXT JNZ EXIT ;如果ZF不等于0即相比都不相等 NEXT1: MOV RES,BLEX

16 如何使一个文本框只能接受数字

(1) 使用NumericUpDown (2) 处理KeyPress 按钮 (3) 处理Text_Changed 事件 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; usin

实现一个非阻塞IO的服务器

先来实现一个简单的服务器,这个服务器简单的回送任何客户端的输入 EchoServer.java package server; import java.io.*; import java.net.*; import java.util.*; /** * This program implements a simple server that listens to port 8189 and echoes back all client input * @author zhangchen * */

17、把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。 NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1. NOTE:给出的所有元素都大于0,若数组大小为0,请返回0. eg: 输入 3 4 5 1 2 输出 1 思路:用二分法查找最小元素 三种情况: (1)rotateArray[mid] >rotateArray[high]: like:[x,x,x,6,x,x,2],此时最小数字一