多个应用窗口激活无法正常工作

mj2*_*008 3 windows delphi focus

我有一个Delphi应用程序,它有一个文档浏览器作为主要表单.当用户打开文档时,我们打开一个编辑器窗口.我们希望每个编辑器在任务栏上都有一个按钮,以及主窗体.我已经应用了常规代码来执行此操作(下面),但是当我在使用编辑器窗口后单击主窗体时,编辑器将保持在顶部,而焦点位于主窗体上.我无法解决导致此行为的原因.

舞台设置:我打开主表单和文档表单.

  1. 点击另一个应用程序,点击主表单,主表单保持专注.(按预期行事.)

  2. 单击文档表单,单击主表单,文档表单返回到前面,但显示为非活动状态.(图为结果)

替代文字http://www.matthew-jones.com/temp_xfer/titlebarfailure.jpg

第一步,这是Delphi 2007,我在项目中:

Application.MainFormOnTaskBar := True;
Run Code Online (Sandbox Code Playgroud)

对于主表单,我没有其他代码.

对于文件表格,我有

procedure TCommonEditForm.CreateParams(var params: TCreateParams);
begin
  inherited;
  params.WndParent := 0; // GetDeskTopWindow; no diff
end;
Run Code Online (Sandbox Code Playgroud)

我试图弄清楚是否有消息使这种情况发生,但找不到合适的东西.我在代码中搜索了与"激活"有关的任何内容.线索欢迎!

Mar*_*der 6

我的应用程序以您描述的方式工作.这是我采取的方法.我本来希望找到一种更简单的方法,但从未做过.

我从阅读这些文章开始.第一个是Peter Peter写的一篇很棒的文章:

http://groups-beta.google.com/group/borland.public.delphi.winapi/msg/e9f75ff48ce960eb?hl=en

此处还发现了其他信息,但这并不是一个有效的解决方案:供我使用:http: //blogs.teamb.com/DeepakShenoy/archive/2005/04/26/4050.aspx

最终这就是我最终的结果.

我的启动画面兼作应用程序主窗体.Main表单与Application Object有特殊关系.使用所有辅助表单可以获得我正在寻找的行为.

在我想要在任务栏上的每个表单中,我重写CreateParams.我在我的编辑表单上执行此操作以及用户将其视为"主要表单"

procedure TUaarSalesMain.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  Params.ExStyle := Params.ExStyle or WS_EX_APPWINDOW;
  Params.WndParent := GetDesktopWindow;
end;
Run Code Online (Sandbox Code Playgroud)

就Delphi而言,我的"主"形式在其Activitate函数中加载了真正的主要形式.我使用成员变量来跟踪第一次激活.然后在函数的末尾我隐藏了初始形式,但是不要关闭它.这对我来说很重要,因为如果用户正在编辑文档并关闭主表单,我不希望同时强制关闭编辑屏幕.这样,所有可见形式都被视为相同.

    if FFirstActivate = false then
      exit;

    FFristActivate := false;

    /* 
       Main Load code here 
       Update Splash label, repaint
       Application.CreateForm
       etc.
    */


    // I can't change visible here but I can change the size of the window
    Self.Height := 0;
    Self.Width := 0;
    Self.Enabled := false;

    //  It is tempting to set Self.Visible := false here but that is not
    // possible because you can't change the Visible status inside this
    // function.  So we need to send a message instead.
    ShowWindow(Self.Handle, SW_HIDE);

  end;
Run Code Online (Sandbox Code Playgroud)

但仍有问题.当所有其他表单都关闭时,您需要关闭主/启动窗口.我在Parent <> nil的关闭例程中有一个额外的检查,因为我使用表单作为插件(形成我的目的,它们比帧更好).

我真的不喜欢使用Idle事件,但我没有注意到这是对CPU的拖累.

{
  TApplicationManager.ApplicationEventsIdle
  ---------------------------------------------------------------------------
}
procedure TApplicationManager.ApplicationEventsIdle(Sender: TObject;
  var Done: Boolean);
begin

  if Screen.FormCount < 2 then
    Close;
end;

{
  TApplicationManager.FormCloseQuery
  ---------------------------------------------------------------------------
}
procedure TApplicationManager.FormCloseQuery(Sender: TObject;
  var CanClose: Boolean);
var
  i: integer;
begin

  for i := 0 to Screen.FormCount - 1 do
  begin
    if Screen.Forms[i] <> self then
    begin
      // Forms that have a parent will be cleaned up by that parent so
      // ignore them here and only attempt to close the parent forms
      if Screen.Forms[i].Parent = nil then
      begin
        if Screen.Forms[i].CloseQuery = false then
        begin
          CanClose := false;
          break;
        end;
      end;
    end;
  end;

end;

{
  TApplicationManager.FormClose
  ---------------------------------------------------------------------------
}
procedure TApplicationManager.FormClose(Sender: TObject;
  var Action: TCloseAction);
var
  i: integer;
begin

  for i := Screen.FormCount - 1 downto 0 do
  begin
    if Screen.Forms[i] <> self then
    begin
      // Forms that have a parent will be cleaned up by that parent so
      // ignore them here and only attempt to close the parent forms
      if Screen.Forms[i].Parent = nil then
      begin
        Screen.Forms[i].Close;
      end;
    end;
  end;

end;
Run Code Online (Sandbox Code Playgroud)

到目前为止,这对我很有帮助.我确实对Vista进行了一些小改动,因为我的"Main/Splash"屏幕的图标仍在显示.我不记得那是什么了.我可能不需要设置宽度,高度,启用,并在启动屏幕上发送隐藏消息.我只是想确保它没有出现:-).

处理近距离事件是必要的.如果我没记错,当Windows发送关机消息时需要这样做.我认为只有主要表单才能获得该消息.