c# 我无法让 SendMessage 将消息发送到记事本 window

c# i'm unable to get SendMessage to send a message to a notepad window

我看过这个问答

How to send text to Notepad in C#/Win32?

我认为不重要的细微变化..是我有一堆记事本windows..所以为了测试这个我将notepad.exe复制为notepadd.exe并打开notepadd.exe,所以我的记事本windows中只有一个是notepadd.exe进程。

我有这个代码

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace testsendmessage
{

    public partial class Form1 : Form
    {
        [DllImport("user32.dll", EntryPoint = "FindWindowEx")]
        public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
        [DllImport("User32.dll")]
        public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, string lParam);

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

         private void button1_Click(object sender, EventArgs e)
        {
            Process[] notepads = Process.GetProcessesByName("notepadd");
            if (notepads.Length == 0) return;
            if (notepads[0] != null)
            {
                IntPtr child = FindWindowEx(notepads[0].MainWindowHandle, new IntPtr(0), "Edit", null);
                SendMessage(child, 0x000C, 0, "abcd");
            }
        }
    }
}

虽然它没有触及记事本 window。

我试过调试,发现记事本数组有一项,当然是正确的。

它进入 'if' 并运行 SendMessage(child, 0x000C, 0, "abcd");

但我在记事本中看不到任何内容window

我没有从代码中得到错误,它只是记事本中什么也没有出现 window..而且我不太了解 winapi 的东西,所以我不确定如何继续试图解决它?

如您所见,它到达了那条线,我可以使用手表 window 查看记事本进程数组,并在 'child' 但我不知道我应该是什么查看并确定为什么它没有发送到 window

已添加

基于雷米建议的新代码

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace testsendmessage
{

    public partial class Form1 : Form
    {
        [DllImport("user32.dll", EntryPoint = "FindWindowEx")]
        public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

        [DllImport("User32.dll", CharSet = CharSet.Unicode, EntryPoint = "SendMessageW")]
        public static extern IntPtr SendMessageWStr(IntPtr hWnd, uint uMsg, IntPtr wParam, string lParam);

        const uint WM_SETTEXT = 0x000C;
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

         private void button1_Click(object sender, EventArgs e)
        {
            Process[] notepads = Process.GetProcessesByName("notepadd");
            if (notepads.Length == 0) return;
            if (notepads[0] != null)
            {
                IntPtr child = FindWindowEx(notepads[0].MainWindowHandle, new IntPtr(0), "Edit", null);
                SendMessageWStr(child, WM_SETTEXT, IntPtr.Zero, "abcd");
            }

        }
    }
}

但我仍然遇到同样的问题,即记事本 window 在单击按钮之前是空白的,之后也是空白的。它不会将文本发送到记事本 window。尽管它正在到达旨在向其发送文本的代码行。

进一步补充。

当前代码,

我已将 FindWindowEx 更改为 FindWindowExW,并将 new IntPtr(0) 更改为 IntPtr.Zero,但它仍然没有响应。

我从 c​​md 打开了 notepadd.exe,我在那里看到了 window。当然还有任务管理器中的 notepadd.exe,但是单击我的应用程序中的按钮并没有向其中写入任何文本 window。

using System;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace testsendmessage
{

    public partial class Form1 : Form
    {
        [DllImport("user32.dll", EntryPoint = "FindWindowExW")]

        public static extern IntPtr FindWindowExW(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

        [DllImport("User32.dll", CharSet = CharSet.Unicode, EntryPoint = "SendMessageW")]
        public static extern IntPtr SendMessageWStr(IntPtr hWnd, uint uMsg, IntPtr wParam, string lParam);

        const uint WM_SETTEXT = 0x000C;
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

         private void button1_Click(object sender, EventArgs e)
        {
            Process[] notepads = Process.GetProcessesByName("notepadd");
            if (notepads.Length == 0) return;
            if (notepads[0] != null)
            {
                IntPtr child = FindWindowExW(notepads[0].MainWindowHandle, IntPtr.Zero, "Edit", null);
                SendMessageWStr(child, WM_SETTEXT, IntPtr.Zero, "abcd");
            }

        }
    }
}

雷米的功劳很大。经过一些故障排除后,我最终发现代码可以工作,所以我发现它为什么没有工作是个谜。

一个很好的故障排除步骤是尝试使用 nircmd 移动 window,这样你就知道你掌握了句柄。

要获取 window 的句柄,您可以使用 nirsoft winlister 或 winspector

您可以使用 nircmd 命令,例如 nircmd win close handle 0x00230632 将 0x00230632 更改为您找到的任何句柄。或者最好不要关闭它(否则你将不得不重新打开它并且新的 window 将有一个新的句柄),所以像 nircmd win move handle 0x00B917AE 80 10 100 100 这样的命令所以你知道句柄是正确的,不管代码的任何问题。

Winspector 也显示记事本的childwindow

回到C#代码,你可以

跳过child并尝试写入parent,它应该写入window

的标题

尝试使用 SendMessage 直接指定一个 window。你用十进制而不是十六进制写句柄。例如如果句柄是 3479948 那么

例如SendMessage(new IntPtr(3479948), WM_SETTEXT, IntPtr.Zero, "abcdee");

您还可以检查 notepads[0].MainWindowHandle 是否获取了正确的值.. winspector 中显示的句柄。

您可以查看 IntPtr child = FindWindowEx(...) 行,确保 'child' 正在拾取 child 句柄。

您可以尝试使用 SendMessage 直接写信给那个人。例如SendMessage(new IntPtr(1234567), WM_SETTEXT, IntPtr.Zero, "abcdee"); //(如果 winspector 显示 child window 是那个句柄)。