2012-01-08 3 views
2

Я читаю текст из блокнота открыл мой program.and это мой кодблокнота декодирование символов

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

Есть ли причина, что вы используете блокнот в качестве промежуточного шага вместо того, чтобы открыть поток файла непосредственно? –

+1

Да, я хочу получить текст, пока пользователь пишет –

+0

Возможный дубликат [Скрап текст из текстового поля в приложении Windows] (http://stackoverflow.com/questions/8374531/scrape-text-from-textbox-in- windows-application) –

ответ

4

Ваша проблема заключается в том, что вы передаете sb.Length в WM_GETTEXT сообщении, когда на самом деле вы должны быть прохождение 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 не то, что вам нужно.


Конечно, в долгосрочной перспективе может быть лучше использовать Юникод повсюду, чтобы вы могли поддерживать международный текст.

лично я бы всегда выбираю для использования API, Unicode и использовать следующий р/ссылаться на заявлении:

[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 –

+0

Где UTF8 входит в вещи? –

+0

при вызове метода GetText –

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); 
} 
Смежные вопросы