我有一个Delphi应用程序,它有一个文档浏览器作为主要表单。当用户打开文档时,我们打开一个编辑器窗口。我们希望每个编辑器在任务栏上都有一个按钮,以及主窗体。我已经应用了常规代码来执行此操作(下面),但是当我在使用编辑器窗口后单击主窗体时,编辑器将保持在顶部,而焦点位于主窗体上。我无法弄清楚导致这种行为的原因。
舞台设置:我打开主表单和文档表单。
点击其他应用,点击主表单,主表单保持专注。 (按预期行事。)
点击文件表格,点击主表格,文件表格到 回到前面,但显示不活跃。 (图片显示结果)
alt text http://www.matthew-jones.com/temp_xfer/titlebarfailure.jpg
第一步,这是Delphi 2007,我在项目中有:
Application.MainFormOnTaskBar := True;
对于主表单,我没有其他代码。
对于文件表格,我有
procedure TCommonEditForm.CreateParams(var params: TCreateParams);
begin
inherited;
params.WndParent := 0; // GetDeskTopWindow; no diff
end;
如果有消息导致这种情况发生,但我找不到合适的东西。我在代码中搜索了与“激活”有关的任何内容。线索欢迎!
答案 0 :(得分:6)
我的应用程序以您描述的方式工作。这是我采取的方法。我本来希望找到一种更简单的方法,但从未做过。
我从阅读这些文章开始。第一篇是彼得下面的一篇很好的写作:
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;
就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;
但仍有问题。当所有其他表单都关闭时,您需要关闭主/启动窗口。我在父亲<>的近距离例程中有一个额外的检查。没有,因为我使用表单作为插件(形成我的目的,他们比帧更好地工作)。
我真的不喜欢使用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;
到目前为止,这对我很有帮助。我确实对Vista进行了一些小改动,因为我的“Main / Splash”屏幕的图标仍在显示。我不记得那是什么了。我可能不需要设置宽度,高度,启用,并在启动屏幕上发送隐藏消息。我只是想确保它没有出现: - )。
处理近距离事件是必要的。如果我没记错,当Windows发送关机消息时需要这样做。我认为只有主要表单才会收到该消息。
答案 1 :(得分:0)
很抱歉,如果这真的很愚蠢,但你没有将formstyle设置为fsStayOnTop吗?这可以解释这种行为。
答案 2 :(得分:0)
或许可以在createparams中添加它
Params.ExStyle := Params.ExStyle OR WS_EX_APPWINDOW;
或在代码中的任何地方尝试此操作。我主要在表格上使用它.OnCreate事件。
SetWindowLong(Wnd, GWL_EXSTYLE,
GetWindowLong(Wnd, GWL_EXSTYLE) or WS_EX_APPWINDOW) ;
这样做的缺点是,如果主窗体最小化,其他窗体也会隐藏,但在主窗体恢复时会恢复。