Search code examples
c#wpfuser32setparent

Set the parent window for the winform form with a transparent background C#


Please help me figure out the problem. There is a form on WinForms. I ask her the parent: SetParent(guestHandle, hostHandle); SetWindowLongPtr(guestHandle, GWL_STYLE, GetWindowLong(guestHandle, GWL_STYLE) | WS_CHILD); The form is moved to the parent window.

Everything stops working when I set a transparent background for the form. The form becomes a child, but it is not visible.

I tried installing transparency via user32, I tried to do the same with the wpf. There is no result. How to achieve a working window with transparency in the parent application?

P.s. The child window is embedded in a third-party application.

Sample code:

using System;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Media;

namespace Demo
{
    public partial class MainWindow : Window
    {
        [DllImport("user32.dll", EntryPoint = "SetWindowLong")]
        private static extern int SetWindowLong32(IntPtr hWnd, int nIndex, int dwNewLong);

        [DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
        private static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, int nIndex, int dwNewLong);

        [DllImport("user32.dll")]
        public static extern int GetWindowLong(IntPtr hWnd, int nIndex);

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

        public const int GWL_EXSTYLE = -20;
        public const int WS_EX_LAYERED = 0x80000;
        public const int LWA_ALPHA = 0x2;
        public const int LWA_COLORKEY = 0x1;

        public static int GWL_STYLE = -16;
        public static int WS_CHILD = 0x40000000;

        public HwndSource hwnd;

        public MainWindow()
        {
            InitializeComponent();
        }

        public static IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, int dwNewLong)
        {
            if (Environment.Is64BitOperatingSystem)
                return new IntPtr(SetWindowLong32(hWnd, nIndex, dwNewLong));
            else
                return SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
        }

        private void Window_ContentRendered(object sender, EventArgs e)
        {
            this.hwnd = PresentationSource.FromVisual(this) as HwndSource;

            if (this.hwnd != null)
            {
                Process hostProcess = Process.GetProcessesByName("POWERPNT").FirstOrDefault();

                if (hostProcess != null)
                {
                    IntPtr hostHandle = hostProcess.MainWindowHandle;
                    IntPtr guestHandle = this.hwnd.Handle;


                    SetParent(guestHandle, hostHandle);

                    SetWindowLongPtr(guestHandle, GWL_STYLE, GetWindowLong(guestHandle, GWL_STYLE) | WS_CHILD);
                }
            }
        }
    }
}

Solution

  • Here it worked like this in a WPF project

    using System;
    using System.Diagnostics;
    using System.Linq;
    using System.Runtime.InteropServices;
    using System.Windows;
    using System.Windows.Interop;
    
    
    public partial class MainWindow : Window
    {
    
    [DllImport("user32.dll", EntryPoint = "SetWindowLong")]
    private static extern int SetWindowLong32(IntPtr hWnd, int nIndex, int dwNewLong);
    
    [DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
    private static extern IntPtr SetWindowLongPtr64(IntPtr hWnd, int nIndex, int dwNewLong);
    
    [DllImport("user32.dll", SetLastError = true)]
    private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
    
    [DllImport("user32.dll", SetLastError = true)]
    private static extern UInt32 GetWindowLong(IntPtr hWnd, int nIndex);
    [DllImport("user32.dll")]
    static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
    [DllImport("user32.dll")]
    static extern bool SetLayeredWindowAttributes(IntPtr hwnd, uint crKey, byte bAlpha, uint dwFlags);
    public const int GWL_EXSTYLE = -20;
    public const int WS_EX_LAYERED = 0x80000;
    public const int WS_EX_TRANSPARENT = 0x20;
    public const int LWA_ALPHA = 0x2;
    public const int LWA_COLORKEY = 0x1;
    
    
    public HwndSource hwnd;
    
    public MainWindow()
    {
        InitializeComponent();
    }
    
    public static IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, int dwNewLong)
    {
        if (Environment.Is64BitOperatingSystem)
            return new IntPtr(SetWindowLong32(hWnd, nIndex, dwNewLong));
        else
            return SetWindowLongPtr64(hWnd, nIndex, dwNewLong);
    }
    
    private void Window_ContentRendered(object sender, EventArgs e)
    {
        this.hwnd = PresentationSource.FromVisual(this) as HwndSource;
    
        if (this.hwnd != null)
        {
            Process hostProcess = Process.GetProcessesByName("WindowsFormsApp5").FirstOrDefault();
    
            if (hostProcess != null)
            {
                IntPtr hostHandle = hostProcess.MainWindowHandle;
                IntPtr guestHandle = this.hwnd.Handle;
    
                SetWindowLong(hostHandle, GWL_EXSTYLE, (IntPtr)(GetWindowLong(hostHandle, GWL_EXSTYLE) ^ WS_EX_LAYERED));
                SetLayeredWindowAttributes(hostHandle, 0, 200, LWA_ALPHA);
                SetParent(guestHandle, hostHandle);
                 
            }
        }
    }
    
    private void Grid_Loaded(object sender, RoutedEventArgs e)
    {
        Window_ContentRendered(sender, e);
    }
    }