• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

ReceiveWindowsMessagesInYourCustomDelphiClass-NonWindowedControl-AllocateHWnd

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

http://delphi.about.com/od/windowsshellapi/a/receive-windows-messages-in-custom-delphi-class-nonwindowed-control.htm

Windows messages are a key ingredient in communication
between Windows and (your) applications and also in communication between (two) applications.

Even "without your knowledge" Windows messages are being posted and handled by forms in your application.

For example, when the user closes the form in your application,

the WM_CLOSE message is sent to the window/form and the form gets closed (if you do not react programmatically).

For an application to receive a Window message, the application must provide a "window" a message will be sent to.

In normal situation this window is the (main) form in your application.

You write a procedure to handle a specific message, like WM_NCHitTest, and you are done.

BUT, what is you do NOT have a window to receive a message?

What if you want to handle messages in your custom class derived from TObject?

Handle Windows Messages in TMyObject = class(TObject)

A Delphi control that has a window handle (derives from TWinControl) can receive Windows messages.

The TObject does not expose a window handle, and therefore any of your custom classes (deriving from TObject)

cannot receive and handle Windows messages, at least not "by default".

To enable your custom class to receive Windows messages you must provide a window handle to the message sender.

The trick is in using the following methods (defined in classes.pas - therefore straightforward to use):

  • AllocateHWnd(WndMethod : TWndMethod). AllocateHWnd is used to create a window that is not associated with a windowed control.
  • The WndMethod : TWndMethod specifies the window procedure that the generated window uses to respond to messages.
  • DeallocateHWnd. DeallocateHWnd destroys window that was created using the AllocateHWnd function.
// The TMsgReceiver skeleton below is a custom class derived from TObject capable of receiving and handling Windows messages.

interface 

TMsgReceiver =  class(TObject) 
private 
  fMsgHandlerHWND : HWND; 
   procedure WndMethod( var Msg: TMessage); 
public 
   constructor Create; 
   destructor Destroy;  override; 
end; 

implementation 

constructor TMsgReceiver.Create; 
begin 
   inherited Create; 

  fMsgHandlerHWND := AllocateHWnd(WndMethod); 
end; 

destructor TMsgReceiver.Destroy; 
begin 
  DeallocateHWnd(fMsgHandlerHWND); 
   inherited; 
end; 

procedure TMsgReceiver.WndMethod(var Msg: TMessage); 
begin 
   if Msg.Msg = WM_MY_UNIQUE_MESSAGE  then 
   begin 
     //do something 
   end 
   else 
    Msg.Result := DefWindowProc(fMsgHandlerHWND, Msg.Msg, Msg.wParam, Msg.lParam);
end; 

 

In the WndMethod procedure (the window procedure for the hidden window) you handle all the messages you are interested in.

For all other mesages a call to DefWindowProc is needed to ensure default processing for any messages that your code does not process.

Handle a Message From Another Application

With the above skeleton, you can now handle messages sent from other applications.

Suppose some application registers Windows message using RegisterWindowMessage API call.

The RegisterWindowMessage function is typically used to register messages for communicating between two cooperating applications.

The "sending" application would have a line like:

WM_MY_APP_MESSAGE := RegisterWindowMessage('MSG_MY_APP_MESSAGE');

 

Where WM_MY_APP_MESSAGE is a cardinal value field used when posting the message to (all) windows.

Let's say we post this message in a form's OnMouseDown event:

procedure TClickSendForm.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); 
begin 
  PostMessage(HWND_BROADCAST, WM_MY_APP_MESSAGE, x, y); 
end; 

 

The HWND_BROADCAST parameter ensures that our WM_MY_APP_MESSAGE is posted to all top-level windows in the system,

including disabled or invisible unowned windows, overlapped windows, and pop-up windows AND our TMsgReceiver hidden window.

To handle the message in the TMsgReceiver instance have the WndMethod as:

procedure TMsgReceiver.WndMethod( var Msg: TMessage); 
begin 
   if Msg.Msg = WM_MY_UNIQUE_MESSAGE  then 
   begin 
    Point.X := Msg.LParam; 
    Point.Y := Msg.WParam; 
     // just to have some "output" 
    Windows.Beep(Point.X, Point.Y); 
   end 
   else 
    Msg.Result := DefWindowProc(fMsgHandlerHWND, Msg.Msg, Msg.wParam, Msg.lParam);
end; 

 

The "Point" is a field in the TMsgReceiver.

And there you have it - TMsgReceiver receiving where the user has clicked on the form in some other application.

The WM_MY_UNIQUE_MESSAGE also needs to be registered in TMsgReceiver.

Download full source code to explore.

 


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
delphiCtrl+鼠标左键或者FindDeclaration不能定位到源文件发布时间:2022-07-18
下一篇:
DELPHI动态添加多级菜单发布时间:2022-07-18
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap