これは既知の問題です。最後のフォーカス変更が完了する前にフォーカスを変更すると、Windowsに問題が発生します(たとえば、フォーカスがからEdit1
に変更され始めますがEdit2
、Edit1.OnExit
フォーカスを別のコントロールまたはフォームに変更するために何かを実行します。
これは、たとえば、アプリがOnExit
イベントで検証を実行しようとし、検証が失敗したときにフォーカスを元のコントロールに戻そうとした場合に発生します。
最も簡単な解決策は、代わりにフォームハンドルにメッセージを投稿し、OnExit
そこでフォーカスの変更の必要性を処理することです。ターゲットコントロールが入力フォーカスを取得すると起動し、Windowsが混乱することはありません。
const
UM_EDIT1_EXITED = WM_USER + 1;
type
TForm1=class(TForm)
...
private
procedure UMEdit1Exited(var Msg: TMessage); message UM_EDIT1_EXITED;
end;
implementation
procedure TForm1.Edit1Exit(Sender: TObject);
begin
PostMessage(Handle, UM_EDIT1_EXITED, 0, 0);
end;
procedure TForm1.UMEdit1Exited(var Msg: TMessage);
begin
// Show your other form here
end;
TeamBのPeterBelow博士による古いBorlandNG投稿から:
これが「OnExitからのダイアログを表示する」問題に関する私の一般的な説教です。
OnExitハンドラーがトリガーされた場合(これはWindowsメッセージWM_KILLFOCUSに応答して発生します)、Windowsはフォーカス変更の最中です。別のフォーカス変更を引き起こすハンドラーで何かを行うと(メッセージボックスのポップアップやSetFocus呼び出しの実行など)、Windowsはひどく混乱します。カーソルの欠落はその症状です。
OnExitハンドラーからユーザーにメッセージを表示する必要がある場合は、次のようにします。
フォームの型宣言の上にある、ユニットのインターフェイスセクションのどこかにユーザーメッセージの定数を定義します。
'Const UM_VALIDATE = WM_USER + 200;'
フォームにこのメッセージのハンドラーを指定します。これは、クラス宣言のプライベートセクションに配置するのが最適です。
Procedure UMValidate( Var Msg: TMessage ); message UM_VALIDATE;
フィールドの内容に問題がある場合は、OnExitハンドラーからフォームにUM_VALIDATEメッセージを送信します。メッセージのwparamパラメーターとlparamパラメーターで、エラー番号やSenderオブジェクトなどの追加情報を渡すことができます。実際、UMValidateハンドラーで検証全体を実行できます。