德尔福:创建保持在顶部并且不激活的表单

时间:2015-08-23 15:25:23

标签: delphi winapi

我正在使用WS_EX_NOACTIVATE,但仍可以通过单击激活表单。 在Windows 10,Delphi XE8下进行测试。 我做错了什么?

主窗体(调用Form3.Show on button click):

unit Unit2;

...

type
  TForm2 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);

...

procedure TForm2.Button1Click(Sender: TObject);
begin
form3.Show;
end;

end.

工具栏表单(form3):

unit Unit3;

...

type
  TForm3 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  protected
  procedure CreateParams(var Params: TCreateParams); override;
  public

...   

procedure TForm3.CreateParams(var Params: TCreateParams);
const WS_EX_NOACTIVATE = $8000000;
begin
  inherited;
  Params.ExStyle := Params.ExStyle + WS_EX_NOACTIVATE;
end;

procedure TForm3.FormCreate(Sender: TObject);
begin
FormStyle := fsStayOnTop;
end;

end.

1 个答案:

答案 0 :(得分:0)

我无法发表评论,所以我必须发帖作为答案。

通过将焦点设置在您想要的任何窗口上,您可以轻松实现它。 只需使用EnumWindows获取所有窗口,然后使用SetForegroundWindow来放松焦点。 我在屏幕键盘的实现中做到了这一点。

这意味着当您点击窗口时会有焦点。 在OnClick方法中,使用您想要的句柄调用SetForegroundWindow 专注于你会再次失去焦点。 如果使用OnMouseDown方法,则会更快地失去焦点。

这是我6年前制作的生产代码。 你将不得不修改它,但我希望它会让你知道我在说什么。

  TWindowData = class(TObject)
  private
    FWDWindowHandle: HWND;
    FWDWindowCaption: string;
    FWDExeFileName: string;
    procedure SetWDExeFileName(const Value: string);
    procedure SetWDWindowCaption(const Value: string);
    procedure SetWDWindowHandle(const Value: HWND);
  public
    property WDWindowCaption:string read FWDWindowCaption write SetWDWindowCaption;
    property WDExeFileName:string read FWDExeFileName write SetWDExeFileName;
    property WDWindowHandle: HWND read FWDWindowHandle write SetWDWindowHandle;
  end;

function GetTitle (Hwnd: THandle; Param: Pointer): Boolean; stdcall;
{ get caption from every visible window }

var Text,TempString: string;
    Buf : Array [0..100] of Char;
begin
  result := True;
  If (GetWindowLong(Hwnd,GWL_HWNDPARENT)=0) and (IsWindowVisible(Hwnd) or IsIconic(Hwnd))then
  begin
  TempString := GetWindowExeName(Hwnd);
  SetLength (Text, 100);

  GetModuleFileName( Hwnd,buf, 100 );

  GetWindowText (Hwnd, PChar (Text), 100);
  if NoSystemWindowOrSelf(TempString,Text) then
  begin
    MainForm.OneWindowData := TWindowData.create;
    with MainForm.OneWindowData do
    begin
      WDWindowHandle := Hwnd;
      WDWindowCaption := Text;
      WDExeFileName := TempString;
    end;
    MainForm.WindowDataList.Add (MainForm.OneWindowData);
    MainForm.lbWindowListMemo.Items.Add(text); { Show all Windows in this Memo }

  end;
  Result := True;
  end;
end;

procedure TMainForm.bFillMemoClick(Sender: TObject);
var EWProc: EnumWindowsProc;
begin
  WindowListMemo.Items.Clear;
  WindowDataList.clear;

  { EnumWindows geht der Reihe nach alle offenen Fenster durch }
  EWProc := GetTitle;
  EnumWindows (@EWProc, 0);
end;

procedure TMainForm.FocusWindow;
{ Click on a Memo line to focus a window }
var TempWindowData : TWindowData;
begin
  TempWindowData := TWindowData(WindowDataList[WindowListMemo.itemindex]);
  SetForegroundWindow(TempWindowData.WDWindowHandle);
end;