任务栏最小化C#Windows窗体问题

时间:2011-04-27 23:07:16

标签: c# winforms taskbar minimize

我有一个Windows窗体应用程序,当窗体是Activated,Deactivated或SizeChanged时,窗体会执行某些操作。这是相当具体的。例如:

表单已激活:将变量isActive设置为true,并将输入重点放在输入框中,以便某人输入内容。

表单已停用:将变量isActive设置为false,以便应用程序中的任何焦点更改(由远程计算机消息,聊天消息等引起),不会窃取焦点来自其他应用程序。

现在,我在webBrowser1.Focus()事件中有Form Activated命令,这是不理想的,因为当您点击任务栏图标时,它会尝试最小化,但由于它重点关注在Web浏览器中,然后再次恢复/激活表单。

我在Stack Overflow上做了一些搜索,发现了以下信息:

编辑以下信息:

我确实在Stack Overflow上的另一篇文章中找到了这些信息:

protected void OnActivateApp(bool activate)
{
    Console.WriteLine("Activate {0}", activate);
}

protected override void WndProc(ref System.Windows.Forms.Message m)
{
    // Trap WM_ACTIVATEAPP
    if (m.Msg == 0x1c) OnActivateApp(m.WParam != IntPtr.Zero);
    base.WndProc(ref m);
}

但是这种行为类似于我在上述2个事件中看到的问题。当任务栏图标为CLICKED时,表单会捕获Deactivated:

  

激活假

然后立刻就这样做了:

  

激活True

看来,当您使用任务栏按钮最小化窗口时,它仍然作为“聚焦”应用程序保留,直到您单击另一个应用程序。

其中一个帖子确实建议我捕获表单的GotFocus,但我找不到GotFocus的表单级别的事件,因为GotFocus来自一个控件,而不是一个申请表。

问题:如何使用任务栏按钮最小化表单,然后在重新表示表单时,让它执行webBrowser1.Focus()命令将焦点放在何处它应该是?

3 个答案:

答案 0 :(得分:2)

以下是我最终解决问题的方法。以前,我在OnActivated的ActiveElement上调用Focus()。但是,除了您注意到的任务栏最小化调用之外,按Alt-tab键使您的表单重点不会导致对OnActivated的调用。

因此,我选择查看WM_ACTIVATE消息以确定何时给予焦点。来自MSDN docs

  

的wParam

     

低位字指定窗口是否被激活或   停用。此参数可以是以下值之一。该   高位字指定窗口的最小化状态   激活或停用。非零值表示窗口是   最小化。

[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
protected override void WndProc(ref Message message)
{
    base.WndProc(ref message);
    if (message.Msg == 0x6)
    {
        int highOrderWord = (int)((message.WParam.ToInt32() & 0xFFFF0000) >> 16);
        bool minimized = highOrderWord != 0;
        bool activating = message.WParam != IntPtr.Zero;
        if (activating && !minimized)
        {
            this.FocusBrowserElement();
        }
    }
}


private void FocusBrowserElement()
{
    if (!this.webBrowser.IsDisposed && 
         this.webBrowser.Document != null &&
         this.webBrowser.Document.ActiveElement != null)
    {
        this.webBrowser.Document.ActiveElement.Focus();
    }
}

答案 1 :(得分:0)

我不喜欢你的焦点方法,这是一个残酷的黑客,但你可以推迟焦点的变化一秒钟这个:

Thread t = new Thread((ThreadStart)delegate(){
  Thread.Sleep(1000);
  this.Invoke(methodChangingFocus, new object[] {});
}).Start();

这可以让用户按下最小化按钮。

答案 2 :(得分:0)

很抱歉我原本以为GotFocus事件会对表单起作用,但是当窗口本身的焦点发生变化时似乎不会触发。

所以我冒昧地编写了有效的代码。它改为使用Form Resize Event。我为你的Activated和Deactivate事件留下了事件处理程序,以防它们仍然需要但我不认为它们应该是。只需确保调用'刷新',以便重新绘制表单并重点移动。

    public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }
    private bool isActive = false;
    private FormWindowState previousstate;
    private void Form1_Load(object sender, EventArgs e)
    {
        previousstate = this.WindowState;
        //Got Focus Anonymous Delegate handles focus on the textbox
        //if the Form currently is Activated
        this.Resize += delegate(object resizesender, EventArgs resizee)
        {
            //if (previousstate == FormWindowState.Minimized)
            // {
                txtGetFocus.Focus();
                this.Refresh();
            // }
            previousstate = this.WindowState;
        };
        this.Activated += delegate(object activatedsender, EventArgs activatede)
        {
            isActive = true;
        };
        this.Deactivate += delegate(object deactivatesender, EventArgs deactivatee)
        {
            isActive = false;
        };
    }
}

如果您想根据某个Windowstate抑制移动,我会注释掉一个测试用例。希望这会有所帮助。