记事本字符解码
本文关键字:解码 字符 记事本 | 更新日期: 2023-09-27 18:19:43
我正在程序打开的记事本上阅读文本。这是我的代码
const int WM_GETTEXT = 0x000D;
const int WM_GETTEXTLENGTH = 0x000E;
[DllImport("User32.dll", EntryPoint = "SendMessage")]
extern static int SendMessageGetTextLength(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
[DllImport("User32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
extern static IntPtr SendMessageGetText(IntPtr hWnd, int msg, IntPtr wParam, [Out] StringBuilder lParam);
[DllImport("user32.dll", EntryPoint = "FindWindowEx")]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
public static string GetText(IntPtr hwnd)
{
if (hwnd == IntPtr.Zero)
throw new ArgumentNullException("hwnd");
IntPtr handler = FindWindowEx(hwnd, new IntPtr(0), "Edit", null);
int length = SendMessageGetTextLength(handler, WM_GETTEXTLENGTH, IntPtr.Zero, IntPtr.Zero);
if (length > 0 && length < int.MaxValue)
{
length++;
StringBuilder sb = new StringBuilder(length);
SendMessageGetText(handler, WM_GETTEXT, (IntPtr)sb.Length, sb);
return sb.ToString();
}
return String.Empty;
}
它正在获取文本,但使用了特殊编码。例如,如果输入的文本是"hello",则会得到"興梀ȿڳㇺ'.这个文本的编码是什么,所以我可以把它解码成ASCII?
您的问题实际上是在WM_GETTEXT
消息中传递sb.Length
,而实际上您应该传递sb.Capacity
,甚至只是length
。
我会这样做:
if (length > 0 && length < int.MaxValue)
{
StringBuilder sb = new StringBuilder(length+1);
SendMessageGetText(handler, WM_GETTEXT, (IntPtr)length+1, sb);
return sb.ToString();
}
我还要指出,WM_GETTEXT
不会向length < int.MaxValue
返回超过64k个字符,这不是您所需要的。
当然,从长远来看,最好始终使用Unicode,以便支持国际文本。
我个人总是选择使用Unicode API,并使用以下p/invoke声明:
[DllImport("User32.dll", EntryPoint = "SendMessage",
CharSet = CharSet.Unicode, SetLastError = true)]
extern static int SendMessageGetTextLength(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
[DllImport("User32.dll", EntryPoint = "SendMessage",
CharSet = CharSet.Unicode, SetLastError = true)]
extern static IntPtr SendMessageGetText(IntPtr hWnd, int msg, IntPtr wParam, StringBuilder lParam);
[DllImport("user32.dll", EntryPoint = "FindWindowEx",
CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
由于您是用托管代码编写的,您还可以使用托管代码自动化接口,它为您完成所有的互操作。为什么要重新发明轮子?
using System.Windows.Automation;
public static string GetText(IntPtr hwnd)
{
IntPtr hwndEdit = FindWindowEx(hwnd, IntPtr.Zero, "Edit", null);
return (string)AutomationElement.FromHandle(hwndEdit).
GetCurrentPropertyValue(AutomationElement.NameProperty);
}
你甚至可以让自动化为你做FindWindowEx
:
public static string GetText(IntPtr hwnd)
{
var editElement = AutomationElement.FromHandle(hwnd).
FindFirst(TreeScope.Subtree,
new PropertyCondition(
AutomationElement.ClassNameProperty, "Edit"));
return (string)editElement.GetCurrentPropertyValue(AutomationElement.NameProperty);
}