Add Win32 API

This commit is contained in:
polarboy 2024-10-08 18:18:39 +08:00
parent 92daa08919
commit c646cd796a
14 changed files with 365 additions and 86 deletions

View File

@ -50,6 +50,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AtomUI", "packages\AtomUI\A
{B2A7349B-4B38-45CB-8D22-3E06D1E3650F} = {B2A7349B-4B38-45CB-8D22-3E06D1E3650F}
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AtomUI.Platform.Win32", "src\AtomUI.Platform.Win32\AtomUI.Platform.Win32.csproj", "{9BF7EF51-4100-4EAE-8A95-FC5F1BD4A1E4}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -96,6 +98,10 @@ Global
{89A98C0D-B6F7-48CD-91C4-79FC0FED3615}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{89A98C0D-B6F7-48CD-91C4-79FC0FED3615}.Debug|Any CPU.Build.0 = Debug|Any CPU
{89A98C0D-B6F7-48CD-91C4-79FC0FED3615}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9BF7EF51-4100-4EAE-8A95-FC5F1BD4A1E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9BF7EF51-4100-4EAE-8A95-FC5F1BD4A1E4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9BF7EF51-4100-4EAE-8A95-FC5F1BD4A1E4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9BF7EF51-4100-4EAE-8A95-FC5F1BD4A1E4}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -18,4 +18,8 @@
<InternalsVisibleTo Include="AtomUI.Controls"/>
</ItemGroup>
<ItemGroup Condition="$([MSBuild]::IsOSPlatform('Windows'))">
<ProjectReference Include="..\AtomUI.Platform.Win32\AtomUI.Platform.Win32.csproj" />
</ItemGroup>
</Project>

View File

@ -1,11 +1,11 @@
using System.Reflection;
using AtomUI.Platform.Windows;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Primitives.PopupPositioning;
using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.VisualTree;
using AtomUI.Platform.Windows;
namespace AtomUI.MotionScene;

View File

@ -1,75 +0,0 @@
using System.Reflection;
using System.Runtime.Loader;
using Avalonia.Controls;
namespace AtomUI.Platform.Windows;
internal static class WindowExt
{
public const uint WS_EX_TRANSPARENT = 32; // 0x00000020
public const uint WS_EX_LAYERED = 0x00080000;
private static readonly Type WindowImplType;
private static readonly MethodInfo GetExtendedStyleInfo;
private static readonly MethodInfo SetExtendedStyleInfo;
static WindowExt()
{
var assembly = AssemblyLoadContext.Default.LoadFromAssemblyName(new AssemblyName("Avalonia.Win32"));
WindowImplType = assembly.GetType("Avalonia.Win32.WindowImpl")!;
GetExtendedStyleInfo =
WindowImplType.GetMethod("GetExtendedStyle", BindingFlags.Instance | BindingFlags.NonPublic)!;
SetExtendedStyleInfo =
WindowImplType.GetMethod("SetExtendedStyle", BindingFlags.Instance | BindingFlags.NonPublic)!;
}
public static void SetTransparentForMouseEvents(this WindowBase window, bool flag)
{
var impl = window.PlatformImpl!;
var currentStyles = GetExtendedStyle(impl);
// 不是确定这样处理是否合适
if (flag)
{
currentStyles |= WS_EX_TRANSPARENT | WS_EX_LAYERED;
}
else
{
currentStyles &= ~(WS_EX_TRANSPARENT | WS_EX_LAYERED);
}
SetExtendedStyle(impl, currentStyles, false);
}
public static void SetTransparentForMouseEvents(this Window window, bool flag)
{
var impl = window.PlatformImpl!;
var currentStyles = GetExtendedStyle(impl);
// 不是确定这样处理是否合适
if (flag)
{
currentStyles |= WS_EX_TRANSPARENT | WS_EX_LAYERED;
}
else
{
currentStyles &= ~(WS_EX_TRANSPARENT | WS_EX_LAYERED);
}
SetExtendedStyle(impl, currentStyles, false);
}
private static uint GetExtendedStyle(object instance)
{
return (uint)GetExtendedStyleInfo.Invoke(instance, new object[] { })!;
}
private static void SetExtendedStyle(object instance, uint styles, bool save)
{
SetExtendedStyleInfo.Invoke(instance, new object[] { styles, save });
}
public static bool IsTransparentForMouseEvents(this WindowBase window)
{
var impl = window.PlatformImpl!;
var styles = GetExtendedStyle(impl);
return (styles & WS_EX_TRANSPARENT) != 0;
}
}

