2012-01-08 74 views
2

我读通过我的发展项目中打开一个记事本的文字,这是我的代码记事本字符解码

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?

+1

有你使用记事本作为一个中间步骤,而不是直接打开文件流的原因是什么? – 2012-01-08 22:55:39

+1

是的,我想获得文本,而用户正在写 – 2012-01-08 22:58:41

+0

可能重复的[从Windows应用程序中的文本框刮]文本(http://stackoverflow.com/questions/8374531/scrape-text-from-textbox-in- Windows应用程序) – 2012-01-10 17:24:47

回答

4

你的问题实际上是你在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不会超过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); 
+0

仍然无法正常工作,我将CharSet更改为Ansi,然后将文本转换为UTF8 – 2012-01-08 23:07:21

+0

UTF8在哪里进入了一些操作? – 2012-01-08 23:07:56

+0

当调用GetText方法 – 2012-01-08 23:09:10

3

既然你在托管代码编写,你不妨使用托管代码自动化接口,它为你完成所有的互操作。为什么重新发明轮子?

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