为什么要这样做?

有时候我们需要一个非窗口组件(比如一个非继承自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 
     to handle messages passed to our
     hidden window
     窗口过程的调用Windows将通过我们的
     隐藏窗口来处理消息
    ********************************}
    ...
  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------------------

当然,我们正是使用Windows API函数创建一个窗体这种困难的方法提供给Windows过程。它是一种用一个方法作为一个窗口过程很困难的方法,如果我们使用它的话。关于AllocateHWnd函数明智的用法是a创建一个隐藏的窗口给我们同时B允许我是用一个方法。而不是一个简单的函数作为窗口的过程同时一个方法自从他存取了类的私有数据后变得很有用。

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

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

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

  1. 让一个非窗口组件(non-windowed component)可以接受来自Windows的消息

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

  2. C#中接受一个非字符串的输入

    接受来自用户的值 System 命名空间中的 Console 类提供了一个函数 ReadLine(),用于接收来自用户的输入,并把它存储到一个变量中. 例如: int num; num = Conve ...

  3. .net core MVC接受来自自前端的GET和POST请求方法的区别

    小伙伴们都知道,常用的http请求有两种方式,即GET方法和POST方法,很多刚入门的童鞋难免都会有一个误区,是不是GET是从服务器上获取数据,POST是向服务器传送数据? 我的理解是:不论是GET还 ...

  4. Java成长之路--一个非科班生的进阶之路

    前言 笔者从事Java开发六年有余,从什么都不懂的小白一路成长到上市公司管理20人的技术leader.管理的团队,虽然人数不算多,但也是对于我这个非科班生这么多年努力的一种肯定.在技术的道路上,我没有 ...

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

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

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

    uboot是一个很优秀的开源项目.不只能够学习bootloader.嵌入式,各种总线协议. 还能够了解网络协议栈.在嵌入式开发中,常常使用uboot的tftp和nfs来加快开发的效率.那么在tftp能 ...

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

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

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

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

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

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

随机推荐

  1. checkbox选中问题

    <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312&qu ...

  2. hdu 1355 The Peanuts

    http://acm.hdu.edu.cn/showproblem.php?pid=1355 #include <cstdio> #include <iostream> #in ...

  3. Linux下的命令行上网

    对于网页浏览器现在大多数人用links/elinks,对了,还有个老牌一点的文本浏览器Lynx,links/elinks也是从Lynx中fork出来的. 以上所说的虽然能字符界面来浏览网页,但是不能显 ...

  4. 2014.8.3情人节欢乐赛【Benny的农场】

    Benny的农场 (farm.pas/.c/.cpp) 时间限制:1s.空间限制:128MB 题目描述: Benny有一片农田需要灌溉.农田的形状为矩形,并被分为许多小块.每一块中都有一些水管.共有1 ...

  5. java 防止sql注入的方法(非原创)

      一.SQL注入简介       SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编程时的疏忽,通过SQL语句,实现无帐号登录,甚至篡改数据库. 二.SQ ...

  6. N种方法妙讲LIS算法

    LIS算法经典汇总 假设存在一个序列d[1..9] = 2 1 5 3 6 4 8 9 7,可以看出来它的LIS长度为5.下面一步一步试着找出它.我们定义一个序列B,然后令 i = 1 to 9 逐个 ...

  7. 使用bulkCopy心得

    最近一直在到excel导入,无意中发现Bulk Insert 批量导入,于是研究了一下,在测试的时候一直有问题,然后找度娘帮忙,说新增DataTable数据结构的时候,每个列要与数据库设计时字段对应, ...

  8. 将json格式日期(毫秒数)转成日常日期格式和日常格式时间对比

    第一:是把生成的Json格式的时间转换,注意要看清楚时间的格式 function (cellval) { var date = new Date(parseInt(cellval.replace(&q ...

  9. 详解AJAX核心 —— XMLHttpRequest 对象 (上)

    我要说的内容都是非常基础的内容,高手就免看了,如果看了欢迎给点意见啊.新手或者对低层还不是很了解的人可以看看,帮助理解与记忆. XMLHttpRequest 对象是AJAX功能的核心,要开发AJAX程 ...

  10. ‘Microsoft.Jet.OLEDB.4.0’ provider is not registered

    正如以下msdn论坛所述,Microsoft.Jet.OLEDB.4.0只有32bit,所以我们必须compile application to x86 platform. http://social ...