View File

@ -0,0 +1,21 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="$(MSBuildThisFileDirectory)..\..\build\Common.props"/>
<Import Project="$(MSBuildThisFileDirectory)..\..\build\Nuget.props"/>
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<InternalsVisibleTo Include="AtomUI.Base" />
<InternalsVisibleTo Include="AtomUI.Controls" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Avalonia"/>
</ItemGroup>
</Project>

View File

@ -0,0 +1,7 @@
namespace AtomUI.Platform.Win32.Interop;
internal enum AppBarMessage : uint
{
ABM_GETSTATE = 0x00000004,
ABM_GETTASKBARPOS = 0x00000005,
}

View File

@ -0,0 +1,19 @@
namespace AtomUI.Platform.Win32.Interop;
[Flags]
internal enum ClassStyles : uint
{
CS_VREDRAW = 0x0001,
CS_HREDRAW = 0x0002,
CS_DBLCLKS = 0x0008,
CS_OWNDC = 0x0020,
CS_CLASSDC = 0x0040,
CS_PARENTDC = 0x0080,
CS_NOCLOSE = 0x0200,
CS_SAVEBITS = 0x0800,
CS_BYTEALIGNCLIENT = 0x1000,
CS_BYTEALIGNWINDOW = 0x2000,
CS_GLOBALCLASS = 0x4000,
CS_IME = 0x00010000,
CS_DROPSHADOW = 0x00020000
}

View File

@ -0,0 +1,26 @@
namespace AtomUI.Platform.Win32.Interop;
internal struct ITaskBarList3VTable
{
public IntPtr IUnknown1;
public IntPtr IUnknown2;
public IntPtr IUnknown3;
public IntPtr HrInit;
public IntPtr AddTab;
public IntPtr DeleteTab;
public IntPtr ActivateTab;
public IntPtr SetActiveAlt;
public IntPtr MarkFullscreenWindow;
public IntPtr SetProgressValue;
public IntPtr SetProgressState;
public IntPtr RegisterTab;
public IntPtr UnregisterTab;
public IntPtr SetTabOrder;
public IntPtr SetTabActive;
public IntPtr ThumbBarAddButtons;
public IntPtr ThumbBarUpdateButtons;
public IntPtr ThumbBarSetImageList;
public IntPtr SetOverlayIcon;
public IntPtr SetThumbnailTooltip;
public IntPtr SetThumbnailClip;
}

View File

