2010-11-22 21 views
6

通常、ShowModalを使用してダイアログを開くと、ダイアログが閉じられるまで現在のスレッドの実行が停止します。私はモーダルダイアログを表示したいが、ダイアログがまだ開いている間は現在のスレッドで実行を続ける。 「モーダル」とモーダルダイアログを非同期に開く

私は単純にモーダルダイアログが閉じられるまで、ユーザーがアプリケーションの他の形態のいずれかと相互作用しないことを意味します。

デルファイShowModal機能は、私が必要とする1つに、「モーダル」のわずかに異なる定義を提供する:

モーダルフォームは、フォームが閉じられるまで、アプリケーションを実行し続けることができないものです。

現在、私はこのようなコードを持っている:私はまだ親ウィンドウと対話することができますを除いて、私は表示されない方法

(など、それを閉じて、それを周りに移動)、

dialog.Parent:=self; 
dialog.Show; 
// keep doing stuff... 

この作品をShowModalを使用せずに、ユーザーが親ウィンドウとやりとりするのを止めるフォーム?

答えて

6

Delphi \ Source \ VCL \ Forms.pasのソースコードを開き、ShowModalの実装を開きます。次に、それがどのように機能するかを学びますCodeGearのIPであるので、ここでソースコードをコピーすることはできませんが、これを自分で簡単に実行し、コードの一部を再利用することができます。

+1

これは機能しているようです。私はShowModalを2つの関数に分割しました。 ShowModalNonBlockingおよびCloseModalNonBlocking。私はコンパイルされないコードをいくつか削除しなければならなかった。私はもっ​​と良い解決策があることを望んでいるが、これは私が今までに見つけた最良の提案である。 – awmross

+0

私はあなたがコードを投稿できないことを知っていますが、 "split at line X"のようなヒントを投稿できますか? – Mawg

+1

@Mawg "ShowModalNonBlocking"関数は "Show()"を呼び出して終了しました。 "CloseModalNonBlocking"は、ダイアログを無効にするためのWindowsメッセージを送信することによって開始されました。希望は助ける? – awmross

6

モーダルフォームが開いていても、メインスレッドはまだ実行されます(そうでなければ、モーダルフォームはそれ自身を再描画できませんでした)。

しかし、モーダルフォームは独自のイベントループを持ち、元のアプリケーションイベントループの実行を妨げます。

彼らは、としてそうでなければ、イベントが戻ってさらに別のモーダルフォームまたはメッセージボックスを作成し、メインイベントループにこっそり持っている可能性があります(Windowsメッセージボックスも同様に持っているだけのよう)に持っています。

そして、その種類はモーダルであることの全体のポイント否定:UIスレッドごとに1つだけのモーダルフォームまたはメッセージボックスがあることができます。

だから、あなた自身にこの質問をする必要があります。

What actions in the main event loop does this modal form prevent from happening?

はその後、別のスレッドにそれらのアクションを移動します。

--jeroen

+1

私は同意しません。 'ShowModal'は、他のフォームを無効にし、新しいフォームを表示してから、メッセージループを実行します。メッセージループ*が 'ShowModal'に属する必要があることは特にありません。代わりに 'TApplication.Run'のものになる可能性があります。一度に複数のモーダルダイアログが存在することは間違いありません。あなたのモーダルフォームから別のフォームを表示するだけです。ただし、アクティブなものは1つだけです。他は無効になります。 –

+0

@Rob:面白い考え。モーダルウィンドウを親アプリケーション(http://en.wikipedia.org/wiki/Modal_window)に戻す前にユーザーが処理する必要がある場合、その親アプリケーションが新しい後続モーダルウィンドウをどのように開始するか最初のモーダルウィンドウ以外の場所? –

+0

アプリケーションが最初のモーダルウィンドウを開始したのと同じ方法:アクティブなウィンドウをすべて無効にし、別のウィンドウを表示する。好ましくは、現在アクティブなウィンドウを新しいウィンドウの親として使用する。 –

5

がいる限り、あなたのダイアログが表示されているとして、あなたの親フォームを無効にし、これはそれを相互作用からユーザーを防ぐことができます。 DisableTaskWindowsを使用して、親フォームだけでなくすべてのフォームを無効にすることもできます。これは文書化されていませんが、 'forms.pas'のTCustomForm.ShowModalでどのように使われているのか分かります。