Non-focusable child window
Non-focusable child window
我有简单的 VCL 窗体,这个窗体位于注入的 dll 中。使用 window 注入进程的 DLL。我需要使我的表单成为 non-focusable 并且始终在 parent window 之前(注入过程的主要 window)。
表单创建:
procedure CreateForm;
var
hWindow: THandle;
Rect: TRect;
begin
if GetProcessWindowHandle(GetCurrentProcessId, hWindow) then begin
FormButtons := TFormButtons.Create(nil);
GetWindowRect(hWindow, Rect);
FormButtons.Left := Rect.Left + 50;
FormButtons.Top := Rect.Top;
FormButtons.ShowModal;
FormButtons.Free;
end;
end;
procedure DLLEntryPoint(dwReason: DWORD);
begin
case dwReason of
DLL_PROCESS_ATTACH: begin
CreateForm;
end;
DLL_PROCESS_DETACH: begin
end;
end;
end;
begin
DLLProc := @DLLEntryPoint;
DLLEntryPoint(DLL_PROCESS_ATTACH);
end.
为表单创建参数:
procedure TFormButtons.CreateParams(var Params: TCreateParams);
var
hWindow: THandle;
begin
inherited CreateParams(Params);
Params.ExStyle := Params.ExStyle or WS_EX_NOACTIVATE;
if GetProcessWindowHandle(GetCurrentProcessId, hWindow) then
Params.WndParent := hWindow;
end;
我有:
有 WS_EX_NOACTIVATE
没有 Params.WndParent := hWindow
我有 non-focusable 我的 window (TFormButtons),但这不是 child window 对于 main window 并且当 main window 激活时我的 window 留在 main window 下。保持领先是个坏主意,我的 window 应该只在 main window.
之前
有了 WS_EX_NOACTIVATE
和机智 Params.WndParent := hWindow
我的 child VCL window 很好 z-ordering,这总是在 main 之前window,但主 window 在激活我的 window
时总是失去焦点
还有另一个问题:如何在没有 ShowModal
但有 Show
的情况下显示我的 VCL window。没有 ShowModal
这是不可见的
可能有一个 class 帮助程序处理 WM_NCHITTEST 形式的消息。
procedure TFormButtonsHelper.WMNCHitTest(var Msg: TWMNCHitTest);
begin
if (Msg.Result <> HTHSCROLL) and (Msg.Result <> HTVSCROLL) then
Msg.Result := HTCLIENT;
end;
终于找到解决办法了。我的表单从未获得焦点,每次都放在主表单上并随主表单一起移动:
注入的 dll:
var
hWndHook: HHOOK = 0;
hWndMain: THandle = 0;
ProcessId: DWORD = 0;
ThreadId: DWORD = 0;
function CallWndProc(Code: Integer; wParam: WPARAM; CWPStruct: PCWPStruct): LRESULT; stdcall;
var
Rect: TRect;
begin
Result := CallNextHookEx(hWndHook, Code, wParam, LPARAM(CWPStruct));
if (Code = HC_ACTION) then begin
case CWPStruct.message of
WM_MOVE: if hWndMain > 0 then begin
if Assigned(FormButtons) then begin
GetWindowRect(hWndMain, Rect);
SetWindowPos(FormButtons.Handle, HWND_TOPMOST, Rect.Left, Rect.Top - 10, 0, 0, SWP_NOACTIVATE or SWP_NOSIZE);
SetWindowPos(FormButtons.Handle, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOMOVE);
end;
end;
WM_ACTIVATE: if (hWndMain > 0) then begin
if Assigned(FormButtons) then begin
SetWindowPos(FormButtons.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOMOVE);
SetWindowPos(FormButtons.Handle, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOMOVE);
end;
end;
WM_CLOSE: if (hWndMain > 0) and (hWndMain = CWPStruct.hwnd) then begin
try
UnhookWindowsHookEx(hWndHook);
hWndMain := 0;
except
MessageBox(0, 'Error: WM_CLOSE', '', MB_OK);
end;
end;
end;
end;
end;
function ThreadProc(Params: Pointer): Integer;
begin
Result := 0;
try
ProcessId := GetCurrentProcessId;
if GetProcessWindowHandle(ProcessId, hWndMain) then
ThreadId := GetWindowThreadProcessId(hWndMain);
if hWndHook = 0 then
hWndHook := SetWindowsHookEx(WH_CALLWNDPROC, @CallWndProc, HInstance, ThreadId);
// MessageBox(0, PChar('Hook installed!' + sLineBreak +
// 'Process Id: ' + IntToStr(ProcessId) + sLineBreak +
// 'Thread Id: ' + IntToStr(ThreadId) + sLineBreak +
// 'hWndMain: ' + IntToStr(hWndMain) + sLineBreak +
// 'hWndHook: ' + IntToStr(hWndHook)), '', MB_OK);
FormButtons := TFormButtons.Create(nil);
FormButtons.ShowModal;
Result := 0;
except
// Result := ERROR_GEN_FAILURE;
end;
end;
procedure DLLEntryPoint(dwReason: DWORD);
var
hThread: THandle;
ThreadId: UInt32;
begin
case dwReason of
DLL_PROCESS_DETACH: begin
// MessageBox(0, PChar('DLL_PROCESS_DETACH: ' + IntToStr(ProcessId)), '', MB_OK);
end;
DLL_PROCESS_ATTACH: begin
hThread := BeginThread(nil, 0, ThreadProc, nil, 0, ThreadId);
if hThread <> 0 then
CloseHandle(hThread);
// MessageBox(0, PChar('DLL_PROCESS_ATTACH: ' + IntToStr(GetCurrentProcessId)), '', MB_OK);
end;
end;
end;
begin
DLLProc := @DLLEntryPoint;
DLLEntryPoint(DLL_PROCESS_ATTACH);
end.
为表单创建参数:
procedure TFormButtons.CreateParams(var Params: TCreateParams);
var
hWindow: THandle;
begin
inherited CreateParams(Params);
Params.ExStyle := Params.ExStyle or WS_EX_NOACTIVATE;
end;
我有简单的 VCL 窗体,这个窗体位于注入的 dll 中。使用 window 注入进程的 DLL。我需要使我的表单成为 non-focusable 并且始终在 parent window 之前(注入过程的主要 window)。
表单创建:
procedure CreateForm;
var
hWindow: THandle;
Rect: TRect;
begin
if GetProcessWindowHandle(GetCurrentProcessId, hWindow) then begin
FormButtons := TFormButtons.Create(nil);
GetWindowRect(hWindow, Rect);
FormButtons.Left := Rect.Left + 50;
FormButtons.Top := Rect.Top;
FormButtons.ShowModal;
FormButtons.Free;
end;
end;
procedure DLLEntryPoint(dwReason: DWORD);
begin
case dwReason of
DLL_PROCESS_ATTACH: begin
CreateForm;
end;
DLL_PROCESS_DETACH: begin
end;
end;
end;
begin
DLLProc := @DLLEntryPoint;
DLLEntryPoint(DLL_PROCESS_ATTACH);
end.
为表单创建参数:
procedure TFormButtons.CreateParams(var Params: TCreateParams);
var
hWindow: THandle;
begin
inherited CreateParams(Params);
Params.ExStyle := Params.ExStyle or WS_EX_NOACTIVATE;
if GetProcessWindowHandle(GetCurrentProcessId, hWindow) then
Params.WndParent := hWindow;
end;
我有:
有
WS_EX_NOACTIVATE
没有Params.WndParent := hWindow
我有 non-focusable 我的 window (TFormButtons),但这不是 child window 对于 main window 并且当 main window 激活时我的 window 留在 main window 下。保持领先是个坏主意,我的 window 应该只在 main window. 之前
有了
WS_EX_NOACTIVATE
和机智Params.WndParent := hWindow
我的 child VCL window 很好 z-ordering,这总是在 main 之前window,但主 window 在激活我的 window 时总是失去焦点
还有另一个问题:如何在没有
ShowModal
但有Show
的情况下显示我的 VCL window。没有ShowModal
这是不可见的
可能有一个 class 帮助程序处理 WM_NCHITTEST 形式的消息。
procedure TFormButtonsHelper.WMNCHitTest(var Msg: TWMNCHitTest);
begin
if (Msg.Result <> HTHSCROLL) and (Msg.Result <> HTVSCROLL) then
Msg.Result := HTCLIENT;
end;
终于找到解决办法了。我的表单从未获得焦点,每次都放在主表单上并随主表单一起移动:
注入的 dll:
var
hWndHook: HHOOK = 0;
hWndMain: THandle = 0;
ProcessId: DWORD = 0;
ThreadId: DWORD = 0;
function CallWndProc(Code: Integer; wParam: WPARAM; CWPStruct: PCWPStruct): LRESULT; stdcall;
var
Rect: TRect;
begin
Result := CallNextHookEx(hWndHook, Code, wParam, LPARAM(CWPStruct));
if (Code = HC_ACTION) then begin
case CWPStruct.message of
WM_MOVE: if hWndMain > 0 then begin
if Assigned(FormButtons) then begin
GetWindowRect(hWndMain, Rect);
SetWindowPos(FormButtons.Handle, HWND_TOPMOST, Rect.Left, Rect.Top - 10, 0, 0, SWP_NOACTIVATE or SWP_NOSIZE);
SetWindowPos(FormButtons.Handle, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOMOVE);
end;
end;
WM_ACTIVATE: if (hWndMain > 0) then begin
if Assigned(FormButtons) then begin
SetWindowPos(FormButtons.Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOMOVE);
SetWindowPos(FormButtons.Handle, HWND_TOP, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOSIZE or SWP_NOMOVE);
end;
end;
WM_CLOSE: if (hWndMain > 0) and (hWndMain = CWPStruct.hwnd) then begin
try
UnhookWindowsHookEx(hWndHook);
hWndMain := 0;
except
MessageBox(0, 'Error: WM_CLOSE', '', MB_OK);
end;
end;
end;
end;
end;
function ThreadProc(Params: Pointer): Integer;
begin
Result := 0;
try
ProcessId := GetCurrentProcessId;
if GetProcessWindowHandle(ProcessId, hWndMain) then
ThreadId := GetWindowThreadProcessId(hWndMain);
if hWndHook = 0 then
hWndHook := SetWindowsHookEx(WH_CALLWNDPROC, @CallWndProc, HInstance, ThreadId);
// MessageBox(0, PChar('Hook installed!' + sLineBreak +
// 'Process Id: ' + IntToStr(ProcessId) + sLineBreak +
// 'Thread Id: ' + IntToStr(ThreadId) + sLineBreak +
// 'hWndMain: ' + IntToStr(hWndMain) + sLineBreak +
// 'hWndHook: ' + IntToStr(hWndHook)), '', MB_OK);
FormButtons := TFormButtons.Create(nil);
FormButtons.ShowModal;
Result := 0;
except
// Result := ERROR_GEN_FAILURE;
end;
end;
procedure DLLEntryPoint(dwReason: DWORD);
var
hThread: THandle;
ThreadId: UInt32;
begin
case dwReason of
DLL_PROCESS_DETACH: begin
// MessageBox(0, PChar('DLL_PROCESS_DETACH: ' + IntToStr(ProcessId)), '', MB_OK);
end;
DLL_PROCESS_ATTACH: begin
hThread := BeginThread(nil, 0, ThreadProc, nil, 0, ThreadId);
if hThread <> 0 then
CloseHandle(hThread);
// MessageBox(0, PChar('DLL_PROCESS_ATTACH: ' + IntToStr(GetCurrentProcessId)), '', MB_OK);
end;
end;
end;
begin
DLLProc := @DLLEntryPoint;
DLLEntryPoint(DLL_PROCESS_ATTACH);
end.
为表单创建参数:
procedure TFormButtons.CreateParams(var Params: TCreateParams);
var
hWindow: THandle;
begin
inherited CreateParams(Params);
Params.ExStyle := Params.ExStyle or WS_EX_NOACTIVATE;
end;