如何在C#中创建一个“不可聚焦”的窗体?

15

我想在C#中创建一个表单,它不能接受焦点,即当我在表单上点击按钮时,焦点不会从当前具有焦点的应用程序中被窃取。

可以看Windows屏幕键盘作为此功能的示例。请注意,当您单击按钮时,不会从您当前使用的应用程序中获取焦点。

我该如何实现这种行为?

更新:

事实证明,只需重写CreateParams属性并将WS_EX_NOACTIVATE添加到扩展窗口样式即可。感谢指导我正确的方向!

不幸的是,这会产生不良的副作用,即它会影响表单移动,即您仍然可以拖放表单到屏幕上,但在拖动时不会显示窗口边框,因此很难精确定位。

如果有人知道如何解决这个问题,将不胜感激。


可能是在不窃取焦点的情况下显示表单?的重复问题。 - rugk
2个回答

12

禁用鼠标激活:

class NonFocusableForm : Form
{
    protected override void DefWndProc(ref Message m)
    {
        const int WM_MOUSEACTIVATE = 0x21;
        const int MA_NOACTIVATE = 0x0003;

        switch(m.Msg)
        {
            case WM_MOUSEACTIVATE:
                m.Result = (IntPtr)MA_NOACTIVATE;
                return;
        }
        base.DefWndProc(ref m);
    }
}

显示窗体而不激活它(我发现在无边框窗体的情况下,这是唯一行得通的方法):

请注意保留原文中的html标签。

Translated content:

To show form without activation (the only one way that worked for me in case of borderless form):

    [DllImport("user32.dll")]
    public static extern bool ShowWindow(IntPtr handle, int flags);

    NativeMethods.ShowWindow(form.Handle, 8);

标准做法(似乎不能适用于所有表单样式):

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

如果有其他激活表单的方法,它们可以以类似的方式被抑制。


1
不幸的是,尽管这可以防止在单击时表单获得焦点,但它并不能防止上一个应用程序失去焦点。感谢您指向正确的解决方案。 - user269597
1
@jnm2,请查看我对原问题的编辑 - 您需要WS_EX_NOACTIVATE扩展窗口样式。https://msdn.microsoft.com/en-us/library/windows/desktop/ff700543 - user269597
1
谢谢。事实证明我需要在表单上的所有按钮上既设置SetStyle(ControlStyles.Selectable, false),以便它们可以被点击,同时还需要SetFocus不响应 WM_MOUSEDOWN - jnm2

0
这是我使用的“无焦点表单(NoFocusForm)”:
public class NoFocusForm : Form
{
    /// From MSDN <see cref="https://learn.microsoft.com/en-us/windows/win32/winmsg/extended-window-styles"/>
    /// A top-level window created with this style does not become the 
    /// foreground window when the user clicks it. The system does not 
    /// bring this window to the foreground when the user minimizes or 
    /// closes the foreground window. The window should not be activated 
    /// through programmatic access or via keyboard navigation by accessible 
    /// technology, such as Narrator. To activate the window, use the 
    /// SetActiveWindow or SetForegroundWindow function. The window does not 
    /// appear on the taskbar by default. To force the window to appear on 
    /// the taskbar, use the WS_EX_APPWINDOW style.
    private const int WS_EX_NOACTIVATE = 0x08000000;

    public NoFocusForm()
    { 
        // my other initiate stuff
    }

    /// <summary>
    /// Prevent form from getting focus
    /// </summary>
    protected override CreateParams CreateParams
    {
        get
        {
            var createParams = base.CreateParams;

            createParams.ExStyle |= WS_EX_NOACTIVATE;
            return createParams;
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接