wpfdirectxwebbrowser-controloleiwebbrowser2

DirectX, bouncing a directx rendering from a source hwnd to a new target hwnd


I have a considerable challenging subject i'm trying to figure out.

Within WPF/WinForms I can create a WebBrowser component which has significant limitations, these would be drastically resolved/reduced if i can bounce the directx surface from the web browser control to a DirectX surface i have setup.

A few things to note:

  1. The WebBrowser component hosts IWebBrowser2 OLE/ActiveX component in a "floating" window above existing content as a child window of the WPF window.

  2. I know and can get (without hacks) the HWND of the floating window; and the sub-classed HWND's of the children which have the actual Internet Explorer component running.

  3. I can confirm that the window is rendering with directX, but i do not have any handles to anything outside of a HWND. I do not know the surface its rendering to, the device, or anything else.

What I've found as potential solutions:

  1. BitBlt the child window to a WPF surface to solve the problem; this is an option of last resort as it would require a timer to capture, and update the bitmap. This seems wasteful and doesn't seem to be all that great.

  2. The option to "Redirect" a HWND's directx surface has been noted as "trivial" by Microsoft Blog writers, but they never actually explain how. So there may be a non-directx non-gdi method thats more high-level that might work if anyone knows of one.

  3. Use a swap chain to bounce the directx surface from the source WebBrowser HWND to the new target. This is my optimal choice; but its difficult to even begin since I do not have anything other than the HWND of the target. (I'm not limited to WPF, other tech such as OLE/COM/MFC/ATL/WinForms solutions are great!)

  4. Is there a way to access the directx device from a OLE/COM object?... Kind of a hail marry, using reflection/debuggers i can't seem to find any reference to it. But this is also somewhat hack-y as i'm digging deep into the internals of the implementation.

Is there any pointers, hints or direction anyone can provide on how i might best accomplish this with the minimal "hackery" and maximum performance?


Solution

  • To begin with, I really don't think you can force WebBrowser to render directly onto your custom DirectDraw surface. However, you might be able to provide a DD surface's HDC to draw onto.

    If you want to play with this, WebBrowser ActiveX control implements Windowless ActiveX Controls interfaces. In theory, you could implement a windowless ActiveX host and use IViewObject::Draw to draw onto the DD surface's HDC. I cannot predict what the performance of this would be, but I doubt it would even closely approach the native DirectDraw performance of Trident rendering engine.

    I also posted a somewhat related code which uses OleDraw (which indirectly calls IViewObject::Draw).