简体   繁体   English

从C#控制台应用程序显示WinFrm,然后等待关闭

[英]Show WinFrm from C# console application and wait to close

I am trying to show a WinForm (inputbox) from a console application in C# and wait until the user closes the form. 我正在尝试从C#中的控制台应用程序显示WinForm(输入框),然后等到用户关闭表单。 It is important for me to have the inputbox ontop and active when it opens. 对我来说重要的是,输入框应在顶部并在打开时处于活动状态。 ShowDialog() is not working in my case as in some cases it does not appears as an active form. 在我的情况下,ShowDialog()无法正常工作,因为在某些情况下,它没有显示为活动形式。 So I'd like to change my code and use Show(). 因此,我想更改代码并使用Show()。 This way I can manually make find out if the form is active or not and if not activate it myself. 通过这种方式,我可以手动确定表单是否处于活动状态,以及是否自己激活该表单。 With ShowDialog(). 使用ShowDialog()。 my code stops and I can not do anything until the from is closed. 我的代码停止了,直到from被关闭,我什么也不能做。

Below is my code. 下面是我的代码。 It does show the inputbox, however it is frozen. 它的确显示了输入框,但已冻结。 What am I doing wrong please? 请问我做错了什么? As clear the while-loop after "inputBox.Show();" 如“ inputBox.Show();”之后的while循环一样 is not doing anything, but if I can manage to run the loop and the inputbox does not freeze, I will sort out the rest myself. 没有做任何事情,但是如果我可以设法运行循环并且输入框没有冻结,那么我将自己整理其余部分。 I appreciate your help. 我感谢您的帮助。

public static string mInputBox(string strPrompt, string strTitle, string strDefaultResponse)
    {
        string strResponse = null;
        Form inputBox = new Form();
        inputBox.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
        inputBox.ClientSize = new Size(500, 85);
        inputBox.Text = strTitle;
        inputBox.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
        inputBox.Left = (Screen.PrimaryScreen.Bounds.Size.Width / 2) - (inputBox.ClientSize.Width / 2);
        inputBox.Top = (Screen.PrimaryScreen.Bounds.Size.Height / 2) - (inputBox.ClientSize.Height / 2);

        Label lblPrompt = new Label();
        lblPrompt.Text = strPrompt;
        inputBox.Controls.Add(lblPrompt);

        TextBox textBox = new TextBox();
        textBox.Text = strDefaultResponse;
        inputBox.Controls.Add(textBox);

        Button okButton = new Button();
        okButton.Text = "&OK";
        inputBox.Controls.Add(okButton);

        Button cancelButton = new Button();
        cancelButton.Text = "&Cancel";
        inputBox.Controls.Add(cancelButton);

        okButton.Click += (sender, e) =>
        {
            strResponse = textBox.Text;
            inputBox.Close();
        };

        cancelButton.Click += (sender, e) =>
        {
            inputBox.Close();
        };
        inputBox.AcceptButton = okButton;
        inputBox.CancelButton = cancelButton;

        SetWindowPos(inputBox.Handle, HWND_TOPMOST, inputBox.Left, inputBox.Top, inputBox.Width, inputBox.Height, NOACTIVATE);

        inputBox.Show();

        while {true}
            Thread.Sleep(100);

        Application.DoEvents();
        return strResponse;
    }

I'm not sure why you are taking this route, I'm sure there are better ways to do it (explain one at the end). 我不确定您为什么选择这条路线,但我确定有更好的方法(最后解释一下)。 however to make your code run you should add Application.DoEvents() inside your loop 但是,要使代码运行,应在循环内添加Application.DoEvents()

the code should be something like this: 代码应该是这样的:

        var formActive = true;
        inputBox.FormClosed += (s, e) => formActive = false;
        inputBox.Show();
        inputBox.TopMost = true;
        inputBox.Activate();

        while (formActive)
        {
            Thread.Sleep(10);
            Application.DoEvents();
        }