@ -0,0 +1,102 @@
namespace AtomUI.Platform.Win32.Interop;
internal enum SystemMetric
{
SM_CXSCREEN = 0, // 0x00
SM_CYSCREEN = 1, // 0x01
SM_CXVSCROLL = 2, // 0x02
SM_CYHSCROLL = 3, // 0x03
SM_CYCAPTION = 4, // 0x04
SM_CXBORDER = 5, // 0x05
SM_CYBORDER = 6, // 0x06
SM_CXDLGFRAME = 7, // 0x07
SM_CXFIXEDFRAME = 7, // 0x07
SM_CYDLGFRAME = 8, // 0x08
SM_CYFIXEDFRAME = 8, // 0x08
SM_CYVTHUMB = 9, // 0x09
SM_CXHTHUMB = 10, // 0x0A
SM_CXICON = 11, // 0x0B
SM_CYICON = 12, // 0x0C
SM_CXCURSOR = 13, // 0x0D
SM_CYCURSOR = 14, // 0x0E
SM_CYMENU = 15, // 0x0F
SM_CXFULLSCREEN = 16, // 0x10
SM_CYFULLSCREEN = 17, // 0x11
SM_CYKANJIWINDOW = 18, // 0x12
SM_MOUSEPRESENT = 19, // 0x13
SM_CYVSCROLL = 20, // 0x14
SM_CXHSCROLL = 21, // 0x15
SM_DEBUG = 22, // 0x16
SM_SWAPBUTTON = 23, // 0x17
SM_CXMIN = 28, // 0x1C
SM_CYMIN = 29, // 0x1D
SM_CXSIZE = 30, // 0x1E
SM_CYSIZE = 31, // 0x1F
SM_CXSIZEFRAME = 32, // 0x20
SM_CXFRAME = 32, // 0x20
SM_CYSIZEFRAME = 33, // 0x21
SM_CYFRAME = 33, // 0x21
SM_CXMINTRACK = 34, // 0x22
SM_CYMINTRACK = 35, // 0x23
SM_CXDOUBLECLK = 36, // 0x24
SM_CYDOUBLECLK = 37, // 0x25
SM_CXICONSPACING = 38, // 0x26
SM_CYICONSPACING = 39, // 0x27
SM_MENUDROPALIGNMENT = 40, // 0x28
SM_PENWINDOWS = 41, // 0x29
SM_DBCSENABLED = 42, // 0x2A
SM_CMOUSEBUTTONS = 43, // 0x2B
SM_SECURE = 44, // 0x2C
SM_CXEDGE = 45, // 0x2D
SM_CYEDGE = 46, // 0x2E
SM_CXMINSPACING = 47, // 0x2F
SM_CYMINSPACING = 48, // 0x30
SM_CXSMICON = 49, // 0x31
SM_CYSMICON = 50, // 0x32
SM_CYSMCAPTION = 51, // 0x33
SM_CXSMSIZE = 52, // 0x34
SM_CYSMSIZE = 53, // 0x35
SM_CXMENUSIZE = 54, // 0x36
SM_CYMENUSIZE = 55, // 0x37
SM_ARRANGE = 56, // 0x38
SM_CXMINIMIZED = 57, // 0x39
SM_CYMINIMIZED = 58, // 0x3A
SM_CXMAXTRACK = 59, // 0x3B
SM_CYMAXTRACK = 60, // 0x3C
SM_CXMAXIMIZED = 61, // 0x3D
SM_CYMAXIMIZED = 62, // 0x3E
SM_NETWORK = 63, // 0x3F
SM_CLEANBOOT = 67, // 0x43
SM_CXDRAG = 68, // 0x44
SM_CYDRAG = 69, // 0x45
SM_SHOWSOUNDS = 70, // 0x46
SM_CXMENUCHECK = 71, // 0x47
SM_CYMENUCHECK = 72, // 0x48
SM_SLOWMACHINE = 73, // 0x49
SM_MIDEASTENABLED = 74, // 0x4A
SM_MOUSEWHEELPRESENT = 75, // 0x4B
SM_XVIRTUALSCREEN = 76, // 0x4C
SM_YVIRTUALSCREEN = 77, // 0x4D
SM_CXVIRTUALSCREEN = 78, // 0x4E
SM_CYVIRTUALSCREEN = 79, // 0x4F
SM_CMONITORS = 80, // 0x50
SM_SAMEDISPLAYFORMAT = 81, // 0x51
SM_IMMENABLED = 82, // 0x52
SM_CXFOCUSBORDER = 83, // 0x53
SM_CYFOCUSBORDER = 84, // 0x54
SM_TABLETPC = 86, // 0x56
SM_MEDIACENTER = 87, // 0x57
SM_STARTER = 88, // 0x58
SM_SERVERR2 = 89, // 0x59
SM_MOUSEHORIZONTALWHEELPRESENT = 91, // 0x5B
SM_CXPADDEDBORDER = 92, // 0x5C
SM_DIGITIZER = 94, // 0x5E
SM_MAXIMUMTOUCHES = 95, // 0x5F
SM_REMOTESESSION = 0x1000, // 0x1000
SM_SHUTTINGDOWN = 0x2000, // 0x2000
SM_REMOTECONTROL = 0x2001, // 0x2001
SM_CONVERTABLESLATEMODE = 0x2003,
SM_SYSTEMDOCKED = 0x2004,
}

