为什么要这样做?

有时候我们需要一个非窗口组件(比如一个非继承自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

让一个非窗口组件(non-windowed component)可以接受来自Windows的消息的更多相关文章

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

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

  2. Java-Spring MVC如何返回一个非JSP文件名字的地址

    return new ModelAndView("redirect:/bizitem/goEditItem.do?item_id="+item_id+"&msg= ...

  3. 4年前端、2年CTO:一个非科班程序员的真实奋斗史

    1.引言   我,Scott,一家创业公司的 CTO. 从业6年却很少写文章,近一年来接触了几十个刚毕业的前端新人,也面试了100多个前端工程师和Nodejs工程师,对于前端发展的这个职业算是有些感触 ...

  4. [物理学与PDEs]第3章习题1 只有一个非零分量的磁场

    设磁场 ${\bf H}$ 只有一个非零分量, 试证明 $$\bex ({\bf H}\cdot\n){\bf H}={\bf 0}. \eex$$ 证明: 不妨设 ${\bf H}=(0,0,H_3 ...

  5. Quartz的集群模式和单机模式共存-让一个非集群的Quartz与集群节点并行着运行

    假如你让一个非集群的 Quartz 应用与集群节点并行着运行,设法使用 JobInitializationPlugin和 RAMJobStore Quartz支持可选节点执行jobquartz集群,会 ...

  6. 最后一个非零数字(POJ 1604、POJ 1150、POJ 3406)

    POJ中有些问题给出了一个长数字序列(即序列中的数字非常多),这个长数字序列的生成有一定的规律,要求求出这个长数字序列中某个位上的数字是多少.这种问题通过分析,找出规律就容易解决. 例如,N!是一个非 ...

  7. coalesce函数-返回参数中第一个非null值

    coalesce函数-返回参数中第一个非null值 学习了:http://www.cnblogs.com/zc_0101/archive/2009/08/11/1543650.html 这个要复杂一些 ...

  8. Python算法每日一题--001--给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素

    给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找出那个只出现了一次的元素. 说明: 你的算法应该具有线性时间复杂度. 你可以不使用额外空间来实现吗? 示例 1: 输入: [ ...

  9. 一个非侵入的Go事务管理库——如何使用

    在文章"清晰架构(Clean Architecture)的Go微服务: 事物管理"中,我谈到了如何在清晰架构中实现非侵入的事务管理. 它允许你把事务代码与业务逻辑代码分开,并且让你 ...

随机推荐

  1. idea vs

    F8对应vs的F10F7对应vs的F11F9对应vs的F5  ctrl+.对应vs的alt+回车  shift+alt+s   查找文本的出现位置就用Ctrl+F/Ctrl+Shift+F在当前窗口或 ...

  2. angularjs指令中的scope

    共享 scope 使用共享 scope 的时候,可以直接从父 scope 中共享属性.因此下面示例可以将那么属性的值输出出来.使用的是父 scope 中定义的值. js代码: app.controll ...

  3. angularjs探秘<五> 举足轻重的scope

    scope在angular中的作用可谓举足轻重,不理解scope就不会angular: scope是应用在 HTML (view) 和 JavaScript (controller)之间的纽带. sc ...

  4. StanFord ML 笔记 第九部分

    第九部分: 1.高斯混合模型 2.EM算法的认知 1.高斯混合模型 之前博文已经说明:http://www.cnblogs.com/wjy-lulu/p/7009038.html 2.EM算法的认知 ...

  5. gentoo samba 配置

    准备搞一台 PC 作为 NAS, 开启 SAMBA 作为文件服务器.考虑多个手机自动备份到不同的文件夹,可以通过盒子进行播放,还要密码防护. 所以在配置文件里面 valid users 这里把 手机和 ...

  6. Maintenance Planner calculate SPs by manual

    note Are you unable to view your system or updated system information? Apply the latest version of t ...

  7. 432 4.3.2 STOREDRV.Deliver; recipient thread limit exceeded

    最近几天Hub-Mailbox服务器时不时就CPU超过90%.在任务管理器里面看到edgetransport占用大量CPU.进入EMC的队列查看器,看到邮箱数据库堵塞,队列上万. 堵塞的邮件大多是收件 ...

  8. python中的get

    get()根据键获取字典中的值,如果键不存在则返回一个默认值,默认值不填写则返回None 1 a = { 2 "name":"dlrb", 3 "ag ...

  9. samba配置中常见错误收集.txt

    在命令行输入命令: ~$ smbclient -L \\127.0.0.1按要求输入密码后,提示出错:session setup failed: NT_STATUS_LOGON_FAILURE 这是因 ...

  10. 文件系统(File System)

    什么是文件系统,引用百科解释: 操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统. 文件系统是操作系统核心的组成部分,没有它我们无法完成对文件的增.删.改.查等基本操作 概念 ...