[英]Update a Modeless Dialog from the Main Window with Windows Forms
我正在使用C#/。NET 3.5 / Windows Forms程序。 我想創建一個“無模式對話框”,然后使用從主窗體生成的信息對其進行更新。 我已經找到了另一個方向的示例-對話框中的信息會更新主窗口,但是在反向時遇到了麻煩。 對話框中的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元素時,將無模式對話框放入第二個線程的最佳方法是什么? 從主窗口/線程更新那些GUI元素的最佳方法是什么? 謝謝!
表單的工作方式是,如果程序是處理消息並將其傳遞到要處理的表單的循環,則其核心是核心。 如果您的窗體從不將控制權返回到消息循環,則程序將停止正常運行。 您試圖通過添加更多線程來解決此問題,但是那樣會導致它自己的痛苦。
您不能在線程中執行此操作,因為應用於表單的所有操作都必須在UI線程上完成。 您可以使用BeginInvoke將諸如Invalidate之類的調用傳遞回UI線程,但這確實很麻煩-編寫在一個UI線程上運行的協作窗口比觸發許多線程然后嘗試將UI線程插入其中要好得多為他們做事。
為此,您將創建表單,然后將控制權返回到消息處理循環。 在將來的某個時間,您將關閉諸如單擊按鈕之類的事件的窗口。 如果由於任何事件而需要更新窗口,則可以在事件處理程序中調用invalidate然后返回。
根據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; }
}
}
首先,因為我是法國人,請為我的英語道歉。
然后,如果我理解您的問題,那么您想從第一個Form更新第二個Form的控件。
請使用表單的Tag對象。
從第一個Form創建第二個Form的實例,如下所示:
Form2 f = new Form2();
f.Tag = MyDataObject();
顯示形式像
f.Show() => Modeless way
或f.ShowDialog => Modal way
在Form2的構造函數中,您可以從Tag對象更新控件,如下所示:
public Form2()
{
MyDataObject do = (MyDataObject)this.Tag;
MyLabel.Text = do.LabelText;
}
如果要從Form2到主窗體執行此操作,請執行以下操作:
進入Form2
this.Tag = MyDataObject;
this.Close();
進入主要形式:
`MyDataObject do = (MyDataObject)f2.Tag;`
我知道這個話題很舊,但希望對您有所幫助
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.