原理:該效果的實現主要是使用AllocateHwnd函數(能夠查閱Delphi的幫助)生成一個非可視的窗口來響應消息,該函數的返回值既是非可視窗口的句柄。而後就能夠在你的類中響應Windows的消息了。該函數只有一個參數就是要建立的非可視窗口的WinProc函數(就是處理該窗口消息的函數),固然你也能夠在這個函數中處理你要處理的消息了。最後在類銷燬時必定要DeallocateHWnd這個非可視窗口。
這些在翻看Delphi ScktComp單元的Socket類時獲得。緣由在於好奇這些類如何能獲得Windows發給它們的關於Socket的消息。ide
如下是從TCustomWinSocket類摘出來源碼(能夠響應消息):函數
unit uClass;測試
interfacespa
uses Messages, Classes, Dialogs;orm
const
WM_MYTEST = WM_USER + $1000; // 測試用繼承
type
TMyClass = class
private
FHandle: THandle;
procedure WinProc(var Msg: TMessage);
procedure WMMyTest(var Msg: TMessage); message WM_MYTEST; // 測試用
public
constructor Create;
destructor Destroy; override;
property Handle: THandle read FHandle;
end;get
implementation源碼
{ TMyClass }it
constructor TMyClass.Create;
begin
if FHandle = 0 then
FHandle := AllocateHwnd(WinProc);
end;io
destructor TMyClass.Destroy;
begin
if FHandle <> 0 then
DeallocateHWnd(FHandle);
end;
procedure TMyClass.WinProc(var Msg: TMessage);
begin
try
//if Msg.Msg = WM_MYTEST then
// ShowMessage('I''m the first get the message "WM_MYTEST"');
Dispatch(Msg);
except
if Assigned(ApplicationHandleException) then
ApplicationHandleException(Self);
end;
end;
procedure TMyClass.WMMyTest(var Msg: TMessage);
begin
ShowMessage('Test OK!' + #10
+ 'I''m coming from Class "TMyClass" with message "WM_MYTEST"!');
end;
end.
後記:這樣,這個類就具備了一個句柄,發個消息WM_MYTEST看看。還能執行。呵呵,之後再寫須要響應消息的類的時候,直接繼承它就能夠了,記得要把 WMMyTest過程刪掉,它只是一個測試。
測試:
var
mc: TMyClass;
begin
mc := TMyClass.Create;
PostMessage(mc.Handle, WM_MYTEST, 0, 0);
end;
個人程序以下 unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, Unit2, StdCtrls; type TForm1 = class(TForm) Button1: TButton; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); private { Private declarations } FPluginRegistry : TPluginRegistry; public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); begin FPluginRegistry := TPluginRegistry.Create; RegisterWindowMessage('WM_DESERIALIZATION'); end; procedure TForm1.Button1Click(Sender: TObject); begin //若是我用這句就能夠接收到自定義的消息 // PostMessage(FPluginRegistry.WindowHandle,WM_DESERIALIZATION,0,0); //若是用這句就不行,怎麼樣才能實現廣播呢? PostMessage(HWND_BROADCAST,WM_DESERIALIZATION,0,0); end; end. unit Unit2; interface uses Classes, Windows, Messages,Dialogs; const WM_DESERIALIZATION = WM_USER + 100; type TPluginRegistry = class(TPersistent) private FWindowHandle: HWND; procedure WndProc(var Msg: TMessage); protected procedure ProcessSaveProperty; virtual; public constructor Create; destructor Destroy; override; property WindowHandle : HWND read FWindowHandle; end; implementation uses Forms; { TPluginRegistry } constructor TPluginRegistry.Create; begin inherited Create; FWindowHandle := Classes.AllocateHWnd(WndProc); end; destructor TPluginRegistry.Destroy; begin Classes.DeallocateHWnd(FWindowHandle); inherited; end; procedure TPluginRegistry.ProcessSaveProperty; begin Showmessage('Received'); end; procedure TPluginRegistry.WndProc(var Msg: TMessage); begin with Msg do if Msg = WM_DESERIALIZATION then try ProcessSaveProperty; except Application.HandleException(Self); end else Result := DefWindowProc(FWindowHandle, Msg, wParam, lParam); end; end.