不可聚焦的儿童窗口

时间:2015-11-25 09:12:17

标签: delphi dll-injection

我有简单的VCL表单,这个表单位于注入的dll中。用窗口注入Dll进程。我需要让我的表单不可聚焦,并始终在父窗口(注入过程的主窗口)之前。

表单创建:

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.

表单的CreateParams:

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;

我有什么:

  1. 使用WS_EX_NOACTIVATE且没有Params.WndParent := hWindow我的窗口不可聚焦(TFormButtons),但这不是主窗口的子窗口,当主窗口激活时,我的窗口保持在主窗口下窗口。保持领先是一个坏主意,我的窗口应该只在主窗口之前。

  2. 使用WS_EX_NOACTIVATE和机智Params.WndParent := hWindow我的子VCL窗口有很好的z顺序,这总是在主窗口之前,但主窗口在激活我的窗口时总是失去焦点

  3. 另一个问题:如何在没有ShowModalShow的情况下显示我的VCL窗口。没有ShowModal,这是不可见的

2 个答案:

答案 0 :(得分:0)

可能有一个类助手处理表单的 WM_NCHITTEST 消息。

procedure TFormButtonsHelper.WMNCHitTest(var Msg: TWMNCHitTest);
begin
    if (Msg.Result <> HTHSCROLL) and (Msg.Result <> HTVSCROLL) then
        Msg.Result := HTCLIENT;
end;

答案 1 :(得分:0)

最后我找到了解决方案。我的表格从未得到重点,每次都放在主表格上,并以主表格移动:

注入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.

表单的CreateParams:

procedure TFormButtons.CreateParams(var Params: TCreateParams);
var
  hWindow: THandle;
begin
  inherited CreateParams(Params);
  Params.ExStyle := Params.ExStyle or WS_EX_NOACTIVATE;
end;