7

コンソールアプリから直接フォームをインスタンス化しようとしています。
奇妙な理由でForm1.Show()、新しく作成したフォームを呼び出すと、すべてのコントロールとフリーズ(HourGlassアイコン)が描画されません。ただし、ShowDialog()を呼び出すと、コンソールに戻る必要があることを除いて、すべてうまくいきますが、できないので、オプションではありません...
フォームを正しく表示するにはどうすればよいですか?私はここで何かが欠けていますか?

OrderControlForm OrderControlBox = new OrderControlForm();
OrderControlBox.BuyEvent += new OrderControl.BuyDelegate(doBuy);
OrderControlBox.SellEvent += new OrderControl.SellDelegate(doSell);
OrderControlBox.Show();

上記のコードは、コンソールユーザーが入力したコマンドに応答して呼び出されます。

編集: これが作業コードです:

        Thread mThread = new Thread(delegate()
        {
            StratControlBox = new StratControl(StratIDs);
            StratControlBox.ShowDialog();
        });

        mThread.SetApartmentState(ApartmentState.STA);

        mThread.Start();

ShowDialog()なぜではなく電話をかけなければならなかったのか、まだわかりませんShow()
後者を使用すると、ペイント後すぐにフォームが「消える」だけです。

4

3 に答える 3

12

その理由はShowDialog、独自のメッセージループを実行するのに対し、実行Showしないためです。を呼び出す代わりに、メッセージループを実行するShowを呼び出す必要があります。Application.Runただし、同期的にループし、フォームが閉じられるまで着信ウィンドウメッセージを処理するため、実質的にはを呼び出すのと同じですShowDialog

したがって、フォームを非同期で表示する場合は、別のスレッドから表示する必要があります。ただし、念のため、を呼び出して、新しいスレッドがアパートメントスレッドを使用していることを確認してnewThread.SetApartmentState(ApartmentState.STA);ください。

また、1つのUIスレッドから1つのメインフォームのみを表示することをお勧めします。そのメインフォームが独自のスレッドからの他のフォームを表示する場合は問題ありませんが、それぞれが独自のスレッドからの複数のフォームを表示しようとすると、問題が発生する可能性があります。

あなたのアップデートについて

Showスレッドからの呼び出しが機能しない理由は2つあります。まず、同期しているため、フォームを閉じるまで戻りません。実行が匿名メソッドを離れるとすぐにスレッドが終了するため、これは重要です。したがって、を呼び出すとShow、すぐに戻り、メソッドを終了してスレッドを終了します。

第2に、フォームが開いたままであっても、同じ理由で、以前と同じように応答しなくなります。WinFormsには、新しい着信ウィンドウメッセージを探して処理し続けるメッセージループが必要です。メッセージループは、と呼ばれるメソッドを呼び出しますWndProc。着信ウィンドウメッセージを処理するメソッドを呼び出すメッセージループがないWndProcと、フォームはユーザーにまったく応答しなくなります。たとえば、マウスドライバがユーザーがマウスボタンを押したことをWindowsに通知すると、WindowsはWM_MOUSEDOWNアプリケーションのメッセージキューにメッセージを投稿します。キューにメッセージがあるかどうかを確認し、それらに基づいて動作するように常にループしているコードがどこかにない場合、マウスダウンイベントが発生することはありません。

前述したように、このShowDialogメソッドは独自のメッセージループを実行するため、機能しますが、Show機能しません。 Showすでに実行中のメッセージループによって呼び出されていることを前提としています。何らかの理由で電話をかけたくない場合は、代わりににShowDialog電話することができます。Application.Run(StratControlBox)このRunメソッドはフォームを表示し、フォームが閉じられるまでメッセージループに留まります。したがって、これはと同じようShowDialogに同期呼び出しであるため、フォームが閉じられるまでスレッドは終了しません。

于 2012-07-10T19:47:30.933 に答える
4

フォームを正しく表示するにはどうすればよいですか?私はここで何かが欠けていますか?

問題は、コンソールアプリケーションがWindowsアプリケーションではなく、Windowsメッセージを処理するための適切な「配管」がないことです。これがないと、フォームは「描画」するための基本的なメッセージなど、アイテムを正しく処理できません。

これは通常、を使用Application.Runしてメッセージ処理を開始することで処理されます。ただし、これはフォームが閉じるまでブロックされます(したがって、コンソールは「実行」を継続しません)。これを処理する方法は、コンソールコードを別のスレッドに移動しApplication.Run、通常のWindowsアプリケーションのようにフォームで使用することです。

于 2012-07-10T19:46:07.890 に答える
-1

.NET 4.7では、簡単に変更できました

myForm.Show()

Task.Run(() => { myForm.ShowDialog(); });

私はすでに使用していました

[STAThread] 
private static void Main(string[] args)
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    .
    .
    .
}

他のいくつかの要件のため。

于 2018-02-28T14:32:46.413 に答える