Discussion:
MSHTML passing a RemotableHandle C#
(too old to reply)
Menard Soliven
2004-06-01 18:58:14 UTC
Permalink
Hi People,

I'm having trouble passing a Windows Handle ( regardless of whether it
is a Bitmap or Printer Handler ) to the MSHTML Active X control's
IHTMLElementRender interface to the DrawToDC() method using C#.

The first approach that I did was to use the RemotableHandle structure
exposed by mshtml:

// Create a _RemotableHandle instance
mshtml._RemotableHandle dcRemote = new
mshtml._RemotableHandle();

const int WDT_INPROC_CALL = 0x48746457;

dcRemote.fContext = WDT_INPROC_CALL; // or should I use
WDT_REMOTE_CALL ??
dcRemote.u.hInproc = hdcBitmap.ToInt32();

Although the above solved my casting problem, I get an "Invalid
Handle" exception when I pass the above structure to the
IHTMLElementRender.DrawToDC() method.

My second approach was to modify the type library of the
Microsoft.Mshtml.DLL
(a tip I got from this newsgroup) :

1. ILDASM Microsoft.mshtml.dll /out=Microsoft.mshtml.il
2. Modified the handle type in the IL code from "_RemotableHandle" to
int
3. ILASM /DLL Microsoft.mshtml.il /RES=Microsoft.mshtml.res

Although ILDASM worked to produce the lengthy IL code, I can't
successfully assemble the IL back to its original DLL form using ILASM
as I get a "FAILURE MESSAGE".

Any level of help would be greatly appreciated.

Thanks in advance!

Menard
stepan hrivna
2004-08-06 14:21:02 UTC
Permalink
Hi Menard

I tried to work with IHTMLElementRender.DrawToDC() by the same way like you
with same result. But what I found before exception "Invalid handle" was that
value of variable which I declared as IHTMLElementRender was not
IHTMLElementRender but it was HTMLBodyClass (after Querynterface). I don't
know which way did you use to obtain instance of IHTMLElementRender. I used

Guid guid;
System.IntPtr pin,pout;
IHTMLDocument2 doc;
Type rendertype;

doc = (IHTMLDocument2) axWebBrowser1.Document;
IHTMLElement el = (IHTMLElement) doc.body;
pin=Marshal.GetComInterfaceForObject(doc,Type.GetType("mshtml.IHTMLElement"));

pout = System.IntPtr.Zero;
guid = new Guid("{3050F669-98B511CF-BB82-00AA00BDCE0B}");
int hres = System.Runtime.InteropServices.Marshal.QueryInterface(pin, ref
guid, out pout);

rendertype = Type.GetTypeFromCLSID(guid);

IHTMLElementRender render =
(IHTMLElementRender)Marshal.GetTypedObjectForIUnknown(pout,rendertype);

Finally I used

_RemotableHandle structt = new _RemotableHandle();
structt.fContext = 0x48746457;
structt.u.hInproc = (int) gr.GetHdc().ToInt32();
render.DrawToDC(ref structt);

invalid handle was reason that render wasn't IHTMLElementRender but
HTMLBodyClass. I think that I'm (or we are) doing something wrong.

BR

Stepan
Post by Menard Soliven
Hi People,
I'm having trouble passing a Windows Handle ( regardless of whether it
is a Bitmap or Printer Handler ) to the MSHTML Active X control's
IHTMLElementRender interface to the DrawToDC() method using C#.
The first approach that I did was to use the RemotableHandle structure
// Create a _RemotableHandle instance
mshtml._RemotableHandle dcRemote = new
mshtml._RemotableHandle();
const int WDT_INPROC_CALL = 0x48746457;
dcRemote.fContext = WDT_INPROC_CALL; // or should I use
WDT_REMOTE_CALL ??
dcRemote.u.hInproc = hdcBitmap.ToInt32();
Although the above solved my casting problem, I get an "Invalid
Handle" exception when I pass the above structure to the
IHTMLElementRender.DrawToDC() method.
My second approach was to modify the type library of the
Microsoft.Mshtml.DLL
1. ILDASM Microsoft.mshtml.dll /out=Microsoft.mshtml.il
2. Modified the handle type in the IL code from "_RemotableHandle" to
int
3. ILASM /DLL Microsoft.mshtml.il /RES=Microsoft.mshtml.res
Although ILDASM worked to produce the lengthy IL code, I can't
successfully assemble the IL back to its original DLL form using ILASM
as I get a "FAILURE MESSAGE".
Any level of help would be greatly appreciated.
Thanks in advance!
Menard
MEnard Soliven
2004-08-06 15:06:23 UTC
Permalink
Hi Stepan,

I finally have this working with the help of a good samaritan. Forget
about the RemotableHandle problem that I mentioned. You don't need to
pass it that way. It's actually a bug with the MSHTML interface. You
need to redefine DrawToDC() in order for it to work.

[
Guid("3050f669-98b5-11cf-bb82-00aa00bdce0b"),
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown),
ComVisible(true),
ComImport
]
interface IHTMLElementRender
{
void DrawToDC([In] IntPtr hDC);
void SetDocumentPrinter([In, MarshalAs(UnmanagedType.BStr)] string
bstrPrinterName, [In] IntPtr hDC); };



Here's how I got IHTMLElementRender:


IHTMLDocument2 objDocument = (mshtml.IHTMLDocument2)
this.objWebBrowser.Document;

if (objDocument != null)
{
IHTMLElement objElement;
objElement = objDocument.body;

if (objElement != null)
{
IHTMLElementRender objRender = (mshtml.IHTMLElementRender)
objElement;


From then on, you can invoke Win32 code to capture the rendered image:

IntPtr hMemDC = g.GetHdc();

int vertRes = Gdi32.GetDeviceCaps(hMemDC, Gdi32.VERTRES);
int y = bitmap.Height;

while (y > vertRes)
{
y -= vertRes;
POINT pt;
Gdi32.SetViewportOrgEx(hMemDC, 0, -y, out pt);
pRender.DrawToDC(hMemDC);
Gdi32.SetViewportOrgEx(hMemDC, pt.x, pt.y, out pt);
Gdi32.BitBlt(hMemDC, 0, y, bitmap.Width, vertRes, hMemDC, 0,
0, Gdi32.SRCCOPY);
}

objRender.DrawToDC(hMemDC);






*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!

Loading...