通知窗口 - 防止窗口获得焦点

yeb*_*lin 6 c# forms notifications focus

我在使用通知框在c#中正常运行时遇到了一些问题.基本上我在屏幕的右下方显示一个无边框形式,它会显示一条消息几秒钟然后消失.问题是,我需要它出现在其他窗口的顶部,而不能偷走焦点.理想情况下,我希望它是纯粹的托管代码,虽然通过类似的例子我怀疑这是可能的.

目前,我在使用覆盖调用Form.Show()时阻止它窃取焦点:

protected override bool ShowWithoutActivation // stops the window from stealing focus
{
    get { return true; }
}
Run Code Online (Sandbox Code Playgroud)

然后忽略鼠标点击:

    private const int WM_MOUSEACTIVATE = 0x0021;
    private const int MA_NOACTIVATEANDEAT = 0x0004;

    protected override void WndProc(ref Message m)
    {
        if (m.Msg == WM_MOUSEACTIVATE)
        {
            m.Result = (IntPtr)MA_NOACTIVATEANDEAT;
            return;
        }
        base.WndProc(ref m);
    }
Run Code Online (Sandbox Code Playgroud)

但是我发现如果我将它们与TopMost = true(我需要)结合使用,它无论如何都会获得焦点,如果所有其他窗口都被最小化,它也会获得焦点.

那么,有没有什么方法可以防止表格获得焦点(无论是通过鼠标点击,alt-tab等),同时仍然是最顶级/最顶级的形式?即使只是将焦点立即重新放回窗口,它也会将其偷走(虽然会引入闪烁).

任何建议都会非常感激,我真的很喜欢这个.

编辑:

好的,所以我终于设法让这个工作使用:

protected override bool ShowWithoutActivation // stops the window from stealing focus
{
    get { return true; }
}

// and

const int WS_EX_NOACTIVATE = 0x08000000;
const int WS_EX_TOPMOST = 0x00000008;

protected override CreateParams CreateParams
{
    get
    {
        CreateParams param = base.CreateParams;
        param.ExStyle |= WS_EX_TOPMOST; // make the form topmost
        param.ExStyle |= WS_EX_NOACTIVATE; // prevent the form from being activated
        return param;
    }
}

// and

[DllImport("user32.dll")]
private extern static IntPtr SetActiveWindow(IntPtr handle);
private const int WM_ACTIVATE = 6;
private const int WA_INACTIVE = 0;

private const int WM_MOUSEACTIVATE = 0x0021;
private const int MA_NOACTIVATEANDEAT = 0x0004;

protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_MOUSEACTIVATE)
    {
        m.Result = (IntPtr)MA_NOACTIVATEANDEAT; // prevent the form from being clicked and gaining focus
        return;
    }
    if (m.Msg == WM_ACTIVATE) // if a message gets through to activate the form somehow
    {
        if (((int)m.WParam & 0xFFFF) != WA_INACTIVE)
        {

            if (m.LParam != IntPtr.Zero)
            {
                SetActiveWindow(m.LParam);
            }
            else
            {
                // Could not find sender, just in-activate it.
                SetActiveWindow(IntPtr.Zero);
            }

        }
    }
Run Code Online (Sandbox Code Playgroud)

我还将Form.Hide()添加到GotFocus事件中,这样即使它以某种方式获得焦点,它也会关闭并尽快退出用户.

此外,如果有人想知道,所有窗口样式的常量等都可以在WINUSER.H中找到,如果你找不到,可以在http://www.woodmann.com/fravia/sources/WINUSER.H上找到它.它.

但是,如果有人能够看到更优雅的方式,我们将不胜感激.

Ale*_*x F 3

可能 WS_EX_NOACTIVATE 扩展窗口样式就是您正在寻找的。单击时不会激活具有此样式的窗口。例如,虚拟键盘窗口就有这种风格。

要将此样式应用于窗口,请重写 CreateParams 函数并更改 baseParams.ExStyle。