2

私はC#/。NET 3.5/Windowsフォームプログラムに取り組んでいます。モードレスダイアログボックスを作成し、メインフォームから生成された情報で更新したいと思います。他の方向の例をいくつか見つけました。ダイアログボックスからの情報でメインウィンドウが更新されますが、逆方向に進むのに問題があります。ダイアログボックスのGUIが正しく機能しません。マウスカーソルは砂時計です。更新が表示されることもありますが、白いボックスが表示されたり、ダイアログボックスの上にあった他のウィンドウの残骸が表示されたり、フリーズしたりすることがよくあります。

最終的にダイアログボックスにはより複雑な情報が表示されますが、今のところ、メインウィンドウにラベルとして表示されるカウンターを複製しようとしています。ダイアログを起動するには、次のようにします。

    bool secondWindowOpen = false;
    Thread secondWindowThread;
    MyPopupWindow secondWindow;

    delegate void TextBoxDelegate(string message);

    private void buttonPop_Click(object sender, EventArgs e)
    {
        // If the second window is not open, then open it
        if (!secondWindowOpen)
        {
            secondWindowOpen = true;

            secondWindow = new MyPopupWindow();
            secondWindowThread = new Thread(secondWindow.MyMethod);
            secondWindowThread.Start();

        }
        else // Close the second window
        {
            secondWindowOpen = false;
            secondWindow.ShouldStop = true;

            secondWindowThread.Join();                
        }
    }

次のコードでカウンターを更新します。

if (secondWindow != null)
{
    secondWindow.CounterText = args.FrameNumber.ToString();
}

モードレスダイアログボックスを制御するためのコードは次のようになります。テキストフィールドを設定するためのコードがおそらく間違っていることを認めますが、それは私が現在取り組んでいる最高のものです(呼び出し呼び出しは私に問題を与えていました)。

public partial class MyPopupWindow : Form
{
    public MyPopupWindow()
    {
        InitializeComponent();
    }

    public bool ShouldStop
    {
        get { return shouldStop; }
        set { shouldStop = value; }
    }
    private bool shouldStop = false;

    public void MyMethod()
    {            
        this.Show();
        this.Refresh();

        while (!shouldStop)
        {
            Thread.Sleep(100);
            labelCounter.Text = CounterText;
            Refresh();
        }

        this.Close();
    }

    public string CounterText;
}

私の大きな質問は次のとおりです。独自のGUI要素を更新する必要がある場合に、モードレスダイアログボックスを2番目のスレッドに配置するための最良の方法は何ですか。メインウィンドウ/スレッドからこれらのGUI要素を更新するための最良の方法は何ですか?ありがとう!

4

3 に答える 3

1

フォームが機能する方法は、プログラムがメッセージを処理し、処理するフォームにメッセージを渡すループである場合のコアです。フォームがメッセージループに制御を戻さない場合、プログラムは正しく機能しなくなります。スレッドを追加してこれを解決しようとしましたが、そうするとそれ自体が苦痛になります。

フォームに適用されるすべての操作はUIスレッドで実行する必要があるため、スレッドでこれを実行することはできません。BeginInvokeを使用してInvalidateなどの呼び出しをUIスレッドに戻すこともできますが、それは非常に面倒です。多くのスレッドを起動してUIスレッドを生成しようとするよりも、1つのUIスレッドで実行される協調ウィンドウを作成する方がはるかに優れています。彼らのために何かをしている。

これを行うには、フォームを作成してから、メッセージ処理ループに制御を戻します。将来的には、ボタンクリックなどのイベントからウィンドウを閉じることになります。イベントの結果としてウィンドウを更新する必要がある場合は、イベントハンドラーでinvalidateを呼び出してから、戻ります。

于 2012-07-20T17:23:20.103 に答える
0

ジェイソンの提案に基づいて、私は物事を単純化し、実際に機能させることになりました。

まず、2番目のウィンドウを表示するときに新しいスレッドを開始する必要はありません。代わりに、私は次のことを行います。

bool secondWindowOpen = false;
MyPopupWindow secondWindow;

private void buttonPop_Click(object sender, EventArgs e)
{
    // If the second window is not open, then open it
    if (!secondWindowOpen)
    {
        secondWindowOpen = true;
        secondWindow = new MyPopupWindow();
        secondWindow.Show();                
    }
    else // Close the second window
    {
        secondWindowOpen = false;
        secondWindow.Close();
    }
}

次に、2番目のウィンドウのコードを次のように簡略化しました。

public partial class MyPopupWindow : Form
{
    public MyPopupWindow()
    {
        InitializeComponent();
    }

    public string CounterText
    {
        set { labelCounter.Text = value; }
    }
}
于 2012-07-20T19:29:47.400 に答える
0

まず、私はフランス語なので、英語をお詫びします。

次に、問題を理解した場合は、最初のフォームから2番目のフォームのコントロールを更新します。

フォームのTagオブジェクトを使用してください。

  1. フォーム間で送信するデータをストックするクラスを作成します
  2. 次のように、最初のフォームから2番目のフォームのインスタンスを作成します。

    Form2 f = new Form2();
    f.Tag = MyDataObject();

  3. 次のようなフォームを表示します

    f.Show() => Modeless wayまたf.ShowDialog => Modal way

  4. Form2のコンストラクターでは、次のようにTagオブジェクトからコントロールを更新します。

    public Form2()
    {
    MyDataObject do = (MyDataObject)this.Tag;
    MyLabel.Text = do.LabelText;
    }

  5. Form2からメインフォームにそれを行いたい場合は、同じことを行います:

    Form2に

    this.Tag = MyDataObject;
    this.Close();

メインフォームへ:

`MyDataObject do = (MyDataObject)f2.Tag;`

トピックが古いことは知っていますが、これがお役に立てば幸いです

于 2013-10-03T09:59:07.387 に答える