2011-02-10 16 views
2

ダイアログのユーザー入力の検証に失敗したときに呼び出すユーティリティルーチンがあります。問題のコントロールにピントを合わせ、ビープ音を鳴らし、ユーザーに適切なメッセージを表示します。問題のコントロールが隠されていない限り、これはうまく機能します。これを、関連するコントロールが何らかの折り畳み可能なグループボックス(おそらくネストされている)の子である状況に適応させる必要があります.SetFocusを呼び出す前に、「祖先」ボックスが展開されていることを確認する必要があります。エラー報告ルーチンに折りたたみ可能なコンポーネントに関する入れ子の子コントロールが表示されていることを確認してください

  • ビルド知識:

    は今、私はいくつかの可能性があります。私はルーチンがむしろ一般的にとどまるべきであるので、それを避けたいと思います。
  • SetFocusの前に(またはその代わりに)呼び出すことができるコールバックを渡します。これは、すべての関連する場所でコールバックを渡すことを忘れてはいけないので、エラーが発生しやすくなります。しかし、私はそのようなことを知らない「あなたとあなたの子コントロールが表示されていることを確認してください」のコンテナコントロールに指示します(おそらくのTWinControl中)
  • 私のお気に入りのソリューションは、おそらくイベント(またはoverrideable法)になります。私はこのような状況を扱うことができる方法を

任意のアイデア?私の意見で

+0

私は「保存」を押すと、突然拡大/移動を開始する形式を中心にガジェット場合FWIWは、ユーザーとして、私はかなり驚くだろう。代わりに通知が必要です。ちょうど私の見解... –

+0

私は知らない。アプリが「あなたは無効なデータを入力していますが、現在あなたが探しているコントロールがどこにあるのか知っていますが、あなたには表示されません」と告げると、私は迷惑になるだろうと思います。 :-) –

+0

Sertacにはポイントがあります!選択を変更したり、木を広げたり、物を動かしたりすると、ユーザーは「文脈を失う」ことになります。そのようなときに、「何か、どこですか」という瞬間があります。より良いアイデアは、データが隠されようとしているときにデータを検証することです。ユーザはまだ手元にあるタスクに集中しています。たとえば、PageControlのOnChangingイベントで現在のTabSheetのコントロールを検証し、問題がある場合は変更をブロックします。 –

答えて

2

は、最善の解決策は、ダイアログ検証ルーチンは、一般的な滞在することができ、すべてのコンテナコントロールについての知識を構築する別のルーチンになり、同時に簡単にテストされ、維持されることを十分に重視されています。線に沿って何か:

procedure ForceControlVisible(C: TControl); 
begin 
    // Recursive code 
    if Assigned(C.Parent) then ForceControlVisible(C.Parent); 
    // Code specific to each container control class 
    if C is TTabSheet then 
    begin 
     // Code that makes sure "C" is the active page in the PageControl 
     // goes here. We already know the PageControl itself is visible because 
     // of the recursive call. 
    end 
    else if C is TYourCollapsibleBox then 
    begin 
     // Code that handles your specific collapsible boxes goes here 
    end  
end; 

仮想メソッドやインターフェイスの実装に依存しているOOPスタイルの方法は、道よりエレガントであってもよいが、使用したいすべてのコントロールのソースコードへのアクセスが必要になります。でも、あなたの場合必要なすべてのソースにアクセスできるので、変更を導入しないことが好ましいです。これらのコントロールをアップグレードするのが難しくなります(サプライヤーから新しいファイルを取得した後で変更内容を再導入する必要があります)。

+0

+1 - TTabSheetは優れた例です。そして、私はVCLソースを変更するつもりはありません。 :-) –

+0

+1。大きな条件を "IVisibilityEnforcer"のようなものを管理するレジストリに置き換えることができます。私は 'RegisterVisibilityEnforcer(TTabSheet、TabSheetVisibilityEnforcer)'と言うことができます。これにより、新しいコントロールの動作を簡単に追加できます。 – jpfollenius

+0

@Ulrich時にはVCLソースを変更するだけです!しかし、それを最小限に保つのが最善です、それは確かです。私はフックでできるだけ修正する傾向があり、裸の最小値だけを再コンパイルする傾向があります(私は3つのVCLユニットで逃げることができます)。 –

1

各コンポーネントは、そのParentを知っています。リストを歩いて各親を見えるようにすることができます。

+1

残念ながら 'C.Visible:= True'では不十分です。 Cの型に応じて、さらに 'C.Expanded:= True'をコールするか、CがPageControlなどのアクティブなシートであることを確認する必要があります。 –

+0

私はあなたの答えを修正しました。 –

+0

@David - ouch :-) thanks –

4
  1. EnsureVisibleのようなメソッドでインターフェイスを定義します。
  2. すべてのコンポーネントに対して実装します(これらのコンポーネントの独自のバージョンを派生させる必要があるかもしれません)。これにより、異なるコントロールが全く異なる振る舞いを持つことができます。
  3. コントロールが表示されていることを確認する必要がある場合、インターフェイスが実装されている場合、コントロールは親を呼び出し、EnsureVisibleを呼び出します。

インターフェイスが気に入らない場合は、カスタムWindowsメッセージで行いますが、基本的な考え方は得られます。

+0

+1 "すべてのコントロール"のカスタマイズされたバージョンを使用するコンセプト。私が使っているすべてのコントロールの派生バージョンを含む1つの巨大なパッケージを設定して、その日のうちにやり遂げました。それらの日の一つ... –

+0

@コスミン私はすでにそこにいます。それは本当に違いがあります! –

関連する問題