将表单保存在其他应用程序窗口之上

时间:2017-02-01 03:29:17

标签: delphi vcl delphi-10-seattle

我尝试显示一个VCL表单,该表单保留在所有其他应用程序之上,以便可以将数据从此表单复制到另一个应用程序中,而不会在两个应用程序之间轻弹哪个应用程序。

我可以显示一个表单并将其保存在所有其他应用程序之上,并使用fsStayOnTop与其他应用程序交互并使用以下代码打开它:

form := TForm2.Create(nil);

SetWindowPos(form.Handle, // handle to window
    HWND_TOPMOST, // placement-order handle
    form.Left, // horizontal position
    form.Top, // vertical position
    form.Width, form.Height,
    // window-positioning options
    SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE);

form.Show();

我目前遇到的问题是,当我点击我的表单,复制并粘贴数据时,我的应用程序的其他表单也被提出,这隐藏了应用程序我将数据复制到。主应用程序表单使用ShowModal打开TForm1,然后可以使用上面的代码打开TForm2,我认为它会使TForm1向前推进,因为它不应该拥有所有者或父母。

我已经看过这个问题How can get my form to be on top of everything all the time?,不幸的是,它并没有阻止其他形式被提出。

因此,当TForm2聚焦时,我想要的窗口顺序是:

mainform
TForm1
Whatever application, normally word
TForm2

相反,我得到

Whatever application, normally word
mainform
TForm1
TForm2

我知道这个功能看起来有点奇怪,但重要的是提高可用性,主要是在单一监视器上,因为用户可能经常在我的表单和其他应用程序之间轻弹。

我目前在Windows 10 Professional 64位上使用Delphi 10 Seattle,以防万一。

超级简单的例子

(如果有更好的方式来提供我想知道的例子):

Form1按钮

procedure TForm1.Button1Click(Sender: TObject);
var
    form2: TForm2;
begin
    form2 := TForm2.Create(self);
    form2.ShowModal();
end;

Form2按钮

procedure TForm2.Button1Click(Sender: TObject);
var
    form3: TForm3;
begin
    form3 := TForm3.Create(nil);

    SetWindowPos(form3.Handle, // handle to window
        HWND_TOPMOST, // placement-order handle
        form3.Left, // horizontal position
        form3.Top, // vertical position
        form3.Width, form3.Height,
        // window-positioning options
        SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE);

    form3.Show();
end;

Form3:FormStyle = fsStayOnTop

1 个答案:

答案 0 :(得分:0)

感谢Nat建议隐藏其他表格我已经提出这个解决方案,利用How to get a list from all opened forms of my software?

中的信息

简单解决方案

procedure TForm2.Button1Click(Sender: TObject);
var
    form3: TForm3;
    ii: integer;
begin
    for ii := 0 to Screen.FormCount - 1 do
        Screen.Forms[ii].Visible := false;

    form3 := TForm3.Create(nil);

    SetWindowPos(form3.Handle, // handle to window
        HWND_TOPMOST, // placement-order handle
        form3.Left, // horizontal position
        form3.Top, // vertical position
        form3.Width, form3.Height,
        // window-positioning options
        SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE);

    form3.ShowModal();
    form3.Free();

    for ii := 0 to Screen.FormCount - 1 do
        Screen.Forms[ii].Visible := true;
end;

我们的想法是使用Screen.Forms / Screen.FormCount简单地遍历所有当前显示的表单并使其不可见,然后在我们完成后再次将它们全部显示。

扩展解决方案

如果您的表单是使用Application.CreateForm()创建的,并且只是显示和关闭但从未释放,那么这将打开所有这些表单。我找到的解决方案是存储一个可见表单列表,并在最后只显示那些可见表单。

procedure TForm2.Button1Click(Sender: TObject);
var
    form3: TForm3;
    ii: integer;
    visibleForms: TList<TForm>;
begin
    visibleForms := TList<TForm>.Create();
    try
        for ii := 0 to Screen.FormCount - 1 do
        begin
            if Screen.Forms[ii].Visible then
                visibleForms.Add(Screen.Forms[ii]);
            Screen.Forms[ii].Visible := false;
        end;

        form3 := TForm3.Create(nil);

        SetWindowPos(form3.Handle, // handle to window
            HWND_TOPMOST, // placement-order handle
            form3.Left, // horizontal position
            form3.Top, // vertical position
            form3.Width, form3.Height,
            // window-positioning options
            SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE);

        form3.ShowModal();
        form3.Free();
    finally
        for ii := 0 to visibleForms.Count - 1 do
            visibleForms[ii].Visible := true;
        visibleForms.Free();
    end;
end;