发送按键到非活动应用程序

5
我正在尝试找出如何让我的C#应用程序向另一个窗口发送按键,而无需将其聚焦。我有一个单词列表和3个记事本文件。想象一下,我按顺序打开了所有3个记事本窗口,并且我的程序会在列表框中取出第一个单词并将其写入第一个记事本窗口中。第二个单词在第二个记事本窗口中,第三个单词在第三个记事本窗口中。然后重新开始并继续。所以我希望它每次只在每个窗口中发布一个单词并像这样不断进行。但是我只知道如何在有一个活动窗口的情况下使用一个记事本窗口完成此操作。
int i = 0;
i = listBox1.SelectedIndex;
i = i + 1;
if (i > listBox1.Items.Count - 1)
    i = 0;
listBox1.SelectedIndex = i;
string message = listBox1.SelectedItem.ToString();

SendKeys.Send(message);
SendKeys.Send("{ENTER}");

这将要求我首先聚焦在记事本窗口上,启动计时器,并保持对记事本窗口的关注。然后它将循环遍历列表并输入单词(每行一个)。而且它很好用。但我想在3个窗口上执行此操作。

然后我需要以某种方式获取窗口标题,而不是进程名称。 我会有3个名为Notepad的进程。 但是如果它们被命名为Note1,Note2,Note3,我该怎么办呢?

我需要帮助制作一些程序列表:

listofprograms = ["Note1", "Note2", "Note3"];

它会找到打开了这些名称的应用程序窗口,然后以某种方式将文本写入这些窗口。

有人能帮我吗?到目前为止还没有找到相关信息,相信我我已经搜索过了!

3个回答

2
如果你想要向一个应用程序发送按键,使用 SendKeys.Send(keys) 是一个选项,但你需要通过 SetForegroundWindow API 将窗口置于最前面。
因此,如果你继续使用你的方法,你可以使用 FindWindow、SetForegroundWindow 强制激活和聚焦记事本窗口,以便你可以发送按键。
[DllImportAttribute("User32.dll")]
private static extern int FindWindow(String ClassName, String WindowName);

[DllImport("user32.dll")]
private static extern IntPtr SetForegroundWindow(int hWnd);

public int Activate(int hWnd)
{
   if (hWnd > 0) {
      SetForegroundWindow(hWnd);
      return hWnd;
   }
   else {
       return -1;
   }
}

public int GetWindowHwnd(string className, string windowName) {
     int hwnd = 0;
     string cls = className == string.Empty  ? null : className;
     string win = windowName == string.Empty ? null : windowName;

     hwnd = FindWindow(cls , win );
     return hwnd;
}

虽然还有另一种解决方案可以帮助您。这里处理所有记事本进程:

如何在C#/Win32中将文本发送到记事本?

通过一些调整,它也应该适用于您的情况(基本上,您会遍历并循环找到的记事本实例,并在每个实例中放置一个单词)。

您可能还想查看有关FindWindow的以下信息:

http://www.pinvoke.net/default.aspx/user32.findwindow

`SetKeyboardState`:

http://www.pinvoke.net/default.aspx/user32/SetKeyboardState.html

除了SendMessage之外:

http://www.pinvoke.net/default.aspx/coredll/SendMessage.html

你应该在示例和描述中找到一些有用的提示。

2
很遗憾,没有很好的方法可以做到这一点。虽然SendKeys是一个非常简单和理想的API,但它只适用于活动窗口。没有办法让它在非活动窗口上工作,也没有一个同样易于访问且适用于非活动窗口的API。
通常当人们遇到这个问题时,有两种选择:
  1. 逐个激活你想发送按键的应用程序
  2. 降低到更低级别的SendMessagePostMessage来发送键盘事件
第二个选项通常更可靠,但实现起来更困难。

假设您的“1”指的是激活,这可能会对提问者有所帮助。请参考以下链接:https://dev59.com/n0fRa4cB1Zd3GeqP9Hbm - kenny
我不想将焦点放在任何记事本窗口上。这很容易做到,但关键是我想能够直接将列表框中的文本发送到这些窗口中。它们可能被最小化或其他什么状态。难道没有简单的方法吗? - user3036459
@user3036459 不,你基本上必须使用SendMessagePostMessage来发送按键。 - JaredPar

1

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