fsStayOnTop窗体隐藏的模态窗体
我有一个窗体(下面例子中的TBigForm),它允许操纵一些复杂的数据并需要显示其他信息。我把这个信息放在一个fsStayOnTop窗体中(示例中的OnTopForm),以确保它始终可见,但如果有必要的话可以移出。现在,当TBigForm中的某些用户操作显示一种模式形式时,这通常会隐藏在OnTopForm后面,这使得应用程序看起来像冻结了。我怎样才能避免这种情况? (搜索产量很多很多点击,但我无法提炼出他们的解决方案。)fsStayOnTop窗体隐藏的模态窗体
在我的真实应用程序中有很多显示模式窗体的地方,所以我想避免更改所有这些电话。
例:创建一个新的VCL应用程序,滴在Form1上的一个TButton,双击该按钮并用以下替换生成Button1Click实现存根:
type
TBigForm = class(TForm)
strict private
OnTopForm: TForm;
Button1: TButton;
procedure Button1Click(Sender: TObject);
protected
procedure DoHide; override;
procedure DoShow; override;
public
constructor Create(AOwner: TComponent); override;
end;
{ TBigForm }
procedure TBigForm.Button1Click(Sender: TObject);
begin
ShowMessage('Test');
end;
constructor TBigForm.Create(AOwner: TComponent);
begin
inherited CreateNew(AOwner);
Caption := 'Big form';
WindowState := wsMaximized;
Button1 := TButton.Create(Self);
Button1.Parent := Self;
Button1.Caption := 'Freeze!';
Button1.SetBounds(10, 10, 100, 100);
Button1.OnClick := Button1Click;
end;
procedure TBigForm.DoHide;
begin
OnTopForm.Free;
inherited DoHide;
end;
procedure TBigForm.DoShow;
begin
inherited DoShow;
OnTopForm := TForm.Create(Self);
OnTopForm.Caption := 'Important information';
OnTopForm.BorderStyle := bsToolWindow;
OnTopForm.FormStyle := fsStayOnTop;
OnTopForm.Position := poScreenCenter;
OnTopForm.Show;
end;
{ TForm1 }
procedure TForm1.Button1Click(Sender: TObject);
var
f: TBigForm;
begin
f := TBigForm.Create(nil);
try
f.ShowModal;
finally
f.Free;
end;
end;
启动应用程序,点击“按钮1“,然后在”冻结!“。
(BTW:我们使用D2007)显示另一种形式,模式
更改您的OnTopform暂时的FormStyle前:
procedure TBigForm.Button1Click(Sender: TObject);
begin
OnTopForm.FormStyle := fsNormal;
ShowMessage('Test');
OnTopForm.FormStyle := fsStayOnTop;
end;
应该为你想要的工作...
谢谢!这似乎工作,但它需要操纵ShowModal,ShowMessage等每个调用 - 我想避免这种情况。使用Application.OnModalBegin在这里没有帮助,因为如果嵌套ShowModal调用,它只会被调用一次。 :-( – 2010-08-04 19:26:47
尝试将模式窗体的PopupParent属性设置为StayOnTop窗体,或者在调用ShowModal()之前将Application.ModalPopupMode属性设置为pmNone以外的内容。
前者会更改应用程序的窗口层次结构 - StayOnTop窗体将保留在模态窗体下,而后者也无济于事,因为'ShowMessage'是从模态窗体调用的,但StayOnTop窗体是不同的形式,它仍然会保持在顶端 – 2010-08-05 23:15:55
你可以两种方式,你说问题是模式窗口滞留在StayOnTop窗口后面,所以显然模态窗口需要显示在顶部。 ,只需在调用ShowModal()之前将模式窗口移动到StayOnTop窗口之外的区域,对于ShowMessage(),它将显示一个模态TForm,并且受此TApplication.ModalPopupMode属性的约束 – 2010-08-05 23:58:33
正如我所看到的,问题不在于StayOnTop表单中卡住的模式表单,而是ShowMessage表单在StayOnTop表单下卡住了,并且由于ShowMessage是从Modal表单调用的nd **不是从StayOnTop表单获得的,它将不会被StayOnTop表单所有..使用任何ModalPopupMode ... – 2010-08-06 00:47:15
这里您伪善
Create an global TApplicationEvents
Declare an global var to keep track of modal form count
Hookup the OnMessage
var
Ctrl: TControl;
if Msg.hwnd <> 0 then
case Msg.message of
CM_ACTIVATE,
CM_DEACTIVATE:
begin
Ctrl := FindControl(Msg.hwnd);
if Ctrl is TForm then
if fsModal in TForm(Ctrl).FormState then
begin
if Msg.message = CM_ACTIVATE then
Inc(Modal form count var)
else
Dec(Modal form count var);
add more logic based on Modal form count var
end;
end;
end;
玩得开心
我无法获取Inc/Dec行被调用 - Ctrl始终为零。你在我的示例应用程序中尝试过吗? – 2010-08-05 09:11:12
procedure TForm1.ScreenOnActiveFormChange(Sender: TObject);
begin
if (Screen.ActiveForm <> nil) then
begin
if (Screen.ActiveForm.Handle <> Application.MainForm.Handle) then
with Screen.ActiveForm do
SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE or SWP_NOSIZE);
Windows.SetForeGroundWindow(Screen.ActiveForm.Handle);
end;
end;
这应该工作。
这很有趣 - 在3.5年后,一片茫然,没有任何评论。 – 2014-02-06 17:16:45
这是一个upvote抵消downvote。 – Shannon 2014-12-07 04:31:08
@Shannon,谢谢! :-) – 2014-12-07 09:24:52