View File

@ -0,0 +1,12 @@
namespace AtomUI.Platform.Win32.Interop;
internal enum WindowLongParam
{
GWL_WNDPROC = -4,
GWL_HINSTANCE = -6,
GWL_HWNDPARENT = -8,
GWL_ID = -12,
GWL_STYLE = -16,
GWL_EXSTYLE = -20,
GWL_USERDATA = -21
}

View File

@ -0,0 +1,55 @@
namespace AtomUI.Platform.Win32.Interop;
[Flags]
internal enum WindowStyles : uint
{
WS_BORDER = 0x800000,
WS_CAPTION = 0xc00000,
WS_CHILD = 0x40000000,
WS_CLIPCHILDREN = 0x2000000,
WS_CLIPSIBLINGS = 0x4000000,
WS_DISABLED = 0x8000000,
WS_DLGFRAME = 0x400000,
WS_GROUP = 0x20000,
WS_HSCROLL = 0x100000,
WS_MAXIMIZE = 0x1000000,
WS_MAXIMIZEBOX = 0x10000,
WS_MINIMIZE = 0x20000000,
WS_MINIMIZEBOX = 0x20000,
WS_OVERLAPPED = 0x0,
WS_OVERLAPPEDWINDOW = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX,
WS_POPUP = 0x80000000u,
WS_POPUPWINDOW = WS_POPUP | WS_BORDER | WS_SYSMENU,
WS_SYSMENU = 0x80000,
WS_TABSTOP = 0x10000,
WS_THICKFRAME = 0x40000,
WS_VISIBLE = 0x10000000,
WS_VSCROLL = 0x200000,
WS_EX_DLGMODALFRAME = 0x00000001,
WS_EX_NOPARENTNOTIFY = 0x00000004,
WS_EX_NOREDIRECTIONBITMAP = 0x00200000,
WS_EX_TOPMOST = 0x00000008,
WS_EX_ACCEPTFILES = 0x00000010,
WS_EX_TRANSPARENT = 0x00000020,
WS_EX_MDICHILD = 0x00000040,
WS_EX_TOOLWINDOW = 0x00000080,
WS_EX_WINDOWEDGE = 0x00000100,
WS_EX_CLIENTEDGE = 0x00000200,
WS_EX_CONTEXTHELP = 0x00000400,
WS_EX_RIGHT = 0x00001000,
WS_EX_LEFT = 0x00000000,
WS_EX_RTLREADING = 0x00002000,
WS_EX_LTRREADING = 0x00000000,
WS_EX_LEFTSCROLLBAR = 0x00004000,
WS_EX_RIGHTSCROLLBAR = 0x00000000,
WS_EX_CONTROLPARENT = 0x00010000,
WS_EX_STATICEDGE = 0x00020000,
WS_EX_APPWINDOW = 0x00040000,
WS_EX_OVERLAPPEDWINDOW = WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE,
WS_EX_PALETTEWINDOW = WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST,
WS_EX_LAYERED = 0x00080000,
WS_EX_NOINHERITLAYOUT = 0x00100000,
WS_EX_LAYOUTRTL = 0x00400000,
WS_EX_COMPOSITED = 0x02000000,
WS_EX_NOACTIVATE = 0x08000000
}

View File

@ -0,0 +1,51 @@
#nullable enable
using System.Runtime.InteropServices;
// ReSharper disable InconsistentNaming
#pragma warning disable 169, 649
namespace AtomUI.Platform.Win32.Interop;
internal static class Win32API
{
[DllImport("user32.dll", SetLastError = true, EntryPoint = "GetWindowLongPtrW", ExactSpelling = true)]
public static extern uint GetWindowLongPtr(IntPtr hWnd, int nIndex);
[DllImport("user32.dll", SetLastError = true, EntryPoint = "GetWindowLongW", ExactSpelling = true)]
public static extern uint GetWindowLong32b(IntPtr hWnd, int nIndex);
public static uint GetWindowLong(IntPtr hWnd, int nIndex)
{
if (IntPtr.Size == 4)
{
return GetWindowLong32b(hWnd, nIndex);
}
return GetWindowLongPtr(hWnd, nIndex);
}
[DllImport("user32.dll", SetLastError = true, EntryPoint = "SetWindowLongW", ExactSpelling = true)]
private static extern uint SetWindowLong32b(IntPtr hWnd, int nIndex, uint value);
[DllImport("user32.dll", SetLastError = true, EntryPoint = "SetWindowLongPtrW", ExactSpelling = true)]
private static extern IntPtr SetWindowLong64b(IntPtr hWnd, int nIndex, IntPtr value);
public static uint SetWindowLong(IntPtr hWnd, int nIndex, uint value)
{
if (IntPtr.Size == 4)
{
return SetWindowLong32b(hWnd, nIndex, value);
}
return (uint)SetWindowLong64b(hWnd, nIndex, new IntPtr(value)).ToInt32();
}
public static IntPtr SetWindowLongPtr(IntPtr hWnd, int nIndex, IntPtr handle)
{
if (IntPtr.Size == 4)
{
return new IntPtr(SetWindowLong32b(hWnd, nIndex, (uint)handle.ToInt32()));
}
return SetWindowLong64b(hWnd, nIndex, handle);
}
}

View File

@ -0,0 +1,60 @@
using AtomUI.Platform.Win32.Interop;
using Avalonia.Controls;
namespace AtomUI.Platform.Windows;
internal static class WindowBaseExtensions
{
private const WindowStyles WindowStateMask = (WindowStyles.WS_MAXIMIZE | WindowStyles.WS_MINIMIZE);
private static WindowStyles GetWindowStateStyles(this WindowBase window)
{
return window.GetWindowStyle() & WindowStateMask;
}
private static WindowStyles GetWindowStyle(this WindowBase window)
{
var hwnd = window.PlatformImpl!.Handle.Handle;
return (WindowStyles)Win32API.GetWindowLong(hwnd, (int)WindowLongParam.GWL_STYLE);
}
private static void SetWindowStyle(this WindowBase window, WindowStyles style)
{
var hwnd = window.PlatformImpl!.Handle.Handle;
Win32API.SetWindowLong(hwnd, (int)WindowLongParam.GWL_STYLE, (uint)style);
}
private static WindowStyles GetWindowExtendedStyle(this WindowBase window)
{
var hwnd = window.PlatformImpl!.Handle.Handle;
return (WindowStyles)Win32API.GetWindowLong(hwnd, (int)WindowLongParam.GWL_EXSTYLE);
}
private static void SetWindowExtendedStyle(this WindowBase window, WindowStyles style)
{
var hwnd = window.PlatformImpl!.Handle.Handle;
Win32API.SetWindowLong(hwnd, (int)WindowLongParam.GWL_EXSTYLE, (uint)style);
}
public static void SetTransparentForMouseEvents(this WindowBase window, bool flag)
{
var styles = window.GetWindowExtendedStyle();
// 不是确定这样处理是否合适
if (flag)
{
styles |= WindowStyles.WS_EX_TRANSPARENT | WindowStyles.WS_EX_LAYERED;
}
else
{
styles &= ~(WindowStyles.WS_EX_TRANSPARENT | WindowStyles.WS_EX_LAYERED);
}
window.SetWindowExtendedStyle(styles);
}
public static bool IsTransparentForMouseEvents(this WindowBase window)
{
var styles = window.GetWindowExtendedStyle();
return (styles & WindowStyles.WS_EX_TRANSPARENT) != 0;
}
}

View File

@ -31,13 +31,4 @@
<PackageReference Condition="'$(Configuration)' == 'Debug'" Include="Avalonia.Diagnostics"/>
</ItemGroup>
<ItemGroup>
<Compile Remove="Platform/**/*.cs"/>
</ItemGroup>
<ItemGroup Condition="$([MSBuild]::IsOSPlatform('Windows'))">
<Compile Include="Platform\Windows\*.cs"/>
<PackageReference Include="Avalonia.Win32"/>
</ItemGroup>
</Project>