DirectX renderer .net6 port in WPF

Sahil Agnihotri 21 Reputation points
2022-02-07T14:02:09.22+00:00

Hi,

I am porting a directx renderer to .net6 from .net framework 4.8. Previously we could use D3DImage and draw to that in a wpf window. Now since its missing, i manage to draw using the window handle but now problem comes are GUI buttons, it draws on whole screen since parent window handle and handle for control are same. In winforms for example if i use splitview and render on right side, window handle of left and right is different and i can render there without issues. I also tried making a separate child window in wpf and then it works fine since the handle is different but having gui in one window and rendering in another is not really a good solution.

Is there a way to make child window inside main window in wpf in .net6 ?? or any other way to tackle this problem ?

Any help or tips will be appreciated. Thanks!

Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,781 questions
XAML
XAML
A language based on Extensible Markup Language (XML) that enables developers to specify a hierarchy of objects with a set of properties and logic.
812 questions
{count} votes

Accepted answer
  1. Castorix31 85,546 Reputation points
    2022-02-08T17:19:58.327+00:00

    From comments, the test I added in your WPF sample in MainWindow.xaml.cs
    I added a Subclassing of the Static control to test events (Beep on Double-click)
    =>

            private IntPtr hWndContainer = IntPtr.Zero;
            private SUBCLASSPROC SubClassDelegate;
    
            protected override void OnSourceInitialized(EventArgs e)
            {
                base.OnSourceInitialized(e);
                HwndSource? hWndSource = PresentationSource.FromVisual(this) as HwndSource;
                var nWidth = ((Panel)Application.Current.MainWindow.Content).ActualWidth;
                var nHeight = ((Panel)Application.Current.MainWindow.Content).ActualHeight;
                hWndContainer = CreateWindowEx(0, "Static", "", WS_VISIBLE | WS_CHILD | WS_BORDER | SS_NOTIFY, 120, 10, (int)nWidth - 120 - 10, (int)nHeight - 10 * 2, hWndSource.Handle, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
                // comment "handle = childWindowInterOp.Handle;" in MainWindow_Loaded
                // "this.SizeChanged += MainWindow_SizeChanged;" could also be commented or MoveWindow added in MainWindow_SizeChanged
                if (hWndContainer != IntPtr.Zero)
                {
                    handle = hWndContainer;
                    SubClassDelegate = new SUBCLASSPROC(WindowSubClass);
                    bool bRet = SetWindowSubclass(hWndContainer, SubClassDelegate, 0, 0);
                }
                hWndSource.AddHook(WndProc);
            }
    
            private int nX = 110, nY = 0;
            private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
            {
                if (msg == WM_SIZE)
                {
                    if (hWndContainer != IntPtr.Zero)
                        MoveWindow(hWndContainer, nX, nY, LOWORD((int)lParam) - nX, HIWORD((int)lParam), true);
                }
                return IntPtr.Zero;
            }
    
            private int WindowSubClass(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam, IntPtr uIdSubclass, uint dwRefData)
            {
                switch (uMsg)
                {
                    case WM_LBUTTONDBLCLK:
                        {
                            Console.Beep(6000, 10);
                            return 0;
                        }
                        break;              
                }
                return DefSubclassProc(hWnd, uMsg, wParam, lParam);
            }
    

    Declarations :

        public const int WS_OVERLAPPED = 0x0;
        public const int WS_BORDER = 0x00800000;
        public const int WS_POPUP = unchecked((int)0x80000000L);
        public const int WS_CHILD = 0x40000000;
        public const int WS_MINIMIZE = 0x20000000;
        public const int WS_VISIBLE = 0x10000000;
        public const int WS_DISABLED = 0x8000000;
    
        public const int SS_NOTIFY = 0x00000100;
    
        [DllImport("User32.dll", SetLastError = true)]
        public static extern IntPtr CreateWindowEx(int dwExStyle, string lpClassName, string lpWindowName, int dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, IntPtr lpParam);
    
        [DllImport("User32.dll", SetLastError = true)]
        public static extern bool MoveWindow(IntPtr hWnd, int x, int y, int cx, int cy, bool repaint);
    
        public static int HIWORD(int n)
        {
            return (n >> 16) & 0xffff;
        }
        public static int LOWORD(int n)
        {
            return n & 0xffff;
        }
    
        public delegate int SUBCLASSPROC(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam, IntPtr uIdSubclass, uint dwRefData);
    
        [DllImport("Comctl32.dll", SetLastError = true)]
        public static extern bool SetWindowSubclass(IntPtr hWnd, SUBCLASSPROC pfnSubclass, uint uIdSubclass, uint dwRefData);
    
        [DllImport("Comctl32.dll", SetLastError = true)]
        public static extern int DefSubclassProc(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam);
    
        public const int WM_SIZE = 0x0005;
        public const int WM_LBUTTONDBLCLK = 0x0203;
        public const int WM_LBUTTONDOWN = 0x0201;
        public const int WM_LBUTTONUP = 0x0202;  
    

0 additional answers

Sort by: Most helpful

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.