为什么要这样做?

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

    Write a function to find the longest common prefix string amongst an array of strings. class Solutio ...

  2. Qt中事件处理的方法(三种处理方法,四种覆盖event函数,notify函数,event过滤,事件处理器。然后继续传递给父窗口。可观察QWidget::event的源码,它是虚拟保护函数,可改写)

    一.Qt中事件处理的方式   1.事件处理模式一 首先是事件源产生事件,最后是事件处理器对这些事件进行处理.然而也许大家会问, Qt中有这么多类的事件,我们怎么样比较简便的处理每个事件呢?设想,如果是 ...

  3. 多线程实际运用<第七篇>

    1.单线程采集100个页面 class Program { static int i = 6991275; static void Main(string[] args) { Stopwatch sw ...

  4. JavaScriptSerializer类 对象序列化为JSON,JSON反序列化为对象

    JavaScriptSerializer 类由异步通信层内部使用,用于序列化和反序列化在浏览器和 Web 服务器之间传递的数据.说白了就是能够直接将一个C#对象传送到前台页面成为javascript对 ...

  5. 经过一年时间的沉淀 再次回首 TCP Socket服务器编程--转

    ------------------ 前言 ------------------ 开发了这么多年,发现最困难的程序开发就是通讯系统. 其他大部分系统,例如CRM/CMS/权限框架/MIS之类的,无论怎 ...

  6. 一款超出你想象的代码审阅软件understand

    看源码人们一般会想到source insight这款软件可是这款软件目前只支持windows平台,那如果我想在Linux平台上审阅代码呢, 没关系还有一款强大的软件understand,这款软件能够生 ...

  7. java面试题集3

    一.选择题 1.下面程序的运行结果是 int i=0; while(true){ if(i++>10)  break; System.out.println(i); }1-11 2.下面程序的运 ...

  8. 详细介绍Qt,ffmpeg 和SDL开发

        Qt 与 ffmpeg 与 SDl 教程是本文要介绍的内容,从多个角度介绍本文,运用了qmake,先来看内容. 1.  注释 从“ #” 开始,到这一行结束. 2.  指定源文件 1.     ...

  9. hdu 4930 Fighting the Landlords--2014 Multi-University Training Contest 6

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4930 Fighting the Landlords Time Limit: 2000/1000 MS ...

  10. ff与ie 的关于js兼容性

    FF的FIREBUG,不仅能测试JS还能检查CSS错误,是一般常用的.但它主要检查FF方面的错误,对IE就无能为力了.要测试IE,就用ieTester,它可以测试IE几乎所有版本(1.0恐怕也用不到测 ...