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

发布于 2024-11-04 08:40:23 字数 1325 浏览 3 评论 0原文

我有一个 Windows 窗体应用程序,当窗体被激活、停用或大小更改时,窗体会执行某些操作。这是比较具体的。例如:

Form Activated:将变量isActive设置为true,并将输入集中到输入框,以便其他人也可以输入内容。

Form Deactivated:将变量 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);
}

但行为与我遇到的问题类似我看到了上述两个事件。单击任务栏图标时,表单会捕获已停用:

激活错误

但立即,它会执行以下操作:

激活真

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

其中一篇文章确实建议我捕获表单的 GotFocus,但我找不到 GotFocus 表单级别的事件,如 GotFocus< /code> 源自控件,而不是应用程序表单。

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

I have a Windows Form application that, when the form is Activated, Deactivated, or SizeChanged, the form does something. It's rather specific. For example:

Form Activated: Will set the variable isActive to true, and focus the input to an input box for someone to enter something too.

Form Deactivated: Will set the variable isActive to false, so that any focus changes in the application (caused by remote machine messages, chat messages, etc), does not steal focus from other applications.

Right now, I have my webBrowser1.Focus() command inside of the Form Activated event which isn't ideal, as when you click on the taskbar icon, it tries to minimize, but since it focuses back to the web browser, the form is then restored/activated again.

I did some searching here on Stack Overflow, and found the following information:

Edited for the below information:

I did find this information in another post here on 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);
}

But the behavior is similar to the problem I'm seeing with the above 2 events. When the taskbar icon is CLICKED, the form does catch the Deactivated:

Activate False

But then immediately, it does this:

Activate True

It would appear, that when you minimize a window with the taskbar button, it still remains as the 'focused' application until you click on another application.

One of the posts did suggest I capture the GotFocus of the form, but there is no event that I can find for a form level for GotFocus, as GotFocus is derived from a control, not an application form.

Question: How do I allow the form to be minimized with the taskbar button, and when the form is then reshown, get it to do the webBrowser1.Focus() command to put the focus where it should be?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

嘦怹 2024-11-11 08:40:23

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

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

w参数

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

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

Here's how I ended up solving the problem. Previously, I was calling Focus() on the ActiveElement in OnActivated. However, in addition to the taskbar minimization call you noticed, pressing Alt-tab to give your form focus also doesn't cause a call to OnActivated.

As a result, I chose to look at the WM_ACTIVATE message to determine when to give focus. From the MSDN docs:

wParam

The low-order word specifies whether the window is being activated or
deactivated. This parameter can be one of the following values. The
high-order word specifies the minimized state of the window being
activated or deactivated. A nonzero value indicates the window is
minimized.

[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();
    }
}
如果没有你 2024-11-11 08:40:23

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

所以我冒昧地编写了可行的代码。相反,它会利用表单调整大小事件。我为“激活”和“停用”事件留下了事件处理程序,以防仍然需要它们,但我认为不应该如此。请务必调用“刷新”,以便重新绘制表单并移动焦点。

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

如果您想抑制基于特定 Windows 状态的移动,我注释掉了一个测试用例。希望这有帮助。

Sorry I had thought the GotFocus Event would work against the Form but it seems not to fire when the focus on the window itself changes.

So I took the liberty of writing code that does work. It taps into the Form Resize Event instead. I left event handlers for your Activated and Deactivate events in case they were still required but I dont think they should be. Just be sure to call 'Refresh' so the form repaints and the focus moves.

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

I commented out a test case in the event you want to suppress movement based on a certain Windowstate. Hope this helps.

初相遇 2024-11-11 08:40:23

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

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

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

I don't like your approach with the focuses and this is a brutal hack but you could postpone the change of focus for one second liek this:

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

That could give the opportunity to the user to press the minimize button.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文