我有一堆表格,我想让它们自动化,这样它们就可以自己打开和关闭。
我知道如何让它们打开(通过使用OnActivate功能),但我无法关闭它们。
所以,例如,我有
procedure TProgressForm.FormActivate(Sender: TObject);
begin
inherited;
if FModItem.IsInQueue then
begin
RunBtnClick(Self);
ModalResult := mrOK;
end;
end;
运行一个函数。我希望在函数运行后关闭窗口,这就是ModalResult应该做的事情。
(我也尝试在RunBtnClick程序的最后添加ModalResult行,但这也不起作用)
我正在创建这样的表单:
ProgForm := TProgressForm.Create(Self, FModItem);
Self.Visible := False;
try
if ProgForm.ShowModal = mrOK then
begin
Left := ProgForm.Left;
Top := ProgForm.Top;
end;
我已经能够通过向对象检查器中的模态结果添加mrOK来创建关闭表单的按钮,但我似乎无法明确地执行此操作
谁能明白为什么它不起作用?
由于
答案 0 :(得分:15)
不工作的原因是VCL在显示表单后在TCustomForm.ShowModal中主动将ModalResult设置为0,但在开始检查对ModalResult的更改之前。所以在OnActivate和OnShow中,你要早。
解决方案是延迟通知。这可以通过PostMessage完成,如下所示:
const
UM_ACTIVATED = WM_USER + 1;
type
TProgressForm = class(TForm)
procedure FormActivate(Sender: TObject);
private
procedure UMActivated(var Message: TMessage); message UM_ACTIVATED;
end;
...
procedure TProgressForm.FormActivate(Sender: TObject);
begin
PostMessage(Handle, UM_ACTIVATED, 0, 0);
end;
procedure TProgressForm.UMActivated(var Message: TMessage);
begin
{ Your code here }
ModalResult := mrOk;
end;
来源:NLDelphi
答案 1 :(得分:6)
我会覆盖ShowModal
并执行您现在在那里OnActvate
进行的测试。这有两大优点:
OnActivate
启动表单关闭会导致表单在屏幕上“闪烁”:显示并立即关闭。ShowModal
中的操作顺序,因为只有在需要实际显示表单时才会调用它。当然,使用GUI元素(表单)这种方式有点代码味道,因为它基本上使用GUI而不需要用户交互。毫无疑问,这可以使用中间函数进行重构,该函数返回mrOk
并执行RunBtnClick()
无需GUI的操作,并仅在需要时创建Form
。我想这是一种成本效益的情况。
代码:
TMyForm = class(TForm)
....
public
function ShowModal:Integer;override;
end;
function TMyForm.ShowModal:Integer;
begin
if FModItem.IsInQueue then
begin
RunBtnClick(Self);
Result := mrOK;
end
else
Result := inherited ShowModal;
end;
答案 2 :(得分:3)
在ModustResult在TCustomForm.ShowModal中重置为mrNone之前触发OnActivate事件。这意味着将忽略更改OnActivate处理程序中的ModalResult。
function TCustomForm.ShowModal: Integer;
Show;
try
SendMessage(Handle, CM_ACTIVATE, 0, 0); << Your onActivate is called here
ModalResult := 0; << ModalResult is reset
答案 3 :(得分:2)
查看TCustomForm.ShowModal(在forms.pas中):在发送CM_ACTIVATE消息之后 首先检查ModalResult(所述消息触发你的OnActivate调用);实际上,在OnActivate调用返回后,它立即设置为 0 ,所以难怪你的任务无法正常工作。
我不想太乱用这个(你的代码肯定没有通过气味测试),但是你可以尝试添加类似的东西:
if ModalResult=0 then
SendMessage(Handle, CM_ACTIVATE, 0, 0);
到事件处理程序的顶部。