csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
206 lines
7.0 KiB
206 lines
7.0 KiB
// -----------------------------------------------------------------------
|
|
// <copyright file="Window.cs" company="Steven Kirk">
|
|
// Copyright 2014 MIT Licence. See licence.md for more information.
|
|
// </copyright>
|
|
// -----------------------------------------------------------------------
|
|
|
|
namespace Perspex.Windows
|
|
{
|
|
using System;
|
|
using System.ComponentModel;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using Perspex.Controls;
|
|
using Perspex.Input;
|
|
using Perspex.Input.Raw;
|
|
using Perspex.Layout;
|
|
using Perspex.Windows.Input;
|
|
using Perspex.Windows.Interop;
|
|
using Perspex.Windows.Threading;
|
|
using Splat;
|
|
|
|
public class Window : ContentControl, ILayoutRoot
|
|
{
|
|
public static readonly PerspexProperty<double> FontSizeProperty =
|
|
TextBlock.FontSizeProperty.AddOwner<Window>();
|
|
|
|
private static readonly IInputDevice MouseDevice = new MouseDevice();
|
|
|
|
private UnmanagedMethods.WndProc wndProcDelegate;
|
|
|
|
private string className;
|
|
|
|
private Renderer renderer;
|
|
|
|
private IInputManager inputManager;
|
|
|
|
static Window()
|
|
{
|
|
FontSizeProperty.OverrideDefaultValue(typeof(Window), 18.0);
|
|
}
|
|
|
|
public Window()
|
|
{
|
|
this.CreateWindow();
|
|
Size clientSize = this.ClientSize;
|
|
this.LayoutManager = new LayoutManager();
|
|
this.renderer = new Renderer(this.Handle, (int)clientSize.Width, (int)clientSize.Height);
|
|
this.inputManager = Locator.Current.GetService<IInputManager>();
|
|
this.Template = ControlTemplate.Create<Window>(this.DefaultTemplate);
|
|
|
|
this.LayoutManager.LayoutNeeded.Subscribe(x =>
|
|
{
|
|
Dispatcher.CurrentDispatcher.BeginInvoke(
|
|
DispatcherPriority.Render,
|
|
() =>
|
|
{
|
|
this.LayoutManager.ExecuteLayoutPass();
|
|
this.renderer.Render(this);
|
|
});
|
|
});
|
|
}
|
|
|
|
public Size ClientSize
|
|
{
|
|
get
|
|
{
|
|
UnmanagedMethods.RECT rect;
|
|
UnmanagedMethods.GetClientRect(this.Handle, out rect);
|
|
return new Size(rect.right, rect.bottom);
|
|
}
|
|
}
|
|
|
|
public IntPtr Handle
|
|
{
|
|
get;
|
|
private set;
|
|
}
|
|
|
|
public ILayoutManager LayoutManager
|
|
{
|
|
get;
|
|
private set;
|
|
}
|
|
|
|
public void Show()
|
|
{
|
|
UnmanagedMethods.ShowWindow(this.Handle, 4);
|
|
}
|
|
|
|
private Control DefaultTemplate(Window c)
|
|
{
|
|
Border border = new Border();
|
|
border.Background = new Perspex.Media.SolidColorBrush(0xffffffff);
|
|
ContentPresenter contentPresenter = new ContentPresenter();
|
|
contentPresenter.Bind(
|
|
ContentPresenter.ContentProperty,
|
|
this.GetObservable(Window.ContentProperty),
|
|
BindingPriority.Style);
|
|
border.Content = contentPresenter;
|
|
return border;
|
|
}
|
|
|
|
private void CreateWindow()
|
|
{
|
|
// Ensure that the delegate doesn't get garbage collected by storing it as a field.
|
|
this.wndProcDelegate = new UnmanagedMethods.WndProc(this.WndProc);
|
|
|
|
this.className = Guid.NewGuid().ToString();
|
|
|
|
UnmanagedMethods.WNDCLASSEX wndClassEx = new UnmanagedMethods.WNDCLASSEX
|
|
{
|
|
cbSize = Marshal.SizeOf(typeof(UnmanagedMethods.WNDCLASSEX)),
|
|
style = 0,
|
|
lpfnWndProc = this.wndProcDelegate,
|
|
hInstance = Marshal.GetHINSTANCE(this.GetType().Module),
|
|
hCursor = UnmanagedMethods.LoadCursor(IntPtr.Zero, (int)UnmanagedMethods.Cursor.IDC_ARROW),
|
|
hbrBackground = (IntPtr)5,
|
|
lpszClassName = this.className,
|
|
};
|
|
|
|
ushort atom = UnmanagedMethods.RegisterClassEx(ref wndClassEx);
|
|
|
|
if (atom == 0)
|
|
{
|
|
throw new Win32Exception();
|
|
}
|
|
|
|
this.Handle = UnmanagedMethods.CreateWindowEx(
|
|
0,
|
|
atom,
|
|
null,
|
|
(int)UnmanagedMethods.WindowStyles.WS_OVERLAPPEDWINDOW,
|
|
UnmanagedMethods.CW_USEDEFAULT,
|
|
UnmanagedMethods.CW_USEDEFAULT,
|
|
UnmanagedMethods.CW_USEDEFAULT,
|
|
UnmanagedMethods.CW_USEDEFAULT,
|
|
IntPtr.Zero,
|
|
IntPtr.Zero,
|
|
IntPtr.Zero,
|
|
IntPtr.Zero);
|
|
|
|
if (this.Handle == IntPtr.Zero)
|
|
{
|
|
throw new Win32Exception();
|
|
}
|
|
}
|
|
|
|
[SuppressMessage("Microsoft.StyleCop.CSharp.NamingRules", "SA1305:FieldNamesMustNotUseHungarianNotation", Justification = "Using Win32 naming for consistency.")]
|
|
private IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
|
|
{
|
|
RawInputEventArgs e = null;
|
|
|
|
switch ((UnmanagedMethods.WindowsMessage)msg)
|
|
{
|
|
////case UnmanagedMethods.WindowsMessage.WM_DESTROY:
|
|
//// this.OnClosed();
|
|
//// break;
|
|
|
|
////case UnmanagedMethods.WindowsMessage.WM_KEYDOWN:
|
|
//// InputManager.Current.ProcessInput(
|
|
//// new RawKeyEventArgs(
|
|
//// keyboard,
|
|
//// RawKeyEventType.KeyDown,
|
|
//// KeyInterop.KeyFromVirtualKey((int)wParam)));
|
|
//// break;
|
|
|
|
case UnmanagedMethods.WindowsMessage.WM_LBUTTONDOWN:
|
|
e = new RawMouseEventArgs(
|
|
MouseDevice,
|
|
this,
|
|
RawMouseEventType.LeftButtonDown,
|
|
new Point((uint)lParam & 0xffff, (uint)lParam >> 16));
|
|
break;
|
|
|
|
case UnmanagedMethods.WindowsMessage.WM_LBUTTONUP:
|
|
e = new RawMouseEventArgs(
|
|
MouseDevice,
|
|
this,
|
|
RawMouseEventType.LeftButtonUp,
|
|
new Point((uint)lParam & 0xffff, (uint)lParam >> 16));
|
|
break;
|
|
|
|
case UnmanagedMethods.WindowsMessage.WM_MOUSEMOVE:
|
|
e = new RawMouseEventArgs(
|
|
MouseDevice,
|
|
this,
|
|
RawMouseEventType.Move,
|
|
new Point((uint)lParam & 0xffff, (uint)lParam >> 16));
|
|
break;
|
|
|
|
case UnmanagedMethods.WindowsMessage.WM_SIZE:
|
|
this.renderer.Resize((int)lParam & 0xffff, (int)lParam >> 16);
|
|
this.InvalidateMeasure();
|
|
return IntPtr.Zero;
|
|
}
|
|
|
|
if (e != null)
|
|
{
|
|
this.inputManager.Process(e);
|
|
}
|
|
|
|
return UnmanagedMethods.DefWindowProc(hWnd, msg, wParam, lParam);
|
|
}
|
|
}
|
|
}
|
|
|