Attach window to window of another process
Asked Answered
D

3

4

My WPF application has more than one window, I want to attach some of these windows to a window of another process. My problem is that once I attach my window it becomes invisible.

I'm trying this with the following code:

public static bool setParentWindow(IntPtr hWndChild, IntPtr hWndNewParent)
    {
    IntPtr previousParent = SetParent(hWndChild, hWndNewParent);
    return (previousParent == null ? false : true);
}

[DllImport("user32.dll", SetLastError = true)]
private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

setParentWindow(myWindowHwnd, newParentHwnd);

So, the above code successfully attaches the window, but unfortunately makes it invisible.

My reason for doing this is that I'm trying to extend an application by building "Widgets" for it, my widgets will hook in and show the user extra information.

Both windows have the following styles: WS_OVERLAPPEDWINDOW, WS_OVERLAPPED, WS_VISIBLE, WS_CLIPSIBLINGS, WS_CLIPCHILDREN.

Disputant answered 20/5, 2012 at 19:50 Comment(6)
What do you mean by attaching a window? What are the window styles of the windows that are involved?Deeplaid
@Neil: I've added the styles to the end of my question, by attach I mean that I want my WPF window to be a child of the new window.Disputant
Re-parenting windows into other processes is extremely hard. I'd recommend a different solution.Lent
@DavidHeffernan: My window needs to either be a child, or just appear (to the user) to be a child. Do you know anyway to do the latter.Disputant
Do you have control of the other app? If so, then do the coding in that other app. If not then what makes you think that you can push another processes window, and a WPF one at that, into this other app?Lent
I don't have control over the app. I think it should be possible because the window is successfully re-parented, I can see my window is there by using spy++, it's just invisible.Disputant
D
7

I found that I could do this without even using the setParent call. I used HwndSource class as follows:

MyWindow window = new MyWindow();
window.ShowActivated = true;

HwndSourceParameters parameters = new HwndSourceParameters();

parameters.WindowStyle = 0x10000000 | 0x40000000;
parameters.SetPosition(0, 0);
parameters.SetSize((int)window.Width, (int)window.Height);
parameters.ParentWindow = newParent;
parameters.UsesPerPixelOpacity = true;
HwndSource src = new HwndSource(parameters);

src.CompositionTarget.BackgroundColor = Colors.Transparent;
src.RootVisual = (Visual)window.Content;

This is working great now without any problems.

Disputant answered 20/5, 2012 at 23:38 Comment(2)
Hi @Gerve. Yours is the only example I could find of what I'm trying to do, but it doesn't work for me. Spy++ tells me that in my case, MyWindow is NOT a child of newParent. My questions are: a) what values do you set for the WindowStyle, AllowsTransparency and Background properties of MyWindow in MyWindow.xaml? b) Do you call Show() on the window? If so does it matter whether you do it before or after the above code? c) In my case, MyWindow gets the WS_EX_LAYERED extended style, which I read is incompatible with child windows. Not sure why. d) Do you set any other styles with SetWindowLong()?Allot
My WPF Window has always a black background (regardless if I set it's background color to transparent (and allow transparency) or to a color)...Uralaltaic
D
1

I'm not sure what you need to do with overlapped windows, but from MSDN:

For compatibility reasons, SetParent does not modify the WS_CHILD or WS_POPUP window styles of the window whose parent is being changed. Therefore, if hWndNewParent is NULL, you should also clear the WS_CHILD bit and set the WS_POPUP style after calling SetParent. Conversely, if hWndNewParent is not NULL and the window was previously a child of the desktop, you should clear the WS_POPUP style and set the WS_CHILD style before calling SetParent.

Deeplaid answered 20/5, 2012 at 20:21 Comment(0)
M
0
private void TryToAttach(IntPtr ownerHandle)
{
    if(ownerHandle == IntPtr.Zero)
    {
        return;
    }
    try
    {
        var helper = new WindowInteropHelper(window) { Owner = ownerHandle };
    }
    catch(Exception e)
    {
        Logger.Error(e, "Could not attach window.");
    }
}
Mezereum answered 4/1, 2018 at 14:48 Comment(3)
While this may answer the question, it doesn't provide any context to explain how or why. Consider adding a sentence or two to explain your answer.Carry
WindowInteropHelper is class from System.Windows.Interop namesapce. Assists interoperation between Windows Presentation Foundation (WPF) and Win32 code.Mezereum
I'm glad to see you're trying to improve your answer, as a rule you should add clarifications like that in your answer by editing rather than in the comments. Comments can get cleaned up and not everyone reads them so your clarification could be missed.Carry

© 2022 - 2024 — McMap. All rights reserved.