c#我无法让SendMessage向记事本窗口发送消息

时间:2016-09-28 20:16:03

标签: c# .net winapi sendmessage

我看过这个问题并回答

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

我觉得应该没什么重要的变化..是我有一堆记事本窗口..所以要测试这个我复制notepad.exe是notepadd.exe并打开notepadd.exe,所以只有一个我的记事本窗口是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");
            }
        }
    }
}

虽然它没有碰到记事本窗口。

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

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

但我看到记事本窗口中没有出现任何内容

我没有从代码中得到错误,它只是没有出现在记事本窗口中。我并不太了解winapi的东西,所以我不知道如何继续尝试解决它? / p>

正如你所看到它到达那一行,我可以使用观察窗口查看记事本进程数组,以及'孩子',但我不知道我应该看什么来确定它为什么不发送到窗口

enter image description here

基于雷米建议的新代码

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");
            }

        }
    }
}

但是我仍然遇到同样的问题,即在点击按钮之前记事本窗口是空白的,之后也是空白的。它不是将文本发送到notepadd窗口。尽管它正在达到用于将文本发送给它的那行代码。

进一步补充。

当前代码,

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

我从cmd打开了notepadd.exe,我看到那里的窗口。当然还有任务管理器中的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 = "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");
            }

        }
    }
}

1 个答案:

答案 0 :(得分:0)

雷米非常感谢。经过一些故障排除后,我最终发现代码工作,所以这是一个谜,为什么我发现它没有。

一个很好的故障排除步骤是尝试用nircmd移动窗口,这样你就知道你有把柄。

要获取窗口的句柄,可以使用nirsoft winlister或winspector

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

Winspector还会显示记事本窗口的子项

enter image description here

回到C#代码,你可以

跳过孩子并尝试写入父母,它应该写入窗口的标题

尝试使用SendMessage直接指定窗口。您以十进制而不是十六进制编写句柄。例如如果句柄是3479948那么

e.g。 SendMessage(new IntPtr(3479948), WM_SETTEXT, IntPtr.Zero, "abcdee");

您还可以检查记事本[0] .MainWindowHandle正在拾取正确的值.. winspector中显示的句柄。

您可以查看IntPtr child = FindWindowEx(...)行,确保'孩子'正在拿起子句柄。

您可以尝试使用SendMessage直接写入该文件。例如SendMessage(new IntPtr(1234567), WM_SETTEXT, IntPtr.Zero, "abcdee"); //(如果winspector将子窗口显示为该句柄)。