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

我有一个Delphi文档浏览器作为主要forms的应用程序。 当用户打开文档时,我们打开一个编辑器窗口。 我们希望每个编辑器都有一个在任务栏上的button,以及主窗体。 我已经应用了正常的代码来做到这一点(下面),但是当我在使用编辑器窗口之后单击主窗体时,编辑器将留在最上面,而焦点位于主窗体上。 我无法弄清楚是什么导致了这种行为。

舞台设置:我打开主窗体和文档窗体。

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

  2. 点击文件表单,点击主窗体,文件表单回到前面,但是显示不活动。 (图片显示结果)

替代文字http://img.zgserver.com/windows/titlebarfailure.jpg

第一步,这是delphi2007年,我在项目中:

Application.MainFormOnTaskBar := True; 

对于主窗体,我没有额外的代码。

对于文件表格,我有

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

我试图弄清楚是否有消息使这种情况发生,但找不到任何适当的东西。 我已经search了“激活”的任何代码。 线索欢迎!

我的应用程序按照您描述的方式工作。 这是我采取的方法。 我本来希望找到一个更简单的方法,但从来没有。

我通过阅读这些文章开始。 这第一个是由彼得下面的伟大的写作:

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

最终,这是我最终结束了。

我的启动画面加倍作为应用程序主窗体。 主窗体与应用程序对象有特殊的联系。 使用所有的辅助形式,让我的行为,我一直在寻找。

在任务栏上的每个表单中,我都会覆盖CreateParams。 我在编辑表单上做这个,用户把它看做是“主要形式”

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

就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; 

但是还有一个问题。 当所有其他表单关闭时,您需要关闭主窗口。 我有一个额外的检查在我的父母<> NIL的关闭例程,因为我使用表单作为插件(形式我的目的,他们比框架更好地工作)。

我真的不喜欢使用空闲事件,但我没有注意到这是对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; 

迄今为止,这已经很好了。 我做了一个Vista的小改动,因为我的“Main / Splash”屏幕的图标还在显示。 我不记得那是什么 我可能不需要设置宽度,高度,启用,并在启动画面上发送隐藏消息。 我只是想确保它没有出现:-)。

处理密切事件是必要的。 如果我没有记错,当windows发送关闭消息时需要这样做。 我认为只有主要的形式得到这个信息。

对不起,如果这真的很愚蠢,但你没有formstyle设置为fsStayOnTop你呢? 这将解释这种行为。

也许在createparams中添加这个

 Params.ExStyle := Params.ExStyle OR WS_EX_APPWINDOW; 

或者在代码的任何地方尝试。 我创造性的使用它的形式.OnCreate事件。

 SetWindowLong(Wnd, GWL_EXSTYLE, GetWindowLong(Wnd, GWL_EXSTYLE) or WS_EX_APPWINDOW) ; 

这样做的缺点是,如果主表单被最小化,其他表单就会隐藏起来,而在主表单的时候会恢复。