標籤:strong over sed ble out des 釋放 c函數 理解
為什麼要這樣做?
有時候我們需要一個非視窗組件(比如一個非繼承自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 視窗過程(window proc) 由windows系統調用
to handle messages passed to our
hidden window 該視窗過程是用來處理傳遞到我們的隱藏視窗的 ********************************}
...
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------------------
原文: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.
譯文:當然,我們僅使用 Windows API提供的比較難的方式建立了一個window(視窗)並提供視窗過程。
但是,如果我們採用這種方式,那麼把一個方法作為視窗過程來使用的話將是困難的。
關於AllocateHWnd靈活的特性有:
(a)它建立一個隱藏視窗給我們使用
(b)它允許我們使用一個方法,而不是一個簡單的過程(procedure),作為該視窗過程——當使用這個方法來訪問該類的私人資料的時候更加有用。
後記:第一次翻譯文章,可能有些地方理解的不是很透徹,所以附錄原文地址如下.
原文:http://www.delphidabbler.com/articles?article=1
怎麼讓一個非視窗組件可以接受來自Windows的訊息