C# - 向(最后)选定的窗口发送键盘事件

3
我想使用在此处找到的虚拟键盘程序集http://www.codeproject.com/KB/miscctrl/touchscreenkeyboard.aspx,就像 Windows 中的屏幕键盘 (OSK.exe) 一样。请问有人能告诉我如何使用它,以便它始终保持在顶部,但用户仍然可以选择桌面上的其他窗口进行键盘输入,就像 Windows 的“屏幕键盘”一样?具体来说,我不知道如何选择上一个选定的窗口(不能仅使用 GetForegroundWindow 或 GetFocus,因为当用户单击虚拟键盘时,它会获得焦点,而我会得到键盘窗口本身的句柄)。
这对我来说非常紧急,所以任何建议都将不胜感激。
提前致谢。
3个回答

4
您需要做的是使您的窗口无法激活。这可以通过覆盖CreateParams轻松实现。然后,您可以使用SendKey.Send向当前活动窗口发送按键操作,您的窗口将永远不会变为活动状态。
以下是一个简单的示例:
  public partial class Form1 : Form
  {
    const int WS_EX_NOACTIVATE = 0x08000000;

    public Form1()
    {      
      InitializeComponent();      
    }

    protected override CreateParams CreateParams
    {
      get
      {
        CreateParams param = base.CreateParams;
        param.ExStyle |= WS_EX_NOACTIVATE;
        return param;
      }
    }

    private void button1_Click(object sender, EventArgs e)
    {
      SendKeys.Send("A");
    }
  }

你会注意到一件奇怪的事情,由于窗口从未变为活动状态,因此当你拖动窗口时,它会有些反应奇怪。基本上拖动是有效的,只是在拖动过程中没有视觉反馈。你可以通过重写WndProc并处理WM_NCLBUTTONDOWN和WM_MOUSEMOVE消息来解决这个问题。


非常感谢你,Chris!你是对的,这就是我需要的代码。在此之前,我发现在我的所谓“设计”中,我错过了非常重要的事情,我不仅需要活动窗口句柄,还需要它的控件,而且我无法记住或在网络上找到如何做到这一点。这解决了整个问题。在应用你写的代码后,程序窗口一开始没有像应该那样保持在最上层,但是我删除了不必要的“SetFocus()”和“SetForegroundWindow()”调用,现在它像魔术般地工作。 是的,我注意到拖动时窗口的行为很奇怪 :) 再次感谢。干杯! - Maks
@Maks,我很高兴能帮到你。为了让窗口保持在最上层,你可以将TopMost属性设置为true。 - Chris Taylor
@Maks:如果您喜欢这个答案,可以通过点击旁边的复选框将其标记为正确答案。 :) - Robert Harvey

1

当你获得输入焦点时,Windows消息WM_SETFOCUS会发送到你的窗口,.net将其转换为你接收到的Forms事件。Windows消息包含先前输入焦点窗口的句柄。

如果在你的C# Form.Activated或Control.Enter/Control.GotFocus事件中没有这些信息,则可能需要重写Form.WndProc以捕获原始的Windows消息并检索句柄-然后可以使用该句柄激活或发送WM_KEYDOWN消息到先前的输入焦点窗口。


感谢您的回复,Jason。虽然我之前一直在使用Win32 API,但现在我选择了更简单的方法。我注册了一个定时器,每秒触发一次,调用方法获取活动窗口句柄并保存它。也许不是很干净,但现在我不能再花更多时间重新审视原始API了。 - Maks
没问题。这不太“优雅”,但它能用,最终这通常才是真正重要的 :-) - Jason Williams

0

感谢链接Robert,但我不知道用户可以选择的窗口的名称。尽管如此,这是个好链接,我找到了关于实际代码的一些澄清,但并没有解决方案。 - Maks

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