Jim Tomasko

I'm trying to make a UserControl that I can use as the frame of an unmanaged window using a 3rd party unmanaged library.

The libary has a call where I pass it an HWND and a RECT, and it will make a child window for displaying it's content. Back when using windows forms, I had this working just fine. Now I'm attempting to do the same thing in WPF.

I can see how to get the window handle of the parent window... I use the WindowInteropHelper class and pass it's constructor the "this" of my window. But I can't find anything like that for a UserControl. I've checked to make sure that if I use the window as the target for the unmanaged content's parent, that it works, so now I've just got to find a way to get this in a control.

I have one goal here:

1. Make a UserControl that I can use as the target for my lib's functionality, so I can use it as a viewer of this special content.

The motivation for this goal is that I am creating the complete functionality for my application as content creation/manipulation classes, so that a designer using expression blend will be able to completely do the UI on their own. The only thing stopping me from finishing this right now is that I need a way for the UI designer to place and configure a specialized content window that meets the requirement of binding with the aforementioned library.

Thanks,

Jim Tomasko



Re: Windows Presentation Foundation (WPF) Any way to get an HWND of a UserControl?

Peter S Antal - MSFT

So, you want to host an 3rd party Hwnd in your WPF app, which needs the parent Hwnd...

What you want to do is derive from HwndHost. Check it out here:

http://msdn2.microsoft.com/en-us/library/system.windows.interop.hwndhost.aspx

Cheers,


Peter






Re: Windows Presentation Foundation (WPF) Any way to get an HWND of a UserControl?

Yiling Lai

UIElement myWPF = new UIElement();
HwndSource source = new HwndSource(
0, // class style
WS_VISIBLE | WS_CHILD, // window style
0, // exstyle
x, y, width, height,
"My WPF Control", // NAME
IntPtr(parent) // parent window
);

source.RootVisual = myWPF;
HWND WPFHwnd = (HWND) source.Handle.ToPointer();






Re: Windows Presentation Foundation (WPF) Any way to get an HWND of a UserControl?

Jim Tomasko

Thanks Peter, I'm working hard on getting my familuraity up with WPF. Even with all the time I'm spending, I would not have found this without help... but nothing a year or two of work will not cure.

Unfortunately, I'm still stuck. Using Yiling's and your replies, I see that there is a path to getting this to work. Unfortunately I'm still in the "cookbook stage" of my knowledge, and am having trouble getting this to work with a UserControl.

Unless I am missing something else I have not found, my control needs to be based on a UserControl so that it will be exposed by Expression Blend for use by a designer. I currently have the following code for the shell of this control:

<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SvClient.SvcViewControl"
x:Name="SvcViewControl1"
Width="320" Height="200">

<Grid x:Name="LayoutRoot" Background="#FFBEFBFB"/>
</UserControl>

Along with a C# partial class defined as:

public partial class SvcViewControl { ... }

If I attempt to inherit any other base class on the partial definition (such as HwndHost or UIElement), I get a compile error telling me that my partial class must not specify different base classes. This all seems reasonable to me, but in the last two days I've attempted to find if there is a way to inform my WPF code that this class inherits from something else, or some other way to get around this.

Any ideas

Thanks again,

Jim Tomasko





Re: Windows Presentation Foundation (WPF) Any way to get an HWND of a UserControl?

Jim Tomasko

Thank you Yiling for that answer. It is definatly 75% of my answer, but I'm still missing one piece of the puzzle. Two of you replied, so I only wrote the full responce once.

It's a pleasure to be in the company of people that are so helpful.

Jim Tomasko





Re: Windows Presentation Foundation (WPF) Any way to get an HWND of a UserControl?

Yiling Lai

Hello, I don't think you need to inherit from HwndHost, instead inherit from UserControl. And use you SvcViewControl to raplace the UIElement in my previous sample code.






Re: Windows Presentation Foundation (WPF) Any way to get an HWND of a UserControl?

Dave Herzig

Hi

Do you look for something like:

// Control element

Button b = new Button();

// Get the HWND

HwndSource hwnd = (HwndSource)HwndSource.FromVisual(b);

regards,

David





Re: Windows Presentation Foundation (WPF) Any way to get an HWND of a UserControl?

Jim Tomasko

Hi Yiling,

Sorry my reply has taken so long... I was redirected from this task for a while.

I'm not sure what is supposed to go into "parent" in the HwndSource function.

I'm not sure if this has been clear as of yet, but I do not have a win32 window to point at during the time I need to create a handle to my usercontrol. (Maybe this doesn't matter, but I can't tell you what a hard time I'm having reading this and understanding it. This WPF is very new to me, although I have been a windows programmer for many years.)

I'm not attempting to create a window (unless I have to make a child to my userwindow just to get it's HWND). What I'm trying to do is just get the HWND of my usercontrol. Once I have that, I will call a libaray function that requires an HWND and a rectangle, which will build it's content as a child of the window given by the HWND.

Thanks again,

Jim Tomasko





Re: Windows Presentation Foundation (WPF) Any way to get an HWND of a UserControl?

Yiling Lai

Hello, if you just want to get the handle of your UserControl and don¡¯t want host it in Win32 window, you can use Dave¡®s answer.

YourUserControl wpfctrl = new YourUserControl();

HwndSource source = (HwndSource)HwndSource.FromVisual(wpfctrl);

IntPtr hWnd = source.Handle;






Re: Windows Presentation Foundation (WPF) Any way to get an HWND of a UserControl?

Josh Smith

I think the fundamental problem here is that in WPF controls are not windows. Unlike the Win32 model where every control has an HWND associated with it, in WPF pretty much the only thing with an HWND is the Window which hosts everything else. With that being the case, porting your code from WinForms to WPF, and expecting a UserControl to have an HWND, is not going to work out easily. I think that Peter's suggestion of subclassing HwndSource is the way to go.

The idea of using HwndSource to get the HWND of a UserControl is not going to work because, as stated earlier, a UserControl does not have an HWND. In fact, if you run this (assume this.Content is a UserControl):

Code Snippet

void Window1_Loaded(object sender, RoutedEventArgs e)

{

HwndSource panelHwnd = HwndSource.FromVisual(this.Content as UserControl) as HwndSource;

WindowInteropHelper windowHwnd =new WindowInteropHelper(this);

bool same = panelHwnd.Handle == windowHwnd.Handle;

Debug.Assert(same);

}

...the assertion does not fail. So, the call to HwndSource.FromVisual() just walks up the element tree looking for the first Win32 Window it can find. What it finds is the main Window itself, not some special Window somehow owned by the UserControl.

Regarding your trouble with subclassing UserControl, try explicitly specifying the base class in the C# code-behind to be UserControl. In the example code you posted, the XAML explicitly declared what the base class is, but the C# code did not. Doing so might fix the problem. You can subclass whatever non-sealed class you need to.

HTH






Re: Windows Presentation Foundation (WPF) Any way to get an HWND of a UserControl?

Jim Tomasko

Thanks to everyone for looking at this. I got a lot of good ideas on where to look and what is and is not possible.

So after much reading, mostly directed by these posts... I've finally come to see that only the parent window has a handle. So what it looks like is the answer is to do the following:

1. Get the HWND of the parent window (which is the only HWND in that entire hierarchy)

2. Use my UserControl as a sort of placeholder as to where the content from my library will go.

3. Call my lib's content creation function, which wants an HWND and a rectangle... the HWND will be the one and only, and the rectangle will come from my usercontrol.

4. Monitor changes in the UserControl's position, and report that back to the lib to change the size of the content.

While this seems a bit on the "cludgey" side, I guess the real design problem is not with WPF, and more with how my content library makes me talk with it.

Thanks again!

Jim