也許一個愚蠢的問題,但...如何從WndProc中獲取窗口句柄?
我正在寫一個class
應採取保持一個窗口的護理(FGuestHWnd
,從現在起)視覺錨定到「主機窗口」(FHostHWnd
)。
FGuestHWnd
和HostHWnd
沒有父母/所有者/子女關係。FGuestHWnd
屬於另一個過程 - 不關心。FHostHWnd
是VCLTWinControl
的窗口句柄,所以這是我的過程中的一個子窗口。它可以坐在父/子樹內的任何級別。例如,假設這是一個TPanel
。
現在我必須「鉤」FHostHWnd
的移動/調整大小,並在我的自定義計算後調用SetWindowPos(FGuestHWnd...
。調整大小非常簡單:我可以使用SetWindowLong(FHostHWnd, GWL_WNDPROC, ...)
將FHostHWnd
的WndProc「重定向到」我的自定義WindowPorcedure和陷阱WM_WINDOWPOSCHANGING
。由於FHostHWnd
是客戶端對齊的,因此此消息會自動發送到FHostHWnd
,因爲其中一個祖先的大小已調整。
感動,如果我不缺少的東西,是有點麻煩,因爲如果我移動的主要形式FHostHWnd
是不是真的很感動。它保持與其父母相同的位置。所以它不會以任何方式通知祖先的移動。
我的解決辦法是有父的WndProc「重定向」到自定義窗口過程和陷阱WM_WINDOWPOSCHANGING爲「移動」唯一消息。 在這種情況下,我可以用自定義消息通知FHostHWnd
。 我班內的一些字段將跟蹤Win Handles,原WndProc addesses和新WndProc地址鏈。
下面是一些代碼來解釋我的結構:
TMyWindowHandler = class(TObject)
private
FHostAncestorHWndList: TList;
FHostHWnd: HWND;
FGuestHWnd: HWND;
FOldHostAncestorWndProcList: TList;
FNewHostAncestorWndProcList: TList;
//...
procedure HookHostAncestorWindows;
procedure UnhookHostAncestorWindows;
procedure HostAncestorWndProc(var Msg: TMessage);
end;
procedure TMyWindowHandler.HookHostAncestorWindows;
var
ParentHWnd: HWND;
begin
ParentHWnd := GetParent(FHostHWnd);
while (ParentHWnd > 0) do
begin
FHostAncestorHWndList.Insert(0, Pointer(ParentHWnd));
FOldHostAncestorWndProcList.Insert(0, TFarProc(GetWindowLong(ParentHWnd, GWL_WNDPROC)));
FNewHostAncestorWndProcList.Insert(0, MakeObjectInstance(HostAncestorWndProc));
Assert(FOldHostAncestorWndProcList.Count = FHostAncestorHWndList.Count);
Assert(FNewHostAncestorWndProcList.Count = FHostAncestorHWndList.Count);
if (SetWindowLong(ParentHWnd, GWL_WNDPROC, LongInt(FNewHostAncestorWndProcList[0])) = 0) then
RaiseLastOSError;
ParentHWnd := GetParent(FHostHWnd);
end;
end;
這裏是處理程序:
procedure TMyWindowHandler.HostAncestorWndProc(var Msg: TMessage);
var
pNew: PWindowPos;
begin
case Msg.Msg of
WM_DESTROY: begin
UnHookHostAncestorWindows;
end;
WM_WINDOWPOSCHANGING: begin
pNew := PWindowPos(Msg.LParam);
// Only if the window moved!
if ((pNew.flags and SWP_NOMOVE) = 0) then
begin
//
// Do whatever
//
end;
end;
end;
Msg.Result := CallWindowProc(???, ???, Msg.Msg, Msg.WParam, Msg.LParam);
end;
我的問題是:
我怎樣才能得到的窗口句柄從我的WindowProcedure裏面,當我最終調用CallWindowProc
? (如果我有窗口句柄,我也可以在FOldHostAncestorWndProcList
中找到它,然後在FHostAncestorHWndList
中查找右邊的Old-WndProc-pointer) 或者,作爲替代,如何獲取CURRENT方法指針,以便我可以在其中找到它FNewHostAncestorWndProcList
並在FHostAncestorHWndList
中查找HWND。
或者你提出其他解決辦法?
請注意,我想保留一切HWND爲導向,而不是VCL/TWinControl感知。
換句話說,我的應用程序應該只實例TMyWindowHandler傳遞給它兩個HWND
S(主機和客戶)。
謝謝大衛。但是'MakeObjectInstance'不是專門爲解決這個問題而存在的嗎?看起來VCL本身綁定了一個'TWinControl'的'WndProc'。 – yankee
我已經擴大了。 'MakeObjectInstance'是你的問題。 'AllocateHwnd'和'TWinControl.Create'使用它來形成窗口和實例之間的一對一關係。您的問題具有多對一的實例關係。所以'MakeObjectInstance'根本不好。 –
好點大衛。謝謝。 – yankee