Forms 像SendToBack这样的东西

Forms 像SendToBack这样的东西,forms,delphi,z-order,Forms,Delphi,Z Order,大家好 我想在我的应用程序中将不同形式的工作模拟为不同的程序。 所有表单在任务栏上都有自己的按钮,应用程序的mainform不可见,Application.ShowMainForm:=false。 但是如果我显示两个窗体,然后打开一些覆盖这两个窗体的程序,然后打开第一个窗体(第二个窗体在某些程序后面),然后关闭第一个窗体,第二个窗体在某些程序前面激活并恢复。 我知道它会恢复,因为在关闭第一个窗体后,我的应用程序会保持活动状态,这就是为什么会显示第一个可见窗体。如何防止恢复第二个表单?似乎我需要在

大家好

我想在我的应用程序中将不同形式的工作模拟为不同的程序。
所有表单在任务栏上都有自己的按钮,应用程序的mainform不可见,Application.ShowMainForm:=false。

但是如果我显示两个窗体,然后打开一些覆盖这两个窗体的程序,然后打开第一个窗体(第二个窗体在某些程序后面),然后关闭第一个窗体,第二个窗体在某些程序前面激活并恢复。

我知道它会恢复,因为在关闭第一个窗体后,我的应用程序会保持活动状态,这就是为什么会显示第一个可见窗体。如何防止恢复第二个表单?似乎我需要在关闭后发送回我的应用程序,但我不知道如何发送

@大卫·赫弗南
这一切的背后其实是窗户。当你的一个朋友 窗体关闭时,Windows也必须决定将焦点移动到何处。 它选择将其移动到流程中的另一个顶级窗口, 因为有一个可见的存在。它通过发送窗口来实现这一点 它选择WM_SETFOCUS消息。毫无疑问,你能截获这个 阻止它发生

我曾试图在我的窗口上设置WM_SETFOCUS,但没有这样的消息

type
  TfMyForm = class(TForm)  
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    FOldWindowProc: TWndMethod;
    procedure NewWindowProc(var Message: TMessage);
  end;

implementation

procedure TfMyForm.FormCreate(Sender: TObject);
begin
  FOldWindowProc := WindowProc;
  WindowProc := NewWindowProc;
end;

procedure TfMyForm.NewWindowProc(var Message: TMessage);
begin
  if Message.Msg = WM_SETFOCUS then
    Beep;
  FOldWindowProc(Message);
end;

这是我自己找到的解决办法

procedure SwitchToPreviousWindow(AHandle: HWND);
var PrevWindow: HWND;
begin
  PrevWindow := GetNextWindow(AHandle, GW_HWNDNEXT);
  while PrevWindow <> NULL do
  begin
    if IsWindowVisible(PrevWindow) then
    begin
      SetForegroundWindow(PrevWindow);
      Exit;
    end;
    PrevWindow := GetNextWindow(PrevWindow, GW_HWNDNEXT);
  end;
end;

procedure TfMyForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  SwitchToPreviousWindow(Self.Handle);
end;
过程切换到上一个窗口(AHandle:HWND);
var-PrevWindow:HWND;
开始
PrevWindow:=GetNextWindow(AHandle,GW\uHwnNext);
而PrevWindow NULL做什么
开始
如果IsWindowVisible(PrevWindow),则
开始
SetForegroundWindow(PrevWindow);
出口
终止
PrevWindow:=GetNextWindow(PrevWindow,GW\uHwnNext);
终止
终止
过程TfMyForm.FormClose(发送方:TObject;var操作:TCloseAction);
开始
切换到上一个窗口(自身手柄);
终止

这是我自己找到的解决方案

procedure SwitchToPreviousWindow(AHandle: HWND);
var PrevWindow: HWND;
begin
  PrevWindow := GetNextWindow(AHandle, GW_HWNDNEXT);
  while PrevWindow <> NULL do
  begin
    if IsWindowVisible(PrevWindow) then
    begin
      SetForegroundWindow(PrevWindow);
      Exit;
    end;
    PrevWindow := GetNextWindow(PrevWindow, GW_HWNDNEXT);
  end;
end;

procedure TfMyForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  SwitchToPreviousWindow(Self.Handle);
end;
过程切换到上一个窗口(AHandle:HWND);
var-PrevWindow:HWND;
开始
PrevWindow:=GetNextWindow(AHandle,GW\uHwnNext);
而PrevWindow NULL做什么
开始
如果IsWindowVisible(PrevWindow),则
开始
SetForegroundWindow(PrevWindow);
出口
终止
PrevWindow:=GetNextWindow(PrevWindow,GW\uHwnNext);
终止
终止
过程TfMyForm.FormClose(发送方:TObject;var操作:TCloseAction);
开始
切换到上一个窗口(自身手柄);
终止

您是如何将任务栏按钮放在那里的?过程TfMyForm.CreateParams(var-Params:TCreateParams);开始继承CreateParams(参数);Params.ExStyle:=Params.ExStyle或WS_EX_APPWINDOW;Params.WndParent:=0;终止为什么要使用
WS\u EX\u APPWINDOW
?当然,
WndParent:=0
是这样做的。是的,我在前面的评论中回答了这个问题。抱歉,我不知道如何在注释中格式化代码。我将尝试
SetWindowPos(…,HWND_BOTTOM…)
您是如何将任务栏按钮放在那里的?过程TfMyForm.CreateParams(var-Params:TCreateParams);开始继承CreateParams(参数);Params.ExStyle:=Params.ExStyle或WS_EX_APPWINDOW;Params.WndParent:=0;终止为什么要使用
WS\u EX\u APPWINDOW
?当然,
WndParent:=0
是这样做的。是的,我在前面的评论中回答了这个问题。对不起,我不知道如何在评论中格式化代码。我会尝试设置WindowPos(…,HWND_BOTTOM…)你是个天才。自问自答,你是个天才。自问自答。