windows Delphi - 如何防止 Forms/MsgBoxes 在先前的表单下移动?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2997079/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Delphi - How to prevent Forms/MsgBoxes to move under prior form?
提问by durumdara
Many times after the Windows 98 era we have experienced that some dialogs lose their Z-Order and move back to the prior form.
在 Windows 98 时代之后,我们多次经历过某些对话框失去了 Z 顺序并返回到之前的形式。
For example:
例如:
Dialog1.ShowModal;
Dialog1.OnClickButton() : ShowMessage('anything');
When MessageBox appears, it sometimes doesn't have focus and is moved under Dialog1. The users are confused about it, they say: My application froze!!! But if they use Alt+Tab to move to another app and back, the focus returns to the MessageBox and it will be the foreground window.
当 MessageBox 出现时,它有时没有焦点并移动到 Dialog1 下。用户对此感到困惑,他们说:我的应用程序冻结了!!!但是如果他们使用 Alt+Tab 移动到另一个应用程序并返回,焦点将返回到 MessageBox 并且它将是前台窗口。
We have experienced this with ShowMessage, MessageBox, normal forms, and also QuickReport forms.
我们在 ShowMessage、MessageBox、普通表单以及 QuickReport 表单中都经历过这种情况。
Does anyone know about this? Is it a Windows bug? How can you prevent it? How to catch this?
有没有人知道这个?这是Windows错误吗?你怎么能预防呢?怎么抓这个?
Thanks for your help: dd
感谢您的帮助:dd
I really said that AFTER Win98, so all OSs (Win7 also) are affected by this problem. We used Delphi 6 Prof, so the properties are not working with Default forms.
我真的是说在Win98之后,所以所有的操作系统(Win7也是)都会受到这个问题的影响。我们使用了 Delphi 6 Prof,因此这些属性不适用于默认表单。
Somebody said that message dialogs are controllable with MessageBox + MB_APPLMODAL. This is good news, but we have many old forms and components, third party tools.
有人说消息对话框可以用MessageBox + MB_APPLMODAL 来控制。这是个好消息,但我们有许多旧的表单和组件,第三方工具。
So it is hard work to make a completely new application with substitution of the forms.
因此,通过替换表格来制作全新的应用程序是一项艰巨的工作。
But we will try doing this.
但我们会尝试这样做。
I think the answer is this is a half application problem and half a Windows problem. If Windows sometimes handles this, and sometimes doesn't - that seems to be a Windows bug. But if we can force good modal window making then it is a programming bug.
我认为答案是这一半是应用程序问题,一半是 Windows 问题。如果 Windows 有时处理这个,有时不处理 - 这似乎是一个 Windows 错误。但是,如果我们可以强制制作良好的模态窗口,那么它就是一个编程错误。
Can somebody explain to me what is the meaning of the WS_POPUP flag? Does it have some side effect or not?
有人可以向我解释 WS_POPUP 标志的含义是什么吗?它是否有一些副作用?
Thanks: dd
谢谢:dd
采纳答案by Craig Stuntz
That's what the PopupMode
and PopupParent
propertiesare for.
这就是PopupMode
和PopupParent
属性的用途。
E.g., you can do:
例如,你可以这样做:
Dialog1.PopupMode := pmExplicit;
Dialog1.PopupParent := self;
Dialog1.ShowModal;
This tells Windows the correct Z-order.
这会告诉 Windows 正确的 Z 顺序。
回答by Warren P
For old versions of delphi (prior to Delphi 2007), on forms OTHER than your main form:
对于旧版本的 delphi(Delphi 2007 之前的版本),在除主窗体之外的窗体上:
interface
TMyForm = Class(TForm)
protected
procedure CreateParams(var Para: TCreateParams); override;
end;
...
implementation
...
procedure TMyForm.CreateParams(var Para: TCreateParams);
begin
inherited;
Para.Style := Para.Style or WS_POPUP;
{ WinXP Window manager requires this for proper Z-Ordering }
// Para.WndParent:=GetActiveWindow;
Para.WndParent := Application.MainForm.Handle;
end;
For message boxes include MB_TOPMOST in your flags:
对于消息框,在您的标志中包含 MB_TOPMOST:
Application.MessageBox(PChar(amessage), PChar(atitle), otherflags or MB_TOPMOST);
回答by Mike Versteeg
I looked at this page and the FAQ for half an hour and still can't find how to post a comment, so forgive me for this breach of protocol.
我看了这个页面和常见问题半个小时,仍然找不到如何发表评论,所以请原谅我违反协议。
First of all I'd like to make clear that the poster, IMHO, is not using Windows 98. He writes "after Windows 98 era" which I understand means he is having this problem with Windows versions after 98.
首先,我想澄清一下,恕我直言,海报没有使用 Windows 98。他写道“在 Windows 98 时代之后”,我理解这意味着他在 98 之后的 Windows 版本中遇到了这个问题。
As I am having this problem too (CB2009), I'd like to emphasize the poster's question "Is it Windows bug?", which I have not seen answered. If it's a Delphi/Builder bug, maybe there is a way to avoid it? I can't see how intercepting all potential dialogs is a workable solution, nor avoid using fsStayOnTop. I have a settings form that needs to stay on top of my main form, but the settings form can and will popup dialogs that under certain conditions will disappear under the settings form.
因为我也有这个问题(CB2009),我想强调一下海报的问题“它是 Windows 错误吗?”,我没有看到答案。如果是 Delphi/Builder 错误,也许有办法避免它?我看不出拦截所有潜在的对话框是一个可行的解决方案,也无法避免使用 fsStayOnTop。我有一个设置表单需要保留在我的主表单之上,但是设置表单可以并且会弹出对话框,在某些情况下这些对话框会在设置表单下消失。
It would be very helpful if I would understand where the support of z-order goes wrong, as it may offer a clue on how to avoid it.
如果我能理解 z-order 的支持在哪里出错,那将非常有帮助,因为它可能提供有关如何避免它的线索。
回答by Jerry Gagnon
A trick I've used recently was to apply these two lines of code during the creation of each form:
我最近使用的一个技巧是在每个表单的创建过程中应用这两行代码:
SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or
WS_EX_APPWINDOW or WS_EX_TOPMOST);
SetWindowLong(Handle, GWL_HWNDPARENT, GetDesktopWindow);
Handle is the handle of the form (Form1.Handle). The WS_EX_APPWINDOW part makes each window appear on the task bar, remove it if you don't want that additional effect.
句柄是窗体的句柄(Form1.Handle)。WS_EX_APPWINDOW 部分使每个窗口都出现在任务栏上,如果您不想要额外的效果,请将其删除。
For my main form I use this line:
对于我的主要表格,我使用这一行:
SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or
WS_EX_TOPMOST);
I also use this function to help build my custom dialogs (I created a new function for each style of dialog - error, confirmation, etc.):
我还使用此函数来帮助构建我的自定义对话框(我为每种对话框样式创建了一个新函数 - 错误、确认等):
function CustomDlg(const AMessage : string; const ADlgType: TMsgDlgType;
const AButtons: TMsgDlgButtons; const ADefaultButton: TMsgDlgBtn) : TForm;
begin
Result := CreateMessageDialog(AMessage, ADlgType, AButtons, ADefaultButton);
with Result do
begin
SetWindowLong(Handle, GWL_EXSTYLE, GetWindowLong(Handle, GWL_EXSTYLE) or
WS_EX_APPWINDOW or WS_EX_TOPMOST);
SetWindowLong(Handle, GWL_HWNDPARENT, GetDesktopwindow);
FormStyle := fsStayOnTop;
BringToFront;
end;
end;
The FormStyle := fsStayOnTop;
part is optional, of course, but I use it to make sure my confirmation and error dialogs are always visible to the user.
FormStyle := fsStayOnTop;
当然,该部分是可选的,但我使用它来确保用户始终可以看到我的确认和错误对话框。
It seems like a bit of work but the net effect is that I no longer have to worry about forms accidentally hiding behind other forms.
这似乎有点工作,但最终效果是我不再需要担心表单不小心隐藏在其他表单后面。