4

我在具有多个表单的大型应用程序中使用 C# 和 WinForms 工作。

在几个点上,我有另一个表格作为进度屏幕出现。因为我无法冻结我的 UI 线程,所以我必须在新线程中启动新表单。我progressform.ShowDialog()用来启动表单,但是因为它在一个新线程中,所以可以单击或Alt + Tab返回主表单。我想禁用它。

我的想法是我可以在事件上放置一个 EventHandlermainForm.GotFocus并将焦点重定向到progressForm它是否显示。但是,当您切换应用程序或在和GotFocus之间移动时,不会触发该事件。我猜这是因为某些元素有焦点,而不是表单本身。progressFormmainFormmainForm

如果有人知道更好的方法(我不致力于 EventHandler 方法)或 EventHandler 方法的工作代码,它将解决我的问题。

编辑

根据评论,我尝试使用该Activated事件。

// in InitializeForm()
this.Activated += FocusHandler;

// outside of InitializeForm()
void FocusHandler(object sender, EventArgs e)
{
    if (ProgressForm != null)
    {
        ProgressForm.Focus();
    }
}

但它仍然允许我单击返回主窗体并单击按钮。

4

1 回答 1

0

我尝试了一些方法,发现这确实可以按您的意愿工作,整个想法是在显示进度表时从您的主 UI 中过滤一些消息:

public partial class Form1 : Form
{
    [DllImport("user32")]
    private static extern int SetForegroundWindow(IntPtr hwnd);        
    public Form1()
    {
        InitializeComponent();            
    }
    ChildUI child = new ChildUI();
    bool progressShown;
    IntPtr childHandle;
    //I suppose clicking on the button1 on the main ui form will show a progress form.
    private void button1_Click(object sender, EventArgs e)
    {
        if(!progressShown)
           new Thread(() => { progressShown = true; childHandle = child.Handle; child.ShowDialog(); progressShown = false; }).Start();
    }
    protected override void WndProc(ref Message m)
    {
        if (progressShown&&(m.Msg == 0x84||m.Msg == 0xA1||m.Msg == 0xA4||m.Msg == 0xA3||m.Msg == 0x6))  
        //0x84:  WM_NCHITTEST
        //0xA1:  WM_NCLBUTTONDOWN
        //0xA4:  WM_NCRBUTTONDOWN 
        //0xA3   WM_NCLBUTTONDBLCLK   //suppress maximizing ...
        //0x6:   WM_ACTIVATE         //suppress focusing by tab...
        {
            SetForegroundWindow(childHandle);//Bring your progress form to the front
            return;//filter out the messages
        }
        base.WndProc(ref m);
    }
}

如果你想正常显示你的进度表单(不是对话框),使用Application.Run(),正常显示表单(使用Show())而不处理一些 while 循环将在显示后几乎立即终止表单:

private void button1_Click(object sender, EventArgs e)
    {
        //progressShown = true;
        //child.Show();
        if (!progressShown)
        {                
            new Thread(() => {
                progressShown = true;
                if (child == null) child = new ChildUI();
                childHandle = child.Handle;
                Application.Run(child);
                child = null;
                progressShown = false;
            }).Start();
        }
    }

我已经测试过了,它就像一个魅力。

于 2013-06-26T02:35:04.290 回答