记事本字符解码

发布于 2024-12-25 14:43:31 字数 1292 浏览 0 评论 0原文

我正在从我的程序打开的记事本中读取文本。这是我的代码

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?

I am reading text from a notepad opened by my program.and this is my code

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

It is getting the text but in a special encoding.
For example, if the text entered is 'hello' it gets '興梀㇨ȿڳㇺ'.
What is the encoding of this text so I can decode it to ASCII?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

您的问题实际上是您在 WM_GETTEXT 消息中传递 sb.Length ,而实际上您应该传递 sb.Capacity 甚至只是长度

我会这样做:

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 不会返回超过 64k 字符的 length int.MaxValue 不是您所需要的。


当然,从长远来看,最好始终使用 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);

Your problem is in fact that you are passing sb.Length in the WM_GETTEXT message, when in fact you should be passing sb.Capacity or even just length.

I would do it like this:

if (length > 0 && length < int.MaxValue)
{
    StringBuilder sb = new StringBuilder(length+1);
    SendMessageGetText(handler, WM_GETTEXT, (IntPtr)length+1, sb);
    return sb.ToString();
}

I'd also point out that WM_GETTEXT will not return more than 64k characters to the length < int.MaxValue isn't what you need.


Of course, in the longer run it may be better to use the Unicode throughout so that you can support international text.

I personally would always opt for using the Unicode APIs and use the following p/invoke declarations:

[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);
ι不睡觉的鱼゛ 2025-01-01 14:43:31

由于您正在使用托管代码编写,因此您也可以使用托管代码自动化接口,它会为您完成所有互操作。为什么要重新发明轮子?

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

Since you're writing in managed code, you may as well use the managed code automation interfaces, which does all the interop for you. Why reinvent the wheel?

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

You can even make the automation do the FindWindowEx for you:

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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文