在 C# 中使窗体不可聚焦

发布于 2024-08-24 21:38:39 字数 741 浏览 11 评论 0原文

我想编写一个虚拟键盘,例如触摸屏电脑的 Windows 屏幕键盘。 但我的虚拟键盘从正在使用的应用程序中窃取焦点时遇到问题。即使用户单击当前应用程序,Windows 屏幕键盘也会将焦点保留在当前应用程序上。有没有办法在 C# 中对 Windows 窗体执行相同的操作?

我现在唯一能做的就是将键盘事件发送到特定的应用程序,例如以下代码中的记事本。如果我可以使窗体不可聚焦,我可以使用 GetForegroundWindow 获取当前聚焦的窗口。

[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName,string lpWindowName);


[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);

private void button1_Click(object sender, EventArgs e)
{
    IntPtr calculatorHandle = FindWindow("notepad", null);
    SetForegroundWindow(calculatorHandle);
    SendKeys.SendWait("111");
}

有办法做到这一点吗?有什么更好的方法让表单将键盘事件发送到正在使用的应用程序的建议吗?

谢谢!!

I'm wanting to write a virtual keyboard, like windows onscreen keyboard for touchscreen pcs.
But I'm having problem with my virtual keyboard stealing the focus from the application being used. The windows onscreen keyboard mantains the focus on the current application even when the user clicks on it. Is there a way to do the same with windows forms in C#?

The only thing I can do for now is to send a keyboard event to an especific application, like notepad in the following code. If I could make the form not focusable, I could get the current focused window with GetForegroundWindow.

[DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
public static extern IntPtr FindWindow(string lpClassName,string lpWindowName);


[DllImport("USER32.DLL")]
public static extern bool SetForegroundWindow(IntPtr hWnd);

private void button1_Click(object sender, EventArgs e)
{
    IntPtr calculatorHandle = FindWindow("notepad", null);
    SetForegroundWindow(calculatorHandle);
    SendKeys.SendWait("111");
}

Is there a way this can be done? Any suggestions of a better way to have the form sending keyboard events to the application being used?

Thanks!!

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

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

发布评论

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

评论(2

音栖息无 2024-08-31 21:38:39

解决了!

我已经尝试了 gehho 的解决方案,但我还需要重写 CreateParams 方法:

private const int WS_EX_NOACTIVATE = 0x08000000;
protected override CreateParams CreateParams
{
    get
    {
        var createParams = base.CreateParams;

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

Its solved!

I've tried the solution from gehho, but I also needed to override the CreateParams method:

private const int WS_EX_NOACTIVATE = 0x08000000;
protected override CreateParams CreateParams
{
    get
    {
        var createParams = base.CreateParams;

        createParams.ExStyle |= WS_EX_NOACTIVATE;
        return createParams;
    }
}
辞别 2024-08-31 21:38:39

我宁愿尝试阻止您的窗口接收焦点/被激活,而不是在单击您的窗口后尝试重置活动窗口。

请查看本文。最后,作者简要解释了如何做到这一点:

如何防止我的窗口在显示时激活并获得焦点?

在 Windows Forms 2.0 中有一个新属性,称为
ShowWithoutActivation – 您需要在表单上覆盖它。
在本机应用程序中,您可以将 SetWindowPos 与
SWP_NOACTIVATE 标志或具有 SW_SHOWNA 标志的 ShowWindow。

此外,在这篇文章中,他提供了一个代码示例对于 Windows 窗体:

如果您想要一个完整的表单,您现在可以覆盖名为
ShowWithoutActivation

公共类NoActivateForm:表单 
{
    受保护的覆盖 bool ShowWithoutActivation =>真的;  
}
  
  

请记住,这并不总是“阻止”激活 - 您可以 仍然通过调用Activate()Focus()...等方法来激活。如果 您想阻止点击客户区来激活 窗口中,您可以处理 WM_MOUSEACTIVATE 消息。

私有常量WM_MOUSEACTIVATE = 0x0021,MA_NOACTIVATE = 0x0003;

protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_MOUSEACTIVATE) 
    {
         m.Result = (IntPtr)MA_NOACTIVATE;
         返回;
    }
    base.WndProc(ref m);
}

Instead of trying to reset the active window after your one has been clicked, I would rather try to prevent your window from receiving focus/being activated.

Have a look at this article. At the end, the author briefly explains how this can be done:

How can I prevent my window from getting activation and focus when shown?

In Windows Forms 2.0 there is a new property called
ShowWithoutActivation – which you would need to override on the Form.
In native applications you can use SetWindowPos with the
SWP_NOACTIVATE flag or the ShowWindow with the SW_SHOWNA flag.

Furthermore, in this article he provides a code example for Windows Forms:

If you want a full-on form, you can now override a property called
ShowWithoutActivation:

public class NoActivateForm : Form 
{
    protected override bool ShowWithoutActivation => true;  
}

Keep in mind this does not “prevent” activation all the time – you can
still activate by calling the Activate(), Focus()… etc methods. If
you want to prevent clicks on the client area from activating the
window, you can handle the WM_MOUSEACTIVATE message.

private const int WM_MOUSEACTIVATE = 0x0021, MA_NOACTIVATE = 0x0003;

protected override void WndProc(ref Message m)
{
    if (m.Msg == WM_MOUSEACTIVATE) 
    {
         m.Result = (IntPtr)MA_NOACTIVATE;
         return;
    }
    base.WndProc(ref m);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文