2012-07-20 34 views
1

我正在研究C#/ .NET 3.5/Windows Forms程序。我想創建一個無模式對話框,然後使用主窗體生成的信息對其進行更新。我發現了其他方向的幾個例子 - 來自對話框的信息更新了主窗口,但我遇到了相反的麻煩。對話框中的圖形用戶界面無法正常工作。鼠標光標是沙漏。我有時會看到更新,但我經常看到一個堅實的白色盒子,其他窗口的殘餘物曾經在對話框的頂部,或者它凍結。使用Windows窗體從主窗口更新無模式對話框

最終,對話框將顯示更復雜的信息,但現在我只是想重複出現的主窗口標籤的計數器。要啓動對話,我做到以下幾點:

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元素的最佳方法是什麼?從主窗口/線程更新這些GUI元素的最佳方法是什麼?謝謝!

回答

1

的方式工作形式是,在覈心如果程序是處理消息,並將它們傳遞出到要處理的形式的循環。如果您的表單從不將控制權返回給您的消息循環,則您的程序將停止正常工作你試圖通過添加更多的線程來解決這個問題,但這樣會導致它自己的痛苦。

您可以在一個線程應用於所有操作的表格必須在UI線程做無法做到這一點。 您可以使用BeginInvoke將調用像Invalidate一樣傳遞給UI線程,但這會變得非常混亂 - 編寫在一個UI線程上運行的協作窗口要比觸發大量線程然後嘗試製作UI線程要好得多爲他們做事。

爲此,您將創建表單,然後將控制權返回給您的消息處理循環。在未來的時間,您可以通過點擊按鈕等事件關閉窗口。如果您需要更新窗口作爲任何事件的結果,您可以在事件處理程序中調用invalidate,然後返回。

+0

感謝。我並不熟悉Windows Forms在封面上的工作方式,因此您的解釋有所幫助。最初我開始按照你的建議來做,但是當我失敗時,我最終陷入了你看到的多線程混亂中。現在它正在工作。我會發佈一個我當前代碼的例子。 – GrandAdmiral 2012-07-20 19:31:43

0

根據Jason的建議,我最終簡化了一些事情,並將其付諸實踐。

首先,當我顯示第二個窗口時不再啓動新線程。相反,我做到以下幾點:

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(); 
    } 
} 

然後,我簡化了代碼在第二個窗口爲以下內容:

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

    public string CounterText 
    { 
     set { labelCounter.Text = value; } 
    } 
} 
+0

僅供參考,我不得不打電話刷新labelCounter – 2015-04-13 13:20:52

0

首先,請,因爲我是法國人,我的英語道歉。

然後,如果我理解你的問題,你想從第一個更新第二種形式的控制。

請使用窗體的標籤對象。

  1. 創建一個類股票的數據要與形式之間傳輸
  2. 從第一個,因爲這創建第二個表格的一個實例:

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

  3. 顯示形式如

    f.Show() => Modeless wayf.ShowDialog => Modal way

  4. 在你的Form2你從你的Tag對象更新您的控制,因爲這構造:

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

  5. 如果你想從窗體2到主窗體做,做同樣的:

    進入窗體2

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

進入主要形式有:

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

我知道這個題目是舊的,但希望這有助於

相關問題