and the whole method will be: 整个方法将是:

    public static string mInputBox(string strPrompt, string strTitle, string strDefaultResponse)
    {
        string strResponse = null;
        Form inputBox = new Form();
        inputBox.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
        inputBox.ClientSize = new Size(500, 85);
        inputBox.Text = strTitle;
        inputBox.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
        inputBox.Left = (Screen.PrimaryScreen.Bounds.Size.Width/2) - (inputBox.ClientSize.Width/2);
        inputBox.Top = (Screen.PrimaryScreen.Bounds.Size.Height/2) - (inputBox.ClientSize.Height/2);

        Label lblPrompt = new Label();
        lblPrompt.Text = strPrompt;
        inputBox.Controls.Add(lblPrompt);

        TextBox textBox = new TextBox();
        textBox.Text = strDefaultResponse;
        inputBox.Controls.Add(textBox);

        Button okButton = new Button();
        okButton.Text = "&OK";
        inputBox.Controls.Add(okButton);

        Button cancelButton = new Button();
        cancelButton.Text = "&Cancel";
        inputBox.Controls.Add(cancelButton);

        okButton.Click += (sender, e) =>
        {
            strResponse = textBox.Text;
            inputBox.Close();
        };

        cancelButton.Click += (sender, e) =>
        {
            inputBox.Close();
        };
        inputBox.AcceptButton = okButton;
        inputBox.CancelButton = cancelButton;


        var formActive = true;
        inputBox.FormClosed += (s, e) => formActive = false;
        inputBox.Show();
        inputBox.TopMost = true;
        inputBox.Activate();

        while (formActive)
        {
            Thread.Sleep(10);
            Application.DoEvents();
        }

        return strResponse;
    }

but I think it would be a better Idea to Derive from Form and create a InputBox and set TopMost and call Activate OnLoad to create what you need, then simply call ShowDialog , something like: 但是我认为从Form派生并创建InputBox并设置TopMost并调用Activate OnLoad来创建所需的东西是一个更好的主意,然后只需调用ShowDialog ,例如:

class Inputbox : Form
        {

            protected override void OnLoad(EventArgs e)
            {
                base.OnLoad(e);

                TopMost = true;
                Activate();
            }
        }

and better to put UI code in InputBox class as the whole code and usage would be like: 最好将UI代码放入InputBox类中,因为整个代码和用法如下所示:

class Inputbox : Form
{
    public string Response { get; set; }

    public Inputbox(string strTitle, string strPrompt, string strDefaultResponse)
    {
        //add UI and Controls here

        FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
        ClientSize = new Size(500, 85);
        Text = strTitle;
        StartPosition = System.Windows.Forms.FormStartPosition.Manual;
        Left = (Screen.PrimaryScreen.Bounds.Size.Width/2) - (ClientSize.Width/2);
        Top = (Screen.PrimaryScreen.Bounds.Size.Height/2) - (ClientSize.Height/2);

        Label lblPrompt = new Label();
        lblPrompt.Text = strPrompt;
        Controls.Add(lblPrompt);

        TextBox textBox = new TextBox();
        textBox.Text = strDefaultResponse;
        Controls.Add(textBox);

        Button okButton = new Button();
        okButton.Text = "&OK";
        Controls.Add(okButton);

        Button cancelButton = new Button();
        cancelButton.Text = "&Cancel";
        Controls.Add(cancelButton);

        okButton.Click += (sender, e) =>
        {
            Response = textBox.Text;
            Close();
        };

        cancelButton.Click += (sender, e) =>
        {
            Close();
        };
        AcceptButton = okButton;
        CancelButton = cancelButton;
    }

    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);

        TopMost = true;
        Activate();
    }
}

public static string mInputBox(string strPrompt, string strTitle, string strDefaultResponse)
{
    string strResponse = null;
    Inputbox inputBox = new Inputbox(strPrompt,strTitle,strDefaultResponse);

    inputBox.ShowDialog();

    return inputBox.Response;
}

您需要运行一个消息循环:

Application.Run(inputBox);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM