123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377 |
- using Newtonsoft.Json.Linq;
- using System;
- using System.Diagnostics;
- using System.Diagnostics.CodeAnalysis;
- using System.Numerics;
- using System.Reflection;
- using System.Runtime.CompilerServices;
- using System.Runtime.InteropServices;
- using System.Text;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Data;
- using System.Windows.Documents;
- using System.Windows.Input;
- using System.Windows.Interop;
- using System.Windows.Media;
- using System.Windows.Media.Imaging;
- using System.Windows.Media.Media3D;
- using System.Windows.Navigation;
- using System.Windows.Shapes;
- namespace Veldrid.Wpf
- {
- public sealed class VeldridContent
- {
- static VeldridContent() { }
- private VeldridContent() { }
- private const string WindowClass = "HwndWrapper";
- public IntPtr Hwnd { get; private set; }
- [AllowNull]
- public Veldrid.Common.VeldridContent Content { get; private set; }
- public static Veldrid.Wpf.VeldridContent CreateContent()
- {
- VeldridContent content = new VeldridContent();
- var wndClass = new NativeMethods.WndClassEx();
- wndClass.cbSize = (uint)Marshal.SizeOf(wndClass);
- wndClass.hInstance = NativeMethods.GetModuleHandle(null);
- wndClass.lpfnWndProc = NativeMethods.DefaultWindowProc;
- wndClass.lpszClassName = WindowClass;
- wndClass.hCursor = NativeMethods.LoadCursor(IntPtr.Zero, NativeMethods.IDC_ARROW);
- NativeMethods.RegisterClassEx(ref wndClass);
- content.Hwnd = NativeMethods.CreateWindowEx(
- 0, WindowClass, "", NativeMethods.WS_VISIBLE,
- 0, 0, 200, 200, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero, 0);
- NativeMethods.ShowWindow(content.Hwnd, 0);
- Module mainModule = typeof(VeldridView).Module;
- IntPtr hinstance = Marshal.GetHINSTANCE(mainModule);
- SwapchainSource win32Source = SwapchainSource.CreateWin32(content.Hwnd, hinstance);
- SwapchainDescription scDesc = new SwapchainDescription(win32Source, 200, 200, PixelFormat.R32_Float, true);
- GraphicsDevice device = GraphicsDevice.CreateD3D11(new GraphicsDeviceOptions(false, null, true, ResourceBindingModel.Default, true, true, true), scDesc);
- content.Content = new Common.VeldridContent(device);
- return content;
- }
- }
- public sealed class VeldridView : HwndHost
- {
- [AllowNull]
- private VeldridContent _Content;
- private IntPtr Hwnd;
- public bool HwndInitialized { get; private set; }
- public VeldridView(VeldridContent content)
- {
- _Content = content;
- Hwnd = _Content.Hwnd;
- base.Loaded += OnLoaded;
- base.Unloaded += OnUnloaded;
- }
- public GraphicsBackend Backend { get; set; } = GraphicsBackend.Direct3D11;
- private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
- {
- Initialize();
- HwndInitialized = true;
- CreateGraphicsDevice();
- }
- private void CreateGraphicsDevice()
- {
- double dpiScale = CompositionScaleX;
- uint width = (uint)(ActualWidth < 0 ? 0 : Math.Ceiling(ActualWidth * dpiScale));
- uint height = (uint)(ActualHeight < 0 ? 0 : Math.Ceiling(ActualHeight * dpiScale));
- width = (uint)ActualWidth;
- height = (uint)ActualHeight;
- NativeMethods.SetWindowLong(Hwnd, -16, 0x40000000L);
- //NativeMethods.SetWindowLong(Hwnd, -20, 0x08000000);
- NativeMethods.SetParent(_Content.Hwnd, parentptr);
- NativeMethods.ShowWindow(Hwnd, 1);
- NativeMethods.SetWindowPos(Hwnd, 0, 0, 0, (int)width, (int)height, 0);
- if (ActualWidth > 0 && ActualHeight > 0)
- {
- _Content.Content.Resize(width,height);
- }
- GraphicsDeviceCreated?.Invoke();
- Thread.Sleep(20);
- }
- private void DestroyGraphicsDevice()
- {
- if (_Content != null)
- {
- GraphicsDeviceDestroyed?.Invoke();
- _Content = null;
- }
- }
- [AllowNull]
- public Action GraphicsDeviceDestroyed;
- [AllowNull]
- public Action GraphicsDeviceCreated;
- private void OnUnloaded(object sender, RoutedEventArgs routedEventArgs)
- {
- Uninitialize();
- HwndInitialized = false;
- DestroyGraphicsDevice();
- Dispose();
- }
- public IntPtr NativeHwnd => this.Hwnd;
- [AllowNull]
- public new Action SizeChanged;
- [AllowNull]
- public new Action Loaded;
- [AllowNull]
- public new Action Unloaded;
- private void Initialize()
- {
- Loaded?.Invoke();
- }
- private void Resized()
- {
- if (_Content != null)
- {
- if (ActualWidth > 0 && ActualHeight > 0)
- {
- _Content.Content.Resize((uint)(ActualWidth * CompositionScaleX), (uint)(ActualHeight * CompositionScaleY));
- }
- }
- SizeChanged?.Invoke();
- }
- public double CompositionScaleX => GetDpiScale();
- public double CompositionScaleY => GetDpiScale();
- private double GetDpiScale()
- {
- PresentationSource source = PresentationSource.FromVisual(this);
- if (source != null)
- return source.CompositionTarget.TransformToDevice.M11;
- else
- return 1;
- }
- private void Uninitialize()
- {
- Unloaded?.Invoke();
- }
- protected override HandleRef BuildWindowCore(HandleRef hwndParent)
- {
- parentptr = hwndParent.Handle;
- NativeMethods.SetWindowLong(Hwnd, -16, 0x40000000L);
- //NativeMethods.SetWindowLong(Hwnd, -20, 0x80000000L);
- NativeMethods.SetParent(_Content.Hwnd, parentptr);
- if (ActualWidth > 0 && ActualHeight > 0)
- {
- _Content.Content.Resize((uint)(ActualWidth*CompositionScaleX), (uint)(ActualHeight*CompositionScaleY));
- }
- NativeMethods.ShowWindow(Hwnd, 1);
- return new HandleRef(this, Hwnd);
- }
- private IntPtr parentptr;
- protected override void DestroyWindowCore(HandleRef hwnd)
- {
- NativeMethods.ShowWindow(Hwnd, 0);
- var result = NativeMethods.GetWindowLong(Hwnd, -16);
- result &= ~0x40000000L;
- NativeMethods.SetWindowLong(Hwnd, -16, result);
- NativeMethods.SetParent(Hwnd, IntPtr.Zero);
- Hwnd = IntPtr.Zero;
- _Content = null;
- }
- protected unsafe override IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
- {
- if (_Content != null)
- {
- tagRECT rect = new tagRECT();
- GetWindowRect(hwnd, ref rect);
- switch (msg)
- {
- case NativeMethods.WM_LBUTTONDOWN:
- _Content.Content.WindowScale = new Vector2((float)ActualWidth / (rect.right - rect.left), (float)ActualHeight / (rect.bottom - rect.top));
- int val = (int)lParam.ToInt64();
- _Content.Content.MouseLeftDown(Unsafe.As<int, Veldrid.Common.MousePositon>(ref val));
- break;
- case NativeMethods.WM_LBUTTONUP:
- _Content.Content.WindowScale = new Vector2((float)ActualWidth / (rect.right - rect.left), (float)ActualHeight / (rect.bottom - rect.top));
- val = (int)lParam.ToInt64();
- _Content.Content.MouseLeftUp(Unsafe.As<int, Veldrid.Common.MousePositon>(ref val));
- break;
- case NativeMethods.WM_RBUTTONDOWN:
- _Content.Content.WindowScale = new Vector2((float)ActualWidth / (rect.right - rect.left), (float)ActualHeight / (rect.bottom - rect.top));
- val = (int)lParam.ToInt64();
- _Content.Content.MouseRightDown(Unsafe.As<int, Veldrid.Common.MousePositon>(ref val));
- break;
- case NativeMethods.WM_RBUTTONUP:
- _Content.Content.WindowScale = new Vector2((float)ActualWidth / (rect.right - rect.left), (float)ActualHeight / (rect.bottom - rect.top));
- val = (int)lParam.ToInt64();
- _Content.Content.MouseRightUp(Unsafe.As<int, Veldrid.Common.MousePositon>(ref val));
- break;
- case NativeMethods.WM_MBUTTONDOWN:
- _Content.Content.WindowScale = new Vector2((float)ActualWidth / (rect.right - rect.left), (float)ActualHeight / (rect.bottom - rect.top));
- val = (int)lParam.ToInt64();
- _Content.Content.MouseMiddleDown(Unsafe.As<int, Veldrid.Common.MousePositon>(ref val) );
- break;
- case NativeMethods.WM_MBUTTONUP:
- _Content.Content.WindowScale = new Vector2((float)ActualWidth / (rect.right - rect.left), (float)ActualHeight / (rect.bottom - rect.top));
- val = (int)lParam.ToInt64();
- _Content.Content.MouseMiddleUp(Unsafe.As<int, Veldrid.Common.MousePositon>(ref val) );
- break;
- case NativeMethods.WM_MOUSEMOVE:
- _Content.Content.WindowScale = new Vector2((float)ActualWidth / (rect.right - rect.left), (float)ActualHeight / (rect.bottom - rect.top));
- val = (int)lParam.ToInt64();
- _Content.Content.MouseMove(Unsafe.As<int, Veldrid.Common.MousePositon>(ref val));
- break;
- case NativeMethods.WM_MOUSEWHEEL:
- _Content.Content.WindowScale = new Vector2((float)ActualWidth / (rect.right - rect.left), (float)ActualHeight / (rect.bottom - rect.top));
- val = (int)lParam.ToInt64();
- _Content.Content.MouseWheel(Unsafe.As<int, Veldrid.Common.MousePositon>(ref val) , (((Int32)wParam.ToInt64()) >> 16) / Mouse.MouseWheelDeltaForOneLine);
- break;
- case NativeMethods.WM_MOUSELEAVE:
- _Content.Content.MouseLeave();
- break;
- }
- }
- return base.WndProc(hwnd, msg, wParam, lParam, ref handled);
- }
- [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]
- private struct tagRECT
- {
- /// LONG->int
- public int left;
- /// LONG->int
- public int top;
- /// LONG->int
- public int right;
- /// LONG->int
- public int bottom;
- }
- [System.Runtime.InteropServices.DllImportAttribute("user32.dll", EntryPoint = "GetWindowRect")]
- [return: System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)]
- private static extern bool GetWindowRect(System.IntPtr hWnd, ref tagRECT lpRect);
- [StructLayout(LayoutKind.Sequential)]
- private struct MSLLHOOKSTRUCT
- {
- public Point pt;
- public int mouseData;
- public int flags;
- public int time;
- public long dwExtraInfo;
- }
- private void RaiseMouseEvent(System.Windows.Input.MouseButton button, RoutedEvent @event)
- {
- RaiseEvent(new MouseButtonEventArgs(Mouse.PrimaryDevice, (int)DateTime.Now.Ticks, button)
- {
- RoutedEvent = @event,
- Source = this,
- });
- }
- protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
- {
- UpdateWindowPos();
- base.OnRenderSizeChanged(sizeInfo);
- if (HwndInitialized)
- Resized();
- }
- }
- internal class NativeMethods
- {
- // ReSharper disable InconsistentNaming
- public const int WS_CHILD = 0x40000000;
- public const int WS_VISIBLE = 0x10000000;
- public const int WM_PAINT = 0x0f;
- public const int WM_LBUTTONDOWN = 0x0201;
- public const int WM_LBUTTONUP = 0x0202;
- public const int WM_RBUTTONDOWN = 0x0204;
- public const int WM_RBUTTONUP = 0x0205;
- public const int WM_NCCALCSIZE = 0x0083;
- public const int WM_MOUSEWHEEL = 0x020A;
- public const int WM_MBUTTONDOWN = 0x0207;
- public const int WM_MBUTTONUP = 0x0208;
- public const int WM_MOUSEMOVE = 0x0200;
- public const int WM_MOUSELEAVE = 0x02A3;
- public const int IDC_ARROW = 32512;
- [StructLayout(LayoutKind.Sequential)]
- public struct WndClassEx
- {
- public uint cbSize;
- public uint style;
- [MarshalAs(UnmanagedType.FunctionPtr)]
- public WndProc lpfnWndProc;
- public int cbClsExtra;
- public int cbWndExtra;
- public IntPtr hInstance;
- public IntPtr hIcon;
- public IntPtr hCursor;
- public IntPtr hbrBackground;
- public string lpszMenuName;
- public string lpszClassName;
- public IntPtr hIconSm;
- }
- [DllImport("user32.dll")]
- public static extern IntPtr DefWindowProc(IntPtr hWnd, uint uMsg, IntPtr wParam, IntPtr lParam);
- public delegate IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
- public static readonly WndProc DefaultWindowProc = DefWindowProc;
- [DllImport("user32.dll", EntryPoint = "CreateWindowEx", CharSet = CharSet.Auto)]
- public static extern IntPtr CreateWindowEx(
- int exStyle,
- string className,
- string windowName,
- int style,
- int x, int y,
- int width, int height,
- IntPtr hwndParent,
- IntPtr hMenu,
- IntPtr hInstance,
- [MarshalAs(UnmanagedType.AsAny)] object pvParam);
- [DllImport("user32.dll", EntryPoint = "DestroyWindow", CharSet = CharSet.Auto)]
- public static extern bool DestroyWindow(IntPtr hwnd);
- [DllImport("kernel32.dll")]
- public static extern IntPtr GetModuleHandle(string module);
- [DllImport("user32.dll")]
- [return: MarshalAs(UnmanagedType.U2)]
- public static extern short RegisterClassEx([In] ref WndClassEx lpwcx);
- [DllImport("user32.dll")]
- public static extern IntPtr LoadCursor(IntPtr hInstance, int lpCursorName);
- [System.Runtime.InteropServices.DllImportAttribute("user32.dll", EntryPoint = "SetParent")]
- public static extern System.IntPtr SetParent(System.IntPtr hWndChild, System.IntPtr hWndNewParent);
- [System.Runtime.InteropServices.DllImportAttribute("user32.dll", EntryPoint = "ShowWindow")]
- [return: System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)]
- public static extern bool ShowWindow(System.IntPtr hWnd, int nCmdShow);
- [System.Runtime.InteropServices.DllImportAttribute("user32.dll", EntryPoint = "SetWindowPos")]
- [return: System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.Bool)]
- public static extern bool SetWindowPos(System.IntPtr hWnd, System.IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, int uFlags);
- [System.Runtime.InteropServices.DllImportAttribute("user32.dll", EntryPoint = "SetWindowLong")]
- public static extern long SetWindowLong(System.IntPtr hWnd, int nIndex, long dwNewLong);
- [System.Runtime.InteropServices.DllImportAttribute("user32.dll", EntryPoint = "GetWindowLong")]
- public static extern long GetWindowLong(System.IntPtr hWnd, int nIndex);
- }
- }
|