How a non-windowed component can receive messages from Windows -- AllocateHWnd

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

Why do it?

Sometimes we need a non-windowed component (i.e. one that isn't derived fromTWinControl) to receive Windows messages.

To receive messages the component needs a window handle, but a non-windowed component hasn't got one!

This article is about how to enable such a component to use a hidden window to receive messages.

How it's done

The Delphi library function AllocateHWnd is used to create a hidden window for us

and the related DeallocateHWnd disposes of the window when we've finished with it.

The hidden window requires window procedure.

AllocateHWnd enables us to use a method as a window procedure where Windows normally requires a stdcall function.

We pass a reference to the required method to AllocateHWnd and

it takes care of the problem of registering the method as a window procedure for us.

Inside the registered method we handle the messages we are interested in

and hand the rest off to Windows using the DefWindowProc API call.

Listing 2 below provides a skeleton of how to use AllocateHWnd.

First though, Listing 1shows an outline definition for our component class:

复制代码
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 }
    ...
  public
     constructor Create(AOwner: TComponent); override;
       { create hidden window here: store handle in fHWnd}
     destructor Destroy; override;
       { free hidden window here }
     ...
  end;
复制代码

And here are the implementation details:

复制代码
constructor TMyClass.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  ...
  // Create hidden window using WndMethod as window proc
  fHWnd := AllocateHWnd(WndMethod);
  ...
end;

destructor TMyClass.Destroy;
begin
  ...
  // Destroy hidden window
  DeallocateHWnd(fHWnd);
  ...
  inherited Destroy;
end;

procedure TMyClass.WndMethod(var Msg : TMessage);
var
  Handled: Boolean;
begin
  // Assume we handle message
  Handled := True;
  case Msg.Msg of
    WM_SOMETHING: DoSomething;
      // Code to handle a message
    WM_SOMETHINGELSE: DoSomethingElse;
      // Code to handle another message
    // Handle other messages here
    else
      // We didn't handle message
      Handled := False;
  end;
  if Handled then
    // We handled message - record in message result
    Msg.Result := 0
  else
    // We didn't handle message
    // pass to DefWindowProc and record result
    Msg.Result := DefWindowProc(fHWnd, Msg.Msg,
      Msg.WParam, Msg.LParam);
end;
复制代码

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.

 

posted @   IAmAProgrammer  阅读(461)  评论(0编辑  收藏  举报
(评论功能已被禁用)
编辑推荐:
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
点击右上角即可分享
微信分享提示