gpt4 book ai didi

c# - 使用 C# 和 WinForms 在与主窗体不同的线程上创建一个新的临时窗体

转载 作者:行者123 更新时间:2023-11-30 20:50:43 28 4
gpt4 key购买 nike

找不到针对这种特定情况的答案。我需要创建一个临时表单(稍后将被销毁),它位于与主表单不同的线程中。

此表单用于向用户显示帐户登录信息。在这个表单出现在屏幕上的同时,一个模态输入框也会显示给用户。模态输入框的存在阻止了与登录信息表单的任何交互(复制/粘贴),这是用户必需的功能。

我怎样才能:

A) 在与主窗体完全不同的线程上创建和显示新窗体?

B) 一旦用户将输入输入到模态对话框中,就从主窗体的线程中销毁该窗体?

注意:我已经探索了 MainForm.Invoke/BeginInvoke,但这并没有给出我需要的结果,正如其他一些帖子所声称的那样。

模态输入框的代码:

class InputBox
{
public static DialogResult Show(string prompt, bool hideInput, out string userInput, Form parent = null)
{
InputBoxForm frm = new InputBoxForm(prompt, hideInput);

if (parent != null)
frm.ShowDialog(parent);
else
frm.ShowDialog();

if (frm.DialogResult == DialogResult.OK)
{
userInput = frm.txtInput.Text;
frm.Dispose();
return DialogResult.OK;
}
else
{
userInput = "";
frm.Dispose();
return DialogResult.Cancel;
}
}
}

以及程序中使用的代码:

Form loginDisplay = LoginInfoForm(user, pass);
loginDisplay.Show(null);
string input = "";
InputBox.Show("Enter info:", false, out input, parent: this);

LoginInfoForm 只是一个动态创建表单并对其进行一些格式化的函数。

最佳答案

这是一个有点做作的情况,IIUIC。为什么您需要在一个单独的线程上创建一个新表单?

您仍然可以在主 UI 线程上同时拥有模态对话框(由主窗体作为父级)和非模态弹出窗体。用户将能够独立地与两者进行交互。

只需指定对话框的正确父级:dialogForm.ShowDialog(mainForm),而不指定无模式窗体的父级:form.Show(null)

无论哪种情况,这种 UI 都可能会让用户感到困惑。

已更新,下面是我所描述内容的示例,其中有一项重要修正。事实上,Form.ShowDialog 禁用了同一线程拥有的所有顶级可见和启用的窗口(而不是像它的 Win32 对应物 DialogBox 那样仅禁用对话框的直接父窗口)。

诚然,这对我来说是一个非常出乎意料的行为,尽管我明白其背后的原因:我上面提到的一致的 UI 体验。更多详细信息,请引用 ModalApplicationContext.DisableThreadWindows 的实现。

解决方法非常简单:如果弹出窗体当前可见,请在显示对话框之前禁用它,并在显示对话框时重新启用它。请注意,这一切都是在同一个线程上完成的:

var dialog = new ModalDialog { Width = 200, Height = 100 };

if (popup != null)
{
popup.Enabled = false;
dialog.Load += delegate {
popup.Enabled = true; };
}

dialog.ShowDialog(this);

完整的 WinForms 应用:

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowsForms_22340190
{
public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();

var cts = new CancellationTokenSource();

this.Load += async (s, e) =>
{
// start the background thread in 1s
await Task.Delay(1000);

Form popup = null;

var task = Task.Run(() =>
{
// background thread
this.Invoke(new Action(() =>
{
// create a popup on the main UI thread
popup = new Popup { Width = 300, Height = 200 };
popup.Show(this);
}));

// imitate some work
var i = 0;
while (true)
{
Thread.Sleep(1000);
cts.Token.ThrowIfCancellationRequested();

var n = i++;
this.BeginInvoke(new Action(() =>
{
// update the popup UI on the main UI thread
popup.Text = "Popup, step #" + n;
}));
}
});

// wait 2s more and display a modal dialog
await Task.Delay(2000);

var dialog = new ModalDialog { Width = 200, Height = 100 };

if (popup != null)
{
popup.Enabled = false;
dialog.Load += delegate {
popup.Enabled = true; };
}

dialog.ShowDialog(this);
};

this.FormClosing += (s, e) =>
cts.Cancel();
}
}

public partial class ModalDialog : Form
{
public ModalDialog()
{
this.Text = "Dialog";
this.Controls.Add(new TextBox { Width = 50, Height = 20 });
}
}

public partial class Popup : Form
{
public Popup()
{
this.Text = "Popup";
this.Controls.Add(new TextBox { Width = 50, Height = 20 });
}
}
}

关于c# - 使用 C# 和 WinForms 在与主窗体不同的线程上创建一个新的临时窗体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22339647/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com