2009-04-06 11 views
2

私が取り組んでいるアプリケーションの一部では、CMExitメッセージの受信時に検証を行うフォームコントロールがあります。これは、Delphiのドキュメントに記載されているとおりです(このコードサンプルはDelphiのヘルプファイル):モーダルダイアログが閉じられているときにDelphi CMExitメッセージが送信されませんか?

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がトリガされていないと推測している。フォームが閉じられているが、フォームコントロールは、まだ閉じた形の「フォーカスがある」。)クロージング

+0

Cm_Exitは、フォーカス変更イベントです。そこからSetFocusを呼び出さないでください。フォーカスがすでに変化している間は、フォーカスを変更しないでください。代わりに、メッセージを投稿し、それに応答してフォーカスを変更します。 OSはフォーカスを変更している間中断されたくない。実際に何が焦点を当てているのか混乱します。 –

答えて

7

フォームは必ずしもTControlの出口イベントを起動するとは限りません。ユーザーは、たとえばAlt-F4を押すことができます。

私は、検証を別のprocに移動して、終了時のの両方の終了イベントから別々の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; 
関連する問題