From 25bfda176baadbdf5c5740e457614b0f0d252aea Mon Sep 17 00:00:00 2001 From: Aigio Liu Date: Mon, 11 Jul 2022 00:46:29 +0800 Subject: [PATCH] Fix DPI, Extra white windows --- .../Avalonia.WebView2.Sample.csproj | 4 - .../BCL/MS/Internal/PresentationCore/SR.cs | 19 ++ .../BCL/MS/Internal/PresentationCore/SRID.cs | 13 + .../BCL/MS/Win32/ExternDll.cs | 57 ++++ .../BCL/MS/Win32/UnsafeNativeMethodsCLR.cs | 21 ++ .../BCL/System/Windows/MessageBox.cs | 248 ++++++++++++++++++ .../MainWindow.xaml.cs | 4 +- src/Avalonia.WebView2.Sample/Program.cs | 38 ++- .../Properties/app.manifest | 83 +----- .../Avalonia.WebView2.csproj | 2 +- .../Avalonia/Input/WebView2KeyEventArgs.cs | 0 .../BCL/MS/Win32/NativeMethods.cs | 64 +++++ .../MS/Win32/NativeMethodsCLR.cs | 0 .../MS/Win32/NativeMethodsOther.cs | 0 .../System/ConvertibleHelper.cs | 0 .../System/OperatingSystemCompat.cs | 0 .../Runtime/Versioning/PlatformAttributes.cs | 0 .../System/Windows/Input/KeyInterop.cs | 0 .../System/Windows/Interop/IHwndHost.cs | 0 .../CefNet/Avalonia/Internal/GlobalHooks.cs | 0 .../Avalonia/Internal/WindowsHwndSource.cs | 0 .../CefNet/Avalonia/WinApi/NativeMethods.cs | 0 src/Avalonia.WebView2/WebView2.cs | 122 ++------- .../MS/Win32/NativeMethods.cs | 60 ----- 24 files changed, 486 insertions(+), 249 deletions(-) create mode 100644 src/Avalonia.WebView2.Sample/BCL/MS/Internal/PresentationCore/SR.cs create mode 100644 src/Avalonia.WebView2.Sample/BCL/MS/Internal/PresentationCore/SRID.cs create mode 100644 src/Avalonia.WebView2.Sample/BCL/MS/Win32/ExternDll.cs create mode 100644 src/Avalonia.WebView2.Sample/BCL/MS/Win32/UnsafeNativeMethodsCLR.cs create mode 100644 src/Avalonia.WebView2.Sample/BCL/System/Windows/MessageBox.cs rename src/Avalonia.WebView2/{_SourceCodeReference => }/Avalonia/Input/WebView2KeyEventArgs.cs (100%) create mode 100644 src/Avalonia.WebView2/BCL/MS/Win32/NativeMethods.cs rename src/Avalonia.WebView2/{_SourceCodeReference => BCL}/MS/Win32/NativeMethodsCLR.cs (100%) rename src/Avalonia.WebView2/{_SourceCodeReference => BCL}/MS/Win32/NativeMethodsOther.cs (100%) rename src/Avalonia.WebView2/{_SourceCodeReference => BCL}/System/ConvertibleHelper.cs (100%) rename src/Avalonia.WebView2/{_SourceCodeReference => BCL}/System/OperatingSystemCompat.cs (100%) rename src/Avalonia.WebView2/{_SourceCodeReference => BCL}/System/Runtime/Versioning/PlatformAttributes.cs (100%) rename src/Avalonia.WebView2/{_SourceCodeReference => BCL}/System/Windows/Input/KeyInterop.cs (100%) rename src/Avalonia.WebView2/{_SourceCodeReference => BCL}/System/Windows/Interop/IHwndHost.cs (100%) rename src/Avalonia.WebView2/{_SourceCodeReference => }/CefNet/Avalonia/Internal/GlobalHooks.cs (100%) rename src/Avalonia.WebView2/{_SourceCodeReference => }/CefNet/Avalonia/Internal/WindowsHwndSource.cs (100%) rename src/Avalonia.WebView2/{_SourceCodeReference => }/CefNet/Avalonia/WinApi/NativeMethods.cs (100%) delete mode 100644 src/Avalonia.WebView2/_SourceCodeReference/MS/Win32/NativeMethods.cs diff --git a/src/Avalonia.WebView2.Sample/Avalonia.WebView2.Sample.csproj b/src/Avalonia.WebView2.Sample/Avalonia.WebView2.Sample.csproj index 37e6a73..62103b8 100644 --- a/src/Avalonia.WebView2.Sample/Avalonia.WebView2.Sample.csproj +++ b/src/Avalonia.WebView2.Sample/Avalonia.WebView2.Sample.csproj @@ -10,10 +10,6 @@ - - - - Properties\AssemblyInfo.OS.cs diff --git a/src/Avalonia.WebView2.Sample/BCL/MS/Internal/PresentationCore/SR.cs b/src/Avalonia.WebView2.Sample/BCL/MS/Internal/PresentationCore/SR.cs new file mode 100644 index 0000000..3ccd23e --- /dev/null +++ b/src/Avalonia.WebView2.Sample/BCL/MS/Internal/PresentationCore/SR.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// https://github.com/dotnet/wpf/blob/v6.0.6/src/Microsoft.DotNet.Wpf/src/PresentationCore/SR.cs + +#if !NETFRAMEWORK && WINDOWS + +namespace MS.Internal.PresentationCore; + +internal static class SR +{ + public static string Get(string name) => name switch + { + SRID.CantShowMBServiceWithOwner => "Cannot show MessageBox Service with Owner.", + _ => "", + }; +} + +#endif \ No newline at end of file diff --git a/src/Avalonia.WebView2.Sample/BCL/MS/Internal/PresentationCore/SRID.cs b/src/Avalonia.WebView2.Sample/BCL/MS/Internal/PresentationCore/SRID.cs new file mode 100644 index 0000000..15a5c6e --- /dev/null +++ b/src/Avalonia.WebView2.Sample/BCL/MS/Internal/PresentationCore/SRID.cs @@ -0,0 +1,13 @@ +#if !NETFRAMEWORK && WINDOWS + +namespace MS.Internal.PresentationCore; + +static class SRID +{ + /// + /// https://github.com/dotnet/wpf/blob/v6.0.6/src/Microsoft.DotNet.Wpf/src/PresentationFramework/Resources/Strings.resx#L510 + /// + public const string CantShowMBServiceWithOwner = "CantShowMBServiceWithOwner"; +} + +#endif \ No newline at end of file diff --git a/src/Avalonia.WebView2.Sample/BCL/MS/Win32/ExternDll.cs b/src/Avalonia.WebView2.Sample/BCL/MS/Win32/ExternDll.cs new file mode 100644 index 0000000..5d7be7c --- /dev/null +++ b/src/Avalonia.WebView2.Sample/BCL/MS/Win32/ExternDll.cs @@ -0,0 +1,57 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// https://github.com/dotnet/wpf/blob/v6.0.6/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/ExternDll.cs + +#if !NETFRAMEWORK && WINDOWS + +namespace MS.Win32; + +internal static class ExternDll +{ + //public const string Activeds = "activeds.dll"; + //public const string Advapi32 = "advapi32.dll"; + //public const string Comctl32 = "comctl32.dll"; + //public const string Comdlg32 = "comdlg32.dll"; + //public const string DwmAPI = "dwmapi.dll"; + //public const string Gdi32 = "gdi32.dll"; + //public const string Gdiplus = "gdiplus.dll"; + //public const string Hhctrl = "hhctrl.ocx"; + //public const string Imm32 = "imm32.dll"; + //public const string Kernel32 = "kernel32.dll"; + //public const string Loadperf = "Loadperf.dll"; + //public const string Mqrt = "mqrt.dll"; + //public const string Mscoree = "mscoree.dll"; + //public const string MsDrm = "msdrm.dll"; + //public const string Mshwgst = "mshwgst.dll"; + //public const string Msi = "msi.dll"; + //public const string NaturalLanguage6 = "naturallanguage6.dll"; + //public const string Ntdll = "ntdll.dll"; + //public const string Ole32 = "ole32.dll"; + //public const string Oleacc = "oleacc.dll"; + //public const string Oleaut32 = "oleaut32.dll"; + //public const string Olepro32 = "olepro32.dll"; + //public const string Penimc = "PenIMC_cor3.dll"; + //public const string PresentationCore = "PresentationCore.dll"; + //public const string PresentationFramework = "PresentationFramework.dll"; + //public const string PresentationHostDll = "PresentationHost_cor3.dll"; + //public const string PresentationNativeDll = "PresentationNative_cor3.dll"; + //public const string Psapi = "psapi.dll"; + //public const string Shcore = "shcore.dll"; + //public const string Shell32 = "shell32.dll"; + //public const string Shfolder = "shfolder.dll"; + //public const string Urlmon = "urlmon.dll"; + public const string User32 = "user32.dll"; + //public const string Uxtheme = "uxtheme.dll"; + //public const string Version = "version.dll"; + //public const string Vsassert = "vsassert.dll"; + //public const string WindowsBase = "windowsbase.dll"; + //public const string Wininet = "wininet.dll"; + //public const string Winmm = "winmm.dll"; + //public const string Winspool = "winspool.drv"; + //public const string Wldp = "wldp.dll"; + //public const string WpfGfx = "WpfGfx_cor3.dll"; + //public const string WtsApi32 = "wtsapi32.dll"; +} + +#endif \ No newline at end of file diff --git a/src/Avalonia.WebView2.Sample/BCL/MS/Win32/UnsafeNativeMethodsCLR.cs b/src/Avalonia.WebView2.Sample/BCL/MS/Win32/UnsafeNativeMethodsCLR.cs new file mode 100644 index 0000000..50a5b92 --- /dev/null +++ b/src/Avalonia.WebView2.Sample/BCL/MS/Win32/UnsafeNativeMethodsCLR.cs @@ -0,0 +1,21 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// https://github.com/dotnet/wpf/blob/v6.0.6/src/Microsoft.DotNet.Wpf/src/Shared/MS/Win32/UnsafeNativeMethodsCLR.cs + +#if !NETFRAMEWORK && WINDOWS + +using System.Runtime.InteropServices; + +namespace MS.Win32; + +internal static class UnsafeNativeMethods +{ + [DllImport(ExternDll.User32, ExactSpelling = true, CharSet = CharSet.Auto)] + public static extern IntPtr GetActiveWindow(); + + [DllImport(ExternDll.User32, SetLastError = true, CharSet = CharSet.Auto, BestFitMapping = false)] + public static extern int MessageBox(HandleRef hWnd, string text, string caption, int type); +} + +#endif \ No newline at end of file diff --git a/src/Avalonia.WebView2.Sample/BCL/System/Windows/MessageBox.cs b/src/Avalonia.WebView2.Sample/BCL/System/Windows/MessageBox.cs new file mode 100644 index 0000000..ff10411 --- /dev/null +++ b/src/Avalonia.WebView2.Sample/BCL/System/Windows/MessageBox.cs @@ -0,0 +1,248 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. +// https://github.com/dotnet/wpf/blob/v6.0.6/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/MessageBox.cs + +#if !NETFRAMEWORK && WINDOWS + +using MS.Win32; +using System.ComponentModel; +using System.Runtime.InteropServices; +using SR_ = MS.Internal.PresentationCore.SR; +using SRID = MS.Internal.PresentationCore.SRID; + +namespace System.Windows; + +public static class MessageBox +{ + const int IDOK = 1; + const int IDCANCEL = 2; + const int IDYES = 6; + const int IDNO = 7; + const int DEFAULT_BUTTON1 = 0x00000000; + const int DEFAULT_BUTTON2 = 0x00000100; + const int DEFAULT_BUTTON3 = 0x00000200; + + static MessageBoxResult Win32ToMessageBoxResult(int value) => value switch + { + IDOK => MessageBoxResult.OK, + IDCANCEL => MessageBoxResult.Cancel, + IDYES => MessageBoxResult.Yes, + IDNO => MessageBoxResult.No, + _ => MessageBoxResult.No, + }; + + public static MessageBoxResult Show( + string messageBoxText, + string caption, + MessageBoxButton button, + MessageBoxImage icon, + MessageBoxResult defaultResult, + MessageBoxOptions options) => ShowCore(IntPtr.Zero, messageBoxText, caption, button, icon, defaultResult, options); + + public static MessageBoxResult Show( + string messageBoxText, + string caption, + MessageBoxButton button, + MessageBoxImage icon, + MessageBoxResult defaultResult) => ShowCore(IntPtr.Zero, messageBoxText, caption, button, icon, defaultResult, 0); + + public static MessageBoxResult Show( + string messageBoxText, + string caption, + MessageBoxButton button, + MessageBoxImage icon) => ShowCore(IntPtr.Zero, messageBoxText, caption, button, icon, 0, 0); + + public static MessageBoxResult Show( + string messageBoxText, + string caption, + MessageBoxButton button) => ShowCore(IntPtr.Zero, messageBoxText, caption, button, MessageBoxImage.None, 0, 0); + + public static MessageBoxResult Show(string messageBoxText, string caption) => ShowCore(IntPtr.Zero, messageBoxText, caption, MessageBoxButton.OK, MessageBoxImage.None, 0, 0); + + public static MessageBoxResult Show(string messageBoxText) => ShowCore(IntPtr.Zero, messageBoxText, string.Empty, MessageBoxButton.OK, MessageBoxImage.None, 0, 0); + + static int DefaultResultToButtonNumber(MessageBoxResult result, MessageBoxButton button) + { + if (result == 0) return DEFAULT_BUTTON1; + + switch (button) + { + case MessageBoxButton.OK: + return DEFAULT_BUTTON1; + case MessageBoxButton.OKCancel: + if (result == MessageBoxResult.Cancel) return DEFAULT_BUTTON2; + return DEFAULT_BUTTON1; + case MessageBoxButton.YesNo: + if (result == MessageBoxResult.No) return DEFAULT_BUTTON2; + return DEFAULT_BUTTON1; + case MessageBoxButton.YesNoCancel: + if (result == MessageBoxResult.No) return DEFAULT_BUTTON2; + if (result == MessageBoxResult.Cancel) return DEFAULT_BUTTON3; + return DEFAULT_BUTTON1; + default: + return DEFAULT_BUTTON1; + } + } + + internal static MessageBoxResult ShowCore( + IntPtr owner, + string messageBoxText, + string caption, + MessageBoxButton button, + MessageBoxImage icon, + MessageBoxResult defaultResult, + MessageBoxOptions options) + { + if (!IsValidMessageBoxButton(button)) + { + throw new InvalidEnumArgumentException("button", (int)button, typeof(MessageBoxButton)); + } + if (!IsValidMessageBoxImage(icon)) + { + throw new InvalidEnumArgumentException("icon", (int)icon, typeof(MessageBoxImage)); + } + if (!IsValidMessageBoxResult(defaultResult)) + { + throw new InvalidEnumArgumentException("defaultResult", (int)defaultResult, typeof(MessageBoxResult)); + } + if (!IsValidMessageBoxOptions(options)) + { + throw new InvalidEnumArgumentException("options", (int)options, typeof(MessageBoxOptions)); + } + + // UserInteractive?? + // + /*if (!SystemInformation.UserInteractive && (options & (MessageBoxOptions.ServiceNotification | MessageBoxOptions.DefaultDesktopOnly)) == 0) { + throw new InvalidOperationException("UNDONE: SR.GetString(SR.CantShowModalOnNonInteractive)"); + }*/ + + if ((options & (MessageBoxOptions.ServiceNotification | MessageBoxOptions.DefaultDesktopOnly)) != 0) + { + if (owner != IntPtr.Zero) + { + throw new ArgumentException(SR_.Get(SRID.CantShowMBServiceWithOwner)); + } + } + else + { + if (owner == IntPtr.Zero) + { + owner = UnsafeNativeMethods.GetActiveWindow(); + } + } + + int style = (int)button | (int)icon | (int)DefaultResultToButtonNumber(defaultResult, button) | (int)options; + + // modal dialog notification? + // + //Application.BeginModalMessageLoop(); + //MessageBoxResult result = Win32ToMessageBoxResult(SafeNativeMethods.MessageBox(new HandleRef(owner, handle), messageBoxText, caption, style)); + MessageBoxResult result = Win32ToMessageBoxResult(UnsafeNativeMethods.MessageBox(new HandleRef(null, owner), messageBoxText, caption, style)); + // modal dialog notification? + // + //Application.EndModalMessageLoop(); + + return result; + } + + static bool IsValidMessageBoxButton(MessageBoxButton value) => value == MessageBoxButton.OK + || value == MessageBoxButton.OKCancel + || value == MessageBoxButton.YesNo + || value == MessageBoxButton.YesNoCancel; + + static bool IsValidMessageBoxImage(MessageBoxImage value) => value == MessageBoxImage.Asterisk + || value == MessageBoxImage.Error + || value == MessageBoxImage.Exclamation + || value == MessageBoxImage.Hand + || value == MessageBoxImage.Information + || value == MessageBoxImage.None + || value == MessageBoxImage.Question + || value == MessageBoxImage.Stop + || value == MessageBoxImage.Warning; + + static bool IsValidMessageBoxResult(MessageBoxResult value) => value == MessageBoxResult.Cancel + || value == MessageBoxResult.No + || value == MessageBoxResult.None + || value == MessageBoxResult.OK + || value == MessageBoxResult.Yes; + + static bool IsValidMessageBoxOptions(MessageBoxOptions value) + { + int mask = ~((int)MessageBoxOptions.ServiceNotification | + (int)MessageBoxOptions.DefaultDesktopOnly | + (int)MessageBoxOptions.RightAlign | + (int)MessageBoxOptions.RtlReading); + + if (((int)value & mask) == 0) + return true; + return false; + } +} + +public enum MessageBoxResult +{ + None = 0, + + OK = 1, + + Cancel = 2, + + Yes = 6, + + No = 7, + + // NOTE: if you add or remove any values in this enum, be sure to update MessageBox.IsValidMessageBoxResult() +} + +[Flags] +public enum MessageBoxOptions +{ + None = 0x00000000, + + ServiceNotification = 0x00200000, + + DefaultDesktopOnly = 0x00020000, + + RightAlign = 0x00080000, + + RtlReading = 0x00100000, +} + +public enum MessageBoxImage +{ + None = 0, + + Hand = 0x00000010, + + Question = 0x00000020, + + Exclamation = 0x00000030, + + Asterisk = 0x00000040, + + Stop = Hand, + + Error = Hand, + + Warning = Exclamation, + + Information = Asterisk, + + // NOTE: if you add or remove any values in this enum, be sure to update MessageBox.IsValidMessageBoxIcon() +} + +public enum MessageBoxButton +{ + OK = 0x00000000, + + OKCancel = 0x00000001, + + YesNoCancel = 0x00000003, + + YesNo = 0x00000004, + + // NOTE: if you add or remove any values in this enum, be sure to update MessageBox.IsValidMessageBoxButton() +} + +#endif \ No newline at end of file diff --git a/src/Avalonia.WebView2.Sample/MainWindow.xaml.cs b/src/Avalonia.WebView2.Sample/MainWindow.xaml.cs index a78009b..7e684a6 100644 --- a/src/Avalonia.WebView2.Sample/MainWindow.xaml.cs +++ b/src/Avalonia.WebView2.Sample/MainWindow.xaml.cs @@ -36,9 +36,9 @@ static string GetTitle(string browserVersion, Architecture architecture = Unknow { if (architecture != Unknown) { - return $"Microsoft Edge WebView2 {browserVersion} {architecture} for Avalonia"; + return $"Microsoft Edge WebView2 {browserVersion} {architecture} for Avalonia on {System.Environment.OSVersion.VersionString}"; } - return $"Microsoft Edge WebView2 {browserVersion} for Avalonia"; + return $"Microsoft Edge WebView2 {browserVersion} for Avalonia on {System.Environment.OSVersion.VersionString}"; } void SetTitle(string browserVersion, Architecture architecture = Unknown) => Title.Content = base.Title = GetTitle(browserVersion, architecture); diff --git a/src/Avalonia.WebView2.Sample/Program.cs b/src/Avalonia.WebView2.Sample/Program.cs index 637e124..3e30d66 100644 --- a/src/Avalonia.WebView2.Sample/Program.cs +++ b/src/Avalonia.WebView2.Sample/Program.cs @@ -1,3 +1,6 @@ +using Microsoft.Win32; +using System.Windows; + namespace Avalonia.WebView2.Sample; static class Program @@ -6,8 +9,39 @@ static class Program // SynchronizationContext-reliant code before AppMain is called: things aren't initialized // yet and stuff might break. [STAThread] - public static void Main(string[] args) => BuildAvaloniaApp() - .StartWithClassicDesktopLifetime(args); + public static void Main(string[] args) + { + // If urn:schemas-microsoft-com:compatibility.v1 supportedOS exists in the app.manifest file, the control will not display normally, but it is normal in WPF + if (IsProgramInCompatibilityMode()) + { + // It's strange that the control running in compatibility mode can't display normally, but it works in WPF + MessageBox.Show("Windows Program Compatibility mode is on. Turn it off and then try again", "Error", MessageBoxButton.OK, MessageBoxImage.Error); + return; + } + + BuildAvaloniaApp().StartWithClassicDesktopLifetime(args); + } + + static bool IsProgramInCompatibilityMode() + { + try + { + foreach (var item in new[] { Registry.CurrentUser, Registry.LocalMachine }) + { + using var layers = item.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers"); + var value = layers?.GetValue(Environment.ProcessPath)?.ToString(); + if (value != null) + { + if (value.Contains("WIN8RTM", StringComparison.OrdinalIgnoreCase)) return true; + if (value.Contains("WIN7RTM", StringComparison.OrdinalIgnoreCase)) return true; + } + } + } + catch + { + } + return false; + } // Avalonia configuration, don't remove; also used by visual designer. public static AppBuilder BuildAvaloniaApp() diff --git a/src/Avalonia.WebView2.Sample/Properties/app.manifest b/src/Avalonia.WebView2.Sample/Properties/app.manifest index b42f355..179f1f9 100644 --- a/src/Avalonia.WebView2.Sample/Properties/app.manifest +++ b/src/Avalonia.WebView2.Sample/Properties/app.manifest @@ -1,79 +1,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + true/PM + PerMonitorV2, PerMonitor + + diff --git a/src/Avalonia.WebView2/Avalonia.WebView2.csproj b/src/Avalonia.WebView2/Avalonia.WebView2.csproj index 608a096..d5eeab3 100644 --- a/src/Avalonia.WebView2/Avalonia.WebView2.csproj +++ b/src/Avalonia.WebView2/Avalonia.WebView2.csproj @@ -10,7 +10,7 @@ This package is necessary for Avalonia applications. To learn more about package versions checkout https://aka.ms/wv2-packageversion. To learn best practices checkout: https://aka.ms/wv2-bestpractices. Web WebView Native native package Edge avalonia avaloniaui dotnet framework core Webview2 - 1.0.1264.42-preview.220710.2 + 1.0.1264.42-preview.220711.2 diff --git a/src/Avalonia.WebView2/_SourceCodeReference/Avalonia/Input/WebView2KeyEventArgs.cs b/src/Avalonia.WebView2/Avalonia/Input/WebView2KeyEventArgs.cs similarity index 100% rename from src/Avalonia.WebView2/_SourceCodeReference/Avalonia/Input/WebView2KeyEventArgs.cs rename to src/Avalonia.WebView2/Avalonia/Input/WebView2KeyEventArgs.cs diff --git a/src/Avalonia.WebView2/BCL/MS/Win32/NativeMethods.cs b/src/Avalonia.WebView2/BCL/MS/Win32/NativeMethods.cs new file mode 100644 index 0000000..45f7b2c --- /dev/null +++ b/src/Avalonia.WebView2/BCL/MS/Win32/NativeMethods.cs @@ -0,0 +1,64 @@ +namespace MS.Win32; + +static partial class NativeMethods +{ + [DllImport("user32.dll", SetLastError = true)] + internal static extern IntPtr BeginPaint(IntPtr hwnd, out PaintStruct lpPaint); + + [DllImport("user32.dll", SetLastError = true)] + internal static extern bool EndPaint(IntPtr hwnd, ref PaintStruct lpPaint); + + //[DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)] + //public static extern IntPtr CreateWindowExW(WS_EX dwExStyle, [MarshalAs(UnmanagedType.LPWStr)] string? lpClassName, [MarshalAs(UnmanagedType.LPWStr)] string lpWindowName, WS dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, IntPtr lpParam); + + //[DllImport("user32.dll", SetLastError = true)] + //[return: MarshalAs(UnmanagedType.Bool)] + //public static extern bool DestroyWindow(IntPtr hwnd); + + //[DllImport("user32.dll")] + //public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); + + //[Flags] + //public enum WS : uint + //{ + // None = 0, + // CLIPCHILDREN = 33554432, // 0x02000000 + // VISIBLE = 268435456, // 0x10000000 + // CHILD = 1073741824, // 0x40000000 + //} + + //[Flags] + //public enum WS_EX : uint + //{ + // None = 0, + // TRANSPARENT = 32, // 0x00000020 + //} + + public enum WM : uint + { + SETFOCUS = 7, + PAINT = 15, // 0x0000000F + + WINDOWPOSCHANGING = 0x0046, + GETOBJECT = 0x003D, + SHOWWINDOW = 0x0018, + } + + public struct Rect + { + public int left; + public int top; + public int right; + public int bottom; + } + + public struct PaintStruct + { + public IntPtr hdc; + public bool fErase; + public Rect rcPaint; + public bool fRestore; + public bool fIncUpdate; + public byte[] rgbReserved; + } +} \ No newline at end of file diff --git a/src/Avalonia.WebView2/_SourceCodeReference/MS/Win32/NativeMethodsCLR.cs b/src/Avalonia.WebView2/BCL/MS/Win32/NativeMethodsCLR.cs similarity index 100% rename from src/Avalonia.WebView2/_SourceCodeReference/MS/Win32/NativeMethodsCLR.cs rename to src/Avalonia.WebView2/BCL/MS/Win32/NativeMethodsCLR.cs diff --git a/src/Avalonia.WebView2/_SourceCodeReference/MS/Win32/NativeMethodsOther.cs b/src/Avalonia.WebView2/BCL/MS/Win32/NativeMethodsOther.cs similarity index 100% rename from src/Avalonia.WebView2/_SourceCodeReference/MS/Win32/NativeMethodsOther.cs rename to src/Avalonia.WebView2/BCL/MS/Win32/NativeMethodsOther.cs diff --git a/src/Avalonia.WebView2/_SourceCodeReference/System/ConvertibleHelper.cs b/src/Avalonia.WebView2/BCL/System/ConvertibleHelper.cs similarity index 100% rename from src/Avalonia.WebView2/_SourceCodeReference/System/ConvertibleHelper.cs rename to src/Avalonia.WebView2/BCL/System/ConvertibleHelper.cs diff --git a/src/Avalonia.WebView2/_SourceCodeReference/System/OperatingSystemCompat.cs b/src/Avalonia.WebView2/BCL/System/OperatingSystemCompat.cs similarity index 100% rename from src/Avalonia.WebView2/_SourceCodeReference/System/OperatingSystemCompat.cs rename to src/Avalonia.WebView2/BCL/System/OperatingSystemCompat.cs diff --git a/src/Avalonia.WebView2/_SourceCodeReference/System/Runtime/Versioning/PlatformAttributes.cs b/src/Avalonia.WebView2/BCL/System/Runtime/Versioning/PlatformAttributes.cs similarity index 100% rename from src/Avalonia.WebView2/_SourceCodeReference/System/Runtime/Versioning/PlatformAttributes.cs rename to src/Avalonia.WebView2/BCL/System/Runtime/Versioning/PlatformAttributes.cs diff --git a/src/Avalonia.WebView2/_SourceCodeReference/System/Windows/Input/KeyInterop.cs b/src/Avalonia.WebView2/BCL/System/Windows/Input/KeyInterop.cs similarity index 100% rename from src/Avalonia.WebView2/_SourceCodeReference/System/Windows/Input/KeyInterop.cs rename to src/Avalonia.WebView2/BCL/System/Windows/Input/KeyInterop.cs diff --git a/src/Avalonia.WebView2/_SourceCodeReference/System/Windows/Interop/IHwndHost.cs b/src/Avalonia.WebView2/BCL/System/Windows/Interop/IHwndHost.cs similarity index 100% rename from src/Avalonia.WebView2/_SourceCodeReference/System/Windows/Interop/IHwndHost.cs rename to src/Avalonia.WebView2/BCL/System/Windows/Interop/IHwndHost.cs diff --git a/src/Avalonia.WebView2/_SourceCodeReference/CefNet/Avalonia/Internal/GlobalHooks.cs b/src/Avalonia.WebView2/CefNet/Avalonia/Internal/GlobalHooks.cs similarity index 100% rename from src/Avalonia.WebView2/_SourceCodeReference/CefNet/Avalonia/Internal/GlobalHooks.cs rename to src/Avalonia.WebView2/CefNet/Avalonia/Internal/GlobalHooks.cs diff --git a/src/Avalonia.WebView2/_SourceCodeReference/CefNet/Avalonia/Internal/WindowsHwndSource.cs b/src/Avalonia.WebView2/CefNet/Avalonia/Internal/WindowsHwndSource.cs similarity index 100% rename from src/Avalonia.WebView2/_SourceCodeReference/CefNet/Avalonia/Internal/WindowsHwndSource.cs rename to src/Avalonia.WebView2/CefNet/Avalonia/Internal/WindowsHwndSource.cs diff --git a/src/Avalonia.WebView2/_SourceCodeReference/CefNet/Avalonia/WinApi/NativeMethods.cs b/src/Avalonia.WebView2/CefNet/Avalonia/WinApi/NativeMethods.cs similarity index 100% rename from src/Avalonia.WebView2/_SourceCodeReference/CefNet/Avalonia/WinApi/NativeMethods.cs rename to src/Avalonia.WebView2/CefNet/Avalonia/WinApi/NativeMethods.cs diff --git a/src/Avalonia.WebView2/WebView2.cs b/src/Avalonia.WebView2/WebView2.cs index eaab685..a674404 100644 --- a/src/Avalonia.WebView2/WebView2.cs +++ b/src/Avalonia.WebView2/WebView2.cs @@ -1,3 +1,5 @@ +using Avalonia.Media.Immutable; + namespace Avalonia.Controls; /// @@ -17,8 +19,20 @@ public WebView2() this.GetPropertyChangedObservable(BoundsProperty).Subscribe(OnBoundsChanged); } - static int ToSize(double d) + int ToSize(double d, bool ignoreDPI = false) { + if (!ignoreDPI) + { + var window = Window; + if (window != null) + { + var screen = window.Screens.ScreenFromWindow(window.PlatformImpl); + if (screen != null) + { + d *= screen.PixelDensity; + } + } + } if (double.IsNaN(d) || d <= 0D) return 0; return Convert.ToInt32(Math.Ceiling(d)); } @@ -98,6 +112,7 @@ protected override void OnInitialized() public override void Render(DrawingContext context) { base.Render(context); + //context.DrawRectangle(new Media.Pen(new ImmutableSolidColorBrush(Avalonia.Media.Color.FromArgb(_defaultBackgroundColor.A, _defaultBackgroundColor.R, _defaultBackgroundColor.G, _defaultBackgroundColor.B))), base.Bounds); _implicitInitGate.OnSynchronizationContextExists(); } @@ -865,119 +880,18 @@ void CoreWebView2Controller_ZoomFactorChanged(object? sender, object e) } #endif - protected IPlatformHandle? PlatformHandle { get; set; } - readonly TaskCompletionSource _hwndTaskSource = new(); - /// - /// This is overridden from and is called to instruct us to create our HWND. - /// - /// The HWND that we should use as the parent of the one we create. - /// The HWND that we created. - /// protected override IPlatformHandle CreateNativeControlCore(IPlatformHandle parent) { -#if !DISABLE_WEBVIEW2_CORE -#if !WINDOWS - if (OperatingSystem.IsWindows()) -#endif - { - var hwnd = Window!.PlatformImpl.Handle.Handle; - IntPtr windowExW = NativeMethods.CreateWindowExW(NativeMethods.WS_EX.TRANSPARENT, "static", string.Empty, NativeMethods.WS.CLIPCHILDREN | NativeMethods.WS.VISIBLE | NativeMethods.WS.CHILD, 0, 0, 0, 0, hwnd, IntPtr.Zero, Marshal.GetHINSTANCE(typeof(NativeMethods).Module), IntPtr.Zero); - var error = Marshal.GetLastWin32Error(); - if (error != 0) throw new Win32Exception(error); - if (_coreWebView2Controller != null) - ReparentController(windowExW); - //if (!_hwndTaskSource.Task.IsCompleted) - // _hwndTaskSource.SetResult(windowExW); - return PlatformHandle = new PlatformHandle(windowExW, "HWND"); - } -#endif - return base.CreateNativeControlCore(parent); + return new PlatformHandle(IntPtr.Zero, null); } - /// - /// This is overridden from and is called to instruct us to destroy our HWND. - /// - /// Our HWND that we need to destroy. - /// protected override void DestroyNativeControlCore(IPlatformHandle control) { -#if !DISABLE_WEBVIEW2_CORE - PlatformHandle = null; -#if !WINDOWS - if (OperatingSystem.IsWindows()) -#endif - { - if (_coreWebView2Controller != null) - ReparentController(IntPtr.Zero); - NativeMethods.DestroyWindow(control.Handle); - } -#endif - ((INativeControlHostDestroyableControlHandle?)control)?.Destroy(); + base.DestroyNativeControlCore(control); } -#if !DISABLE_WEBVIEW2_CORE - /// - /// Changes our controller's ParentWindow to the given HWND, along with any other necessary associated work. - /// - /// The new HWND to set as the controller's parent. IntPtr.Zero means that the controller will have no parent and the CoreWebView2 will be hidden. - /// Whether or not to call as required. Defaults to true. If you pass false then you should call it yourself if required. - /// - /// Reparenting the controller isn't necessarily as simple as changing its ParentWindow property, - /// and this method exists to ensure that any other work that needs to be done at the same time gets done. - /// The reason that SyncControllerWithParentWindow isn't baked directly into this method is because - /// sometimes we want to call the Sync functionality without necessarily reparenting (e.g. during initialization). - /// - void ReparentController(IntPtr hwnd, bool sync = true) - { - if (hwnd == IntPtr.Zero) - { - if (_coreWebView2Controller != null) - { - _coreWebView2Controller.IsVisible = false; - _coreWebView2Controller.ParentWindow = IntPtr.Zero; - } - } - else - { - if (_coreWebView2Controller != null) - { - _coreWebView2Controller.ParentWindow = hwnd; - } - if (!sync) - return; - SyncControllerWithParentWindow(); - } - } -#endif - - /// - /// Updates the child window's size, visibility, and position to reflect the current state of the element. - /// - public virtual void UpdateWindowPos() - { - - } - -#if !DISABLE_WEBVIEW2_CORE - /// - /// Syncs visual/windowing information between the controller and its parent HWND. - /// This should be called any time a new, non-null HWND is set as the controller's parent, - /// including when the controller is first created. - /// - void SyncControllerWithParentWindow() - { - UpdateWindowPos(); - if (_coreWebView2Controller != null) - { - if (KeyboardDevice.Instance?.FocusedElement == this) - _coreWebView2Controller.MoveFocus(CoreWebView2MoveFocusReason.Programmatic); - _coreWebView2Controller.IsVisible = IsVisible; - } - } -#endif - protected Window? Window { get; set; } protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) diff --git a/src/Avalonia.WebView2/_SourceCodeReference/MS/Win32/NativeMethods.cs b/src/Avalonia.WebView2/_SourceCodeReference/MS/Win32/NativeMethods.cs deleted file mode 100644 index 769b8d8..0000000 --- a/src/Avalonia.WebView2/_SourceCodeReference/MS/Win32/NativeMethods.cs +++ /dev/null @@ -1,60 +0,0 @@ -namespace MS.Win32; - -static partial class NativeMethods -{ - [DllImport("user32.dll", SetLastError = true)] - internal static extern IntPtr BeginPaint(IntPtr hwnd, out PaintStruct lpPaint); - - [DllImport("user32.dll", SetLastError = true)] - internal static extern bool EndPaint(IntPtr hwnd, ref PaintStruct lpPaint); - - [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - public static extern IntPtr CreateWindowExW(WS_EX dwExStyle, [MarshalAs(UnmanagedType.LPWStr)] string? lpClassName, [MarshalAs(UnmanagedType.LPWStr)] string lpWindowName, WS dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, IntPtr hMenu, IntPtr hInstance, IntPtr lpParam); - - [DllImport("user32.dll", SetLastError = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool DestroyWindow(IntPtr hwnd); - - [Flags] - public enum WS : uint - { - None = 0, - CLIPCHILDREN = 33554432, // 0x02000000 - VISIBLE = 268435456, // 0x10000000 - CHILD = 1073741824, // 0x40000000 - } - - [Flags] - public enum WS_EX : uint - { - None = 0, - TRANSPARENT = 32, // 0x00000020 - } - - public enum WM : uint - { - SETFOCUS = 7, - PAINT = 15, // 0x0000000F - - WINDOWPOSCHANGING = 0x0046, - GETOBJECT = 0x003D, - } - - public struct Rect - { - public int left; - public int top; - public int right; - public int bottom; - } - - public struct PaintStruct - { - public IntPtr hdc; - public bool fErase; - public Rect rcPaint; - public bool fRestore; - public bool fIncUpdate; - public byte[] rgbReserved; - } -} \ No newline at end of file