单击系统任务栏图标时如何防止当前窗口失去焦点

时间:2019-04-02 23:09:03

标签: c# winforms focus virtual-keyboard topmost

我正在为Windows 10编写一个C#Windows Forms应用程序,类似于系统虚拟键盘。该应用程序是最高的,它不会通过覆盖CreateParams和ShowWithoutActivation来吸引焦点:

private const int WS_EX_NOACTIVATE = 0x08000000;

protected override CreateParams CreateParams
{
    get
    {
        CreateParams params = base.CreateParams;
        params.ExStyle |= WS_EX_NOACTIVATE;
        return (params);
    }
}

protected override bool ShowWithoutActivation
{
    get { return true; }
}

用户可以将应用程序最小化到系统托盘中。这不会改变焦点。但是,当从系统托盘中还原该应用程序(通过单击应用程序图标)时,当前活动窗口将失去焦点。

是否有办法避免这种现象并使活动窗口(在单击鼠标之前)保持焦点?

使用以下方法最小化和恢复该应用程序:

this.Hide();  // minimize on close event
..
this.Show();  // restore on notify icon click event

这里也有类似的问题,但它是过时的:
Prevent system tray icon from stealing focus when clicked

1 个答案:

答案 0 :(得分:0)

这是一个临时解决方案,直到有人找到合适的解决方案为止。它可以通过连续读取窗口并将窗口焦点保存在应用程序的托盘图标鼠标移动事件中来工作。 该保存的窗口将设置为在任务栏图标鼠标按下事件内进行聚焦:

[DllImport("user32.dll", ExactSpelling = true)]
static extern IntPtr GetForegroundWindow();

[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);

private void notifyIcon_MouseDown(object sender, MouseEventArgs e)
{
    if (lastActiveWin != IntPtr.Zero)
    {
        SetForegroundWindow(lastActiveWin);
    }
}

IntPtr lastActiveWin = IntPtr.Zero;
private void notifyIcon_MouseMove(object sender, MouseEventArgs e)
{
    lastActiveWin = GetForegroundWindow();
}