GDI rendering to WPF window - wpf

I've done some searching, but I can't find an exact answer on this. In my C# WPF app, I get the HWND pointer and pass it to a C dll. That C dll then attempts to use GDI calls to render an overlay of sorts on my window. There are no errors, but nothing appears. If I switch to a Windows Form, the dll can render over it fine. If I host a WindowsFormHost control and use the hwnd from there I have the same effect. I've seen information on the HwndHost control but it doesn't really look like what I want. Perhaps someone with more knowledge of that control can tell me differently. I read somewhere that an hwnd used for DirectX rendering (like WPF) can't also use GDI. Does this make my scenario impossible? I could fake it by overlaying a borderless form over the WPF window, but obviously that wouldn't be too pretty. Any thoughts or ideas?

You can't have WPF and GDI rendering to the same hwnd but you can easily have a child hwnd inside of your WPF app and let GDI render into it. Take a look at HwndHost for doing that. The section "Hosting a Microsoft Win32 Window in WPF" in this article has a little more details. It also talks about the various issues you'll run into (like airspace) when doing this type of interop.

Related

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:
The WebBrowser component hosts IWebBrowser2 OLE/ActiveX component in a "floating" window above existing content as a child window of the WPF window.
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.
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:
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.
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.
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!)
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?
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).

How to use the WinRT SwapChainPanel control in a WPF window?

I added references to WinRT dlls to a WPF project and I want to use SwapChainPanel inside of a WPF window.
Is it really possible? For now I cant get it work.
The NuGet package description for Microsoft.Toolkit.Wpf.UI.Controls mentions a SwapChainPanel but I have not found any samples using this control in WPF.
SwapChainPanel : Provides a hosting surface, where Microsoft DirectX swap chains provide content that can be rendered into a XAML UI. A SwapChainPanel element is a key component for an app that renders Microsoft DirectX graphics and then presents those visuals within a XAML page.
It's not currently officially supported - might require some private APIs in Windows, though since Stardock could implement its ModernMix - there might be some way to get it working. The thing is though - you don't have to do that. You can render content with DirectX to a WPF window in other ways. I haven't done that and it might be quite a bit of work to do, but so is anything in DirectX. You can look into DirectComposition or D3DImage class. Perhaps the article on using Direct2D with WPF can be a good sample solution.
You dont have to, as says Filip Skakun, but you can ! Just give a try to SlimDX or SharpDX. They're DirectX's implementations in C#.

Controls to use for Video Stream?

I currently have LibVLC setup with a C# project and it uses a Panel to output the video stream. As WPF is better suited for some GUI options I want to implement, I have now switched my project over to it. However, I noticed that WPF Controls don't have handles like C# controls do.
I have found these...
http://wpfmediakit.codeplex.com/
http://videorendererelement.codeplex.com
However I am new to WPF and have no idea how to actually integrate them. What would be the best approach to output the video streams from LibVlC in WPF?
I managed to resolve this by using a WindowsFormsHost control and just use a Panel as I was doing previously in my Win Forms application. Still seems that using something else native to WPF would be preferable, but for now this is working fine.
I'm afraid that's not possible...
Since WPF controls are not Win32 controls behind the scenes (the MS specific HWND or the more general HANDLE), like most WinForms controls are, providing a HANDLE to libvlc for rendering is not possible or not easy.
See here
All WPF elements on the screen are ultimately backed by a HWND. When you create a WPF Window, WPF creates a top-level HWND, and uses an HwndSource to put the Window and its WPF content inside the HWND. The rest of your WPF content in the application shares that singular HWND. An exception is menus, combo box drop downs, and other pop-ups. These elements create their own top-level window, which is why a WPF menu can potentially go past the edge of the window HWND that contains it.
You could try to use a Window and attempt to get its Handle like this:
IntPtr windowHandle = new WindowInteropHelper(windowInstance).Handle
Then pass this handle to libvlc. Remember to obtain this handle no sooner than inside the Loaded event of the window, see here
But this will limit you to using a top level Window control, which doesn't seem to be what you want.

How to set Win32 window as owner of WPF window?

I want to use WPF windows in a legacy win32 application.
I'd like to behave them in a similar way, like the WPF window always being displayed on top of the win32 window.
For this I'd like to set the owner of the WPF window to the win32 windows, but I got no idea how to achieve this.
Any help here?
Since the answer is hidden behind some link, here the code that did the trick:
System::Windows::Interop::WindowInteropHelper^ helper = gcnew System::Windows::Interop::WindowInteropHelper(myWpfChildWindow);
helper->Owner = (System::IntPtr)myMainWindowHWND;
This article shows how to get the handles for both as well as how to make the WPF window become a transparent overlay for the win32 window.
http://dedjo.blogspot.com/2007/04/transparent-wpf-control-over-unmanaged.html
This article uses a WindowInteropHelper to accomplish similar functionality.
http://blogs.msdn.com/wpfsdk/archive/2007/04/03/centering-wpf-windows-with-wpf-and-non-wpf-owner-windows.aspx
MSDN page on WindowInteropHelper:
http://msdn.microsoft.com/en-us/library/system.windows.interop.windowinterophelper.aspx
Hope that helps,
Ed
How about SetParent()? I know works when making a WPF window an MDI Child of a Windows Form.

WPF Interop & Dialogs

I have an existing WinForms application for which I'm now designing new bits in WPF. Things are going reasonably well and I have run into my first need for a dialog.
I'd like to do the dialog in WPF. It appears as though I'm going to need to do a UserControl for the actual content and then host that content via a WinForms form with an ElementHost (since UserControl has no ShowDialog() method).
And that's where my question is. How does that work? Best I can tell, the WPF UserControl doesn't even have a DialogResult property (which makes sense given that it has no ShowDialog() method) - it looks to me like I'd need a WPF Window control - and I don't think I can use that in this case.
Struggling with the basic flow and setup of things here. Can someone shine a light?
Is this even possible?
You can open a WPF window from a WinForms application.
Just create the window and call ShowDialog(). The CLR will load the WPF framework and open the window.
If you want your interop application to work mostly like a WinForms app, then the approach you describe works fine -- I've pretty much the same thing in my interop cases.
WPF supports MessageBoxes (albeit a slightly different version than WinForms), and you could put something together using WPF Windows (extending it by adding something similar to DialogResult). However, the provided WPF controls suggest that they're trying to change UX interactions to minimize dialogs, particularly modal ones.
To make your life easier though, I would create a WinForms Form/ElementHost subclass specifically for dealing w/hosting WPF content, and depending on how clean you like your "using" declarations, wrapping your own DialogResult-like enumeration so you don't have to include the System.Windows.Forms namespace which can make your WPF code-behinds more cumbersome.

Resources