2

我无法从正在运行的写字板实例获取文本范围。我已经获得了以下 Windows 消息,可以毫无问题地用于写字板:WM_GETTEXT、WM_GETTEXTLENGTH、EM_REPLACESEL、EM_GETSEL 和 EM_SETSEL。不过,我对 EM_GETTEXTRANGE 消息没有任何运气。

在我的 C# 测试应用程序中,我有一些在启动时运行的代码,它查找正在运行的写字板实例,然后在它的子窗口中搜索类名为 RICHEDIT50W 的窗口。这是我发送消息的窗口。同样,除了 EM_GETTEXTRANGE,我发送给这个窗口的所有消息都可以正常工作。发送 EM_GETTEXTRANGE 后,Marshal.GetLastWin32Error 返回 5,MSDN 说是 ERROR_ACCESS_DENIED。下面是我的一些互操作代码。有人可以帮我解决问题吗?谢谢!

const uint WM_USER = 0x0400; const uint EM_GETTEXTRANGE = WM_USER + 75;

[StructLayout(LayoutKind.Sequential)]
struct CharRange
{
  public int min;
  public int max;
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct TextRange
{
  public CharRange charRange;
  [MarshalAs(UnmanagedType.LPWStr)]
  public string text;
}

[DllImport("user32", CharSet = CharSet.Unicode, SetLastError = true)]
extern static int SendMessage(IntPtr hWnd, uint Msg, int wParam, ref TextRange lParam);

public static string GetTextRange(IntPtr wnd, int min, int max)
{
  TextRange textRange = new TextRange();
  textRange.charRange.min = min;
  textRange.charRange.max = max;
  textRange.text = new string('\0', max - min);

  int length = SendMessage(wnd, EM_GETTEXTRANGE, 0, ref textRange);
  int error = Marshal.GetLastWin32Error();

  return error == 0 ? textRange.text : string.Empty;
}

4

1 回答 1

2

我找到了自己问题的答案。当以另一个进程中的窗口为目标调用 SendMessage 时,必须在目标进程内存中为 >= WM_USER 的所有消息分配参数。所需的一切都可以通过调用函数 VirtualAllocEx、VirtualFreeEx、ReadProcessMemory 和 WriteProcessMemory 来完成。在另一个问题中提出了如何将 EM_GETTEXTRANGE 与 WriteProcessMemory 和 ReadProcessMemory 一起使用,但我最初认为这不适用于我正在做的事情,因为我没有完全理解这个问题。

于 2011-02-24T16:59:12.377 回答