模态对话框关闭时,Delphi CMExit消息未发送?

时间:2009-04-06 17:34:13

标签: delphi validation focus delphi-5

在我正在处理的应用程序的一部分中,有一个表单控件在接收CMExit消息时进行验证,这正是Delphi文档所说的(这段代码示例来自Delphi帮助)文件):

procedure TDBCalendar.CMExit(var Message: TWMNoParams);
begin
 try
  FDataLink.UpdateRecord;                          { tell data link to update database }
 except
  on Exception do SetFocus;                      { if it failed, don't let focus leave }
 end;
 inherited;
end;

这样做的目的是在控件失去焦点后立即执行验证。因此,例如,如果我单击“确定”按钮,表单控件将失去焦点,此方法将运行,并且异常会将焦点设置回该表单控件。 (因此,“确定”按钮上的“单击”事件将永远不会通过,对话框将永远不会关闭。

我遇到的问题是这个表单控件位于模态对话框窗口中。单击确实确实发送CMExit消息并导致记录更新(并进行验证)。但是,在窗体控件中按Enter键会导致模式对话框关闭而不发送CMExit消息。好像表单控件从不“失去焦点”。这意味着不仅在没有表单实际验证数据的情况下关闭对话框,而且数据集也不会更新。

鉴于此问题,我放置数据集更新/验证代码的最佳位置在哪里?我可以将它移动到对话框表单本身并在OnCloseQuery处理程序中实现它,但这意味着逻辑在表单本身的表单控件中都是重复的。 (表单控件在其他地方使用,我想避免改变它的行为。)

(我推测CMExit没有被触发,因为控件实际上 没有失去焦点。表单已关闭,但表单控件仍然“关注”关闭表单。)

1 个答案:

答案 0 :(得分:7)

关闭表单不一定会触发TControl的退出事件。例如,用户可以按Alt-F4。

我建议将验证移到单独的proc中,并从出口 on-close事件中调用单独的proc。

以下代码应该无需太多修改即可运行:

function TDBCalendar.UpdateSuccessful: boolean;
begin
  { tell data link to update database }
  { if successful, return True, else return False }
  { this function must be Public if a form is gonna check this value }
  Result := True;
  try
    FDataLink.UpdateRecord;
  except on Exception do
    Result := False;
  end;
  inherited;
end;

procedure TDBCalendar.CMExit(var Message: TWMNoParams);
begin
  //if not valid, then don't let them leave
  if not(UpdateSuccessful) then begin
    SetFocus;
  end;
end;

///////////////////////////////////////////
//on the form that contains your control...
///////////////////////////////////////////

procedure TMyForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  //if not valid, then don't let them close the form
  if not(dbcal.ControlIsValid) then begin
    Action := caNone;
  end
  else begin
    inherited;
  end;
end;