私が取り組んでいるアプリケーションの一部には、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;
これの目的は、コントロールがフォーカスを失うとすぐに検証を実行することです。たとえば、[OK] ボタンをクリックすると、フォーム コントロールはフォーカスを失い、このメソッドが実行され、例外が発生すると、フォーカスがそのフォーム コントロールに戻されます。(したがって、[OK] ボタンの「クリック」イベントは通過せず、ダイアログは閉じません)。
私が抱えている問題は、このフォーム コントロールがモーダル ダイアログ ウィンドウ内にあることです。[OK] をクリックすると、実際に CMExit メッセージが送信され、レコードが更新されます (および検証が行われます)。ただし、フォーム コントロール内で Enter キーを押すと、CMExit メッセージを送信せずにモーダル ダイアログが閉じます。フォーム コントロールが「フォーカスを失う」ことがないかのようです。これは、フォームが実際にデータを検証せずにダイアログが閉じるだけでなく、データ セットも更新されないことを意味します。
この問題を考えると、データセットの更新/検証コードを配置するのに最適な場所はどこですか? これをダイアログ フォーム自体に移動して OnCloseQuery ハンドラーに実装することもできますが、これはフォーム コントロールとフォーム自体の両方でロジックが重複することを意味します。(フォーム コントロールは他の場所で使用されているため、その動作を変更したくありません)。
(コントロールが実際にフォーカスを失うことはないため、CMExit はトリガーされないと推測します。フォームは閉じられますが、フォーム コントロールは閉じたフォームにまだ「フォーカスを持っています」。)