Question

I'm having trouble getting a text range from a running instance of WordPad. I have gotten the following Windows messages to work for WordPad without a problem: WM_GETTEXT, WM_GETTEXTLENGTH, EM_REPLACESEL, EM_GETSEL, and EM_SETSEL. I'm not having any luck with the EM_GETTEXTRANGE message though.

In my C# test app I have some code that runs at startup which looks for a running instance of WordPad, then searches it's child windows for the window with the class name RICHEDIT50W. This is the window that I send messages to. Again, all of the messages I have sent this window work fine except for EM_GETTEXTRANGE. After sending EM_GETTEXTRANGE, Marshal.GetLastWin32Error returns 5, which MSDN says is ERROR_ACCESS_DENIED. Below is some of my interop code. Can someone please help me solve the problem? Thanks!

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

Was it helpful?

Solution

I found the answer to my own problem. When calling SendMessage targeting a window in another process, the parameters have to be allocated in target process memory for all messages that are >= WM_USER. Everything needed can be done by pinvoking the functions VirtualAllocEx, VirtualFreeEx, ReadProcessMemory, and WriteProcessMemory. It was brought up in another question at how to use EM_GETTEXTRANGE with WriteProcessMemory and ReadProcessMemory, but I originally didn't think this was applicable to what I was doing because I didn't fully understand the problem.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top