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,但它仍然没有响应。
我从 cmd 打开了 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 是那个句柄)。
我看过这个问答
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,但它仍然没有响应。
我从 cmd 打开了 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 是那个句柄)。