我在从另一个应用程序获取RichTextBox的RTF时遇到了困难。
现在,让我们使用写字板。
我可以很好地获取写字板中文本区域的句柄。 我甚至可以使用SendMessage和WM_GETTEXT从文本区域获取纯文本。 这一切都很好。
但是,我需要从其他应用程序获取RTF。 在文档中,我看到EM_STREAMOUT应该与EDITSTREAM结构一起使用。
到目前为止,这是我的代码。
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;
}
}
当我调用GetRTFFromActiveWindowElement方法时,我尝试读取的另一个应用程序(写字板)崩溃了。 最初我得到了调试其他程序的选项,并发现它是一个内存访问冲突。但是,我无法复制再次看到此错误消息。在当前状态下,另一个应用程序只是锁定并崩溃而没有错误消息。
请注意:写字板只是一个易于测试的应用程序。我也使用我自己的简单WinForms应用程序完成了这项工作,该应用程序中只有一个RichTextBox,并且存在同样的问题。
解决了这个问题之后,我还希望能够将RTF写回另一个应用程序。
建议?