使用C#将控制台应用程序挂钩到记事本

7
我想做的是创建一个简单的Windows应用程序,它将钩取Notepad并模拟按键。我已经打开了Notepad,将其置于前景,然后模拟按下数字1的过程。但是,如果我从notepad点击到其他地方,正在活动的就成为了正在输入的内容。
我该如何将此应用程序绑定到Notepad,以便我可以点击并在任何地方键入内容,而此应用程序仍会将命令推送到Notepad?
这是我使用的模拟按键的DLL
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using WindowsInput;

namespace NotePadTesting
{
    class Program
    {
        [DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
        public static extern IntPtr FindWindow(string lpClassName,
        string lpWindowName);
        // Activate an application window.
        [DllImport("USER32.DLL")]
        public static extern bool SetForegroundWindow(IntPtr hWnd);


        static void Main(string[] args)
        {

            Process[] processes = Process.GetProcessesByName("notepad");

            if (processes.Length == 0)
            {

                Process.Start("notepad.exe");
                processes = Process.GetProcessesByName("notepad");

            }
            if (processes.Length == 0)
            {
                throw new Exception("Could not find notepad huh....");
            }

            IntPtr WindowHandle = processes[0].MainWindowHandle;
            SetForegroundWindow(WindowHandle);

            for (int i = 0; i < 500; i++)
            {
                System.Threading.Thread.Sleep(100);
                InputSimulator.SimulateKeyPress(VirtualKeyCode.VK_1);

            }


        }
    }
}

我认为这是第一篇浏览量超过25次但没有任何评论的帖子 :( - user222427
我正在调查这些事情,如果这可以让你感觉更好的话。 - Anthony
1
在内部,WindowsInput 项目使用 SendInput 原生的 Windows 调用,它看起来只是模拟了一个硬件消息,这个消息会被 Windows 处理并路由到活动应用程序。你可能需要自己使用本地方法调用,并使用 SendMessage WinAPI 函数将按键发送到 ProcessMainWindowHandle - Anthony
为什么不在按键时检查记事本是否在前台? - Jesse
@Mike,你实际上想要做什么(是学习某些东西,构建比这个测试更大的东西等)? - Mike Cheel
显示剩余7条评论
2个回答

2

您需要通过PostMessageNotepad.exe进行接口交互。您需要使用P/Invoke技术从User32.dll调用此功能:

using System.Runtime.InteropServices;

internal static class NativeMethods
{
  // This method signature is derived from MSDN's PostMessage declaration.
  [DllImport("user32.dll")]
  public static extern bool PostMessage(IntPtr hwnd, uint msg, uint wParam, uint lParam);

  // Other p/invoke methods go here, such as FindWindow...
}

您可以使用FindWindow来定位Notepad,从而获取窗口的句柄(HWND)。

一旦您完成了这个步骤,就可以向该窗口发送键盘通知。这些通知模拟键盘输入,并且只针对该窗口,即使该窗口被最小化或者不是前台窗口。

重要的消息包括WM_KEYDOWNWM_KEYUPWM_CHAR。其中许多使用的是扫描码而不是虚拟键码,这意味着您需要进行相互转换。这可以通过MapVirtualKey来完成。所有WM命令都采用其LPARAMWPARAM值的特定形式,因此请查看MSDN文档以了解它所需的内容。

有一个名为Spy++的工具(曾经)随Visual Studio一起提供,可以让您查看这些消息。这是一种非常适合调试/反向工程此类内容的工具。

使用上述所有Win32 API,您应该能够将按键发送到外部窗口。


2
如果您已经有要输入的窗口句柄,您可以使用PostMessage函数。您只需要搜索虚拟键代码即可。

我认为PostMessage/SendMessage唯一的问题是它需要wpf。 - user222427
1
我不这么认为,因为它是User32.dll库中的本地Windows API函数,就像你示例中的FindWindow函数一样。 - Yoghurt

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