Reading RTF RichTextBox in another application
I am having difficulty getting an RTF RichTextBox from another application.
Now let's work with WordPad.
I can get the handle to the textarea in WordPad just fine. And even I can get plain text from the textarea using SendMessage and WM_GETTEXT. It's all good.
However, I need to get RTF from another application. In the docs, I see that EM_STREAMOUT should be used with an EDITSTREAM structure.
Here is the code I have for this so far.
private const uint WM_USER = 0x0400;
private const uint EM_STREAMOUT = WM_USER + 74;
private const uint SF_RTF = 2;
[DllImport("user32.dll", EntryPoint="GetForegroundWindow")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll", EntryPoint="GetWindowThreadProcessId", SetLastError=true)]
private static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out IntPtr lpdwProcessId);
[DllImport("user32.dll", EntryPoint="GetGUIThreadInfo", SetLastError=true)]
private static extern bool GetGUIThreadInfo(IntPtr hThreadID, ref GUITHREADINFO lpgui);
[DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, uint msg, uint wParam, ref EDITSTREAM lParam);
private delegate int EditStreamCallback(MemoryStream dwCookie, IntPtr pbBuff, int cb, out int pcb);
private static int EditStreamProc(MemoryStream dwCookie, IntPtr pbBuff, int cb, out int pcb)
{
pcb = cb;
byte[] buffer = new byte[cb];
Marshal.Copy(pbBuff, buffer, 0, cb);
dwCookie.Write(buffer, 0, cb);
return 0;
}
[StructLayout(LayoutKind.Sequential)]
private class EDITSTREAM
{
public MemoryStream dwCookie;
public uint dwError;
public EditStreamCallback pfnCallback;
}
private struct RECT
{
public int iLeft;
public int iTop;
public int iRight;
public int iBottom;
}
private struct GUITHREADINFO
{
public int cbSize;
public int flags;
public IntPtr hwndActive;
public IntPtr hwndFocus;
public IntPtr hwndCapture;
public IntPtr hwndMenuOwner;
public IntPtr hwndMoveSize;
public IntPtr hwndCaret;
public RECT rectCaret;
}
public static string GetRTFFromActiveWindowElement()
{
try
{
IntPtr windowHWnd = GetForegroundWindow();
IntPtr lpdwProcessId;
IntPtr threadId = GetWindowThreadProcessId(windowHWnd, out lpdwProcessId);
GUITHREADINFO lpgui = new GUITHREADINFO();
lpgui.cbSize = Marshal.SizeOf(lpgui);
GetGUIThreadInfo(threadId, ref lpgui);
string result = String.Empty;
using (MemoryStream stream = new MemoryStream())
{
EDITSTREAM editStream = new EDITSTREAM();
editStream.pfnCallback = new EditStreamCallback(EditStreamProc);
editStream.dwCookie = stream;
SendMessage(lpgui.hwndFocus, EM_STREAMOUT, SF_RTF, ref editStream);
stream.Seek(0, SeekOrigin.Begin);
using (StreamReader reader = new StreamReader(stream))
{
result = reader.ReadToEnd();
}
}
return result;
}
catch (Exception e)
{
Console.Write(e.Message);
return null;
}
}
When I call the GetRTFFromActiveWindowElement method, another application crashes that I am trying to read from (WordPad). Initially I was getting the ability to debug another program and saw that it was a memory access violation. However, I am unable to repeat this error message. In its current state, the other application simply blocks and crashes without an error message.
Just a side note: WordPad is a simple testing application. I also did it with my own simple WinForms app which only has RichTextBox and the same problem exists.
After solving this problem, I would also like to write the RTF back to another application.
Suggestions?
source to share
No one has answered this question yet
Check out similar questions: