I am attempting to follow the guidance in this blog post, which talks about using SendMessage to RichEdit with EM_STREAMOUT, and SF_BINARY and SF_HTML flags, to get HTML content from a RichEditControl. I am working in C#.
When I call SendMessage, debugging stops in Visual Studio and no exception is thrown. Any idea why? How can I get debugging information?
private static MemoryStream? memoryStream;
public static class WMConstants
{
public const uint WM_USER = 0x0400;
public const uint EM_STREAMOUT = WM_USER + 74;
public const uint SF_HTML = 0x00100000;
public const uint SF_BINARY = 0x0008;
public const uint SF_CLIPBOARD = 0x80000000;
}
[DllImport("user32.dll", CharSet = CharSet.Auto)]
[SuppressMessage("Interoperability", "SYSLIB1054:Use 'LibraryImportAttribute' instead of 'DllImportAttribute' to generate P/Invoke marshalling code at compile time", Justification = "<Pending>")]
private static extern IntPtr SendMessage(IntPtr hwnd, uint msg, uint wParam, ref EDITSTREAM lParam);
internal static string ReadHtml(IntPtr handle)
{
memoryStream = new MemoryStream();
var result = string.Empty;
var editStream = new EDITSTREAM
{
dwCookie = IntPtr.Zero,
pfnCallback = EditStreamProc,
};
try
{
_ = SendMessage(
hwnd: handle,
msg: WMConstants.EM_STREAMOUT,
wParam: WMConstants.SF_BINARY | WMConstants.SF_HTML, // | WMConstants.SF_CLIPBOARD,
lParam: ref editStream);
memoryStream.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(memoryStream))
{
result = reader.ReadToEnd();
}
}
catch (Exception ex)
{
// Log the exception if needed
throw new InvalidOperationException("Failed to read HTML from the RichTextBox.", ex);
}
finally
{
memoryStream?.Dispose();
memoryStream = null;
}
return result;
}
public static int EditStreamProc(IntPtr dwCookie, IntPtr pbBuff, int cb, out int pcb)
{
pcb = cb;
var buffer = new byte[cb];
Marshal.Copy(pbBuff, buffer, 0, cb);
memoryStream!.Write(buffer, 0, cb);
return 0;
}
[StructLayout(LayoutKind.Sequential)]
private struct EDITSTREAM
{
public IntPtr dwCookie;
public uint dwError;
public EditStreamCallback pfnCallback;
}