多个应用程序窗口激活不能正常工作
我有一个Delphi文档浏览器作为主窗体的应用程序。当用户打开一个文档时,我们打开一个编辑器窗口。我们希望每个编辑器在任务栏上都有一个按钮,以及主窗体。我已经应用了普通代码来做到这一点(下面),但是当我在使用编辑器窗口后单击主窗体时,编辑器仍然处于顶部,而焦点位于主窗体上。我无法弄清楚是什么导致了这种行为。多个应用程序窗口激活不能正常工作
舞台设置:我打开主窗体和文档窗体。
点击其他应用程序,单击主窗体,主窗体保持专注。 (表现为预期的。)
单击文档表格上,单击主窗体上,文件的形式来 后到前,但表现出来的不活跃。 (图为结果)
alt text http://www.matthew-jones.com/temp_xfer/titlebarfailure.jpg
第一步,这是德尔福2007年,我在该项目中:
Application.MainFormOnTaskBar := True;
为主要形式,我也没有额外的代码。
对于文件的形式,我有
procedure TCommonEditForm.CreateParams(var params: TCreateParams);
begin
inherited;
params.WndParent := 0; // GetDeskTopWindow; no diff
end;
我试图找出是否有是实现这一点的消息,但无法找到任何合适。我已经在代码中搜索与“激活”有关的任何内容。线索欢迎!
我的应用程序按照您描述的方式工作。这是我采取的方法。我本来希望找到一个更简单的方法,但从来没有。
我开始阅读这些文章。这首先是一个伟大的写了彼得以下:
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;
我的“主”的形式尽可能德尔福关注负载在其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吗?这将解释这种行为。
不好 - 虽然好想法。 FormStyle是fsNormal。 PopupMode是pmNone。 BorderStyle是bsSizeable。 BorderIcons默认。 – mj2008 2009-04-29 13:15:24
也许在的CreateParams
Params.ExStyle := Params.ExStyle OR WS_EX_APPWINDOW;
添加这个或尝试在这段代码的任何地方。我首先在表单上使用它.OnCreate事件。
SetWindowLong(Wnd, GWL_EXSTYLE,
GetWindowLong(Wnd, GWL_EXSTYLE) or WS_EX_APPWINDOW) ;
这样做的缺点是,如果主窗体最小化其他形式的隐藏藏汉,但当主要形式做恢复。
谢谢 - 已经尝试过,但没有影响(嗯,不是这个问题)。 (我应该提到它,但是我现在已经研究了一两天,并且实际上删除了被注释掉的那一行)。 – mj2008 2009-04-29 14:11:39
隐藏的声音听起来很可怕,但它实际上也可能解决另一个问题。如果没有理想出现,这可能是我的目标。谢谢! – mj2008 2009-04-29 15:10:09