从 C# 控制台应用程序显示 WinFrm 并等待关闭 [英] Show WinFrm from C# console application and wait to close

查看:31
本文介绍了从 C# 控制台应用程序显示 WinFrm 并等待关闭的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试从 C# 中的控制台应用程序显示一个 WinForm(输入框),并等待用户关闭该表单.将输入框置于顶部并在打开时处于活动状态对我来说很重要.ShowDialog() 在我的情况下不起作用,因为在某些情况下它不会显示为活动表单.所以我想更改我的代码并使用 Show().这样我就可以手动找出表单是否处于活动状态,如果没有自己激活它.使用 ShowDialog().我的代码停止了,在 from 关闭之前我什么也做不了.

I am trying to show a WinForm (inputbox) from a console application in C# and wait until the user closes the form. 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. So I'd like to change my code and use Show(). This way I can manually make find out if the form is active or not and if not activate it myself. With ShowDialog(). my code stops and I can not do anything until the from is closed.

下面是我的代码.它确实显示了输入框,但是它被冻结了.请问我做错了什么?清除inputBox.Show();"之后的while循环没有做任何事情,但是如果我可以设法运行循环并且输入框没有冻结,我将自己整理其余部分.感谢您的帮助.

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

推荐答案

我不知道你为什么要走这条路,我相信有更好的方法来做到这一点(最后解释一个).但是为了让您的代码运行,您应该在循环中添加 Application.DoEvents()

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

代码应该是这样的:

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

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

整个方法将是:

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

但我认为从 Form 派生并创建一个 InputBox 并设置 TopMost 并调用 Activate 会是一个更好的主意OnLoad 创建您需要的内容,然后只需调用 ShowDialog,例如:

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:

class Inputbox : Form
        {

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

                TopMost = true;
                Activate();
            }
        }

最好将 UI 代码放在 InputBox 类中,因为整个代码和用法如下:

and better to put UI code in InputBox class as the whole code and usage would be like:

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

这篇关于从 C# 控制台应用程序显示 WinFrm 并等待关闭的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