décodage des caractères du bloc-notes

Je lis le texte d’un bloc-notes ouvert par mon programme.et c’est mon 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] SsortingngBuilder lParam); [DllImport("user32.dll", EntryPoint = "FindWindowEx")] public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, ssortingng lpszClass, ssortingng lpszWindow); public static ssortingng 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; } 

C’est obtenir le texte mais dans un encodage spécial. Par exemple, si le texte saisi est «hello», il devient «興 梀 ㇨ ȿ ڳ ㇺ». Quel est l’encodage de ce texte pour pouvoir le décoder en ASCII?

Votre problème est en fait que vous transmettez sb.Length dans le message WM_GETTEXT , alors qu’en fait vous devez transmettre sb.Capacity ou même simplement la length .

Je le ferais comme ça:

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

Je ferais également remarquer que WM_GETTEXT ne renverra pas plus de 64 k caractères à la length < int.MaxValue n'est pas ce dont vous avez besoin.


Bien entendu, à long terme, il est préférable d’utiliser l’Unicode pour prendre en charge le texte international.

Personnellement, je choisirais toujours d'utiliser les API Unicode et d'utiliser les déclarations p / invoke suivantes:

 [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, SsortingngBuilder lParam); [DllImport("user32.dll", EntryPoint = "FindWindowEx", CharSet = CharSet.Unicode, SetLastError = true)] public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, ssortingng lpszClass, ssortingng lpszWindow); 

Puisque vous écrivez en code managé, vous pouvez également utiliser les interfaces d’automatisation de code managé, qui font tout l’interopérabilité pour vous. Pourquoi réinventer la roue?

 using System.Windows.Automation; public static ssortingng GetText(IntPtr hwnd) { IntPtr hwndEdit = FindWindowEx(hwnd, IntPtr.Zero, "Edit", null); return (ssortingng)AutomationElement.FromHandle(hwndEdit). GetCurrentPropertyValue(AutomationElement.NameProperty); } 

Vous pouvez même faire en sorte que l’automatisation fasse le FindWindowEx pour vous:

 public static ssortingng GetText(IntPtr hwnd) { var editElement = AutomationElement.FromHandle(hwnd). FindFirst(TreeScope.Subtree, new PropertyCondition( AutomationElement.ClassNameProperty, "Edit")); return (ssortingng)editElement.GetCurrentPropertyValue(AutomationElement.NameProperty); }