WPF 窗体设置亚克力效果
框架使用
大于等于.NET40。
Visual Studio 2022。
项目使用
MIT 开源许可协议。
WindowAcrylicBlur 设置亚克力颜色。
Opacity 设置透明度。
实现代码
1) 准备
WindowAcrylicBlur.cs如下:
usingSystem;
usingSystem.Runtime.InteropServices;
usingSystem.Windows;
usingSystem.Windows.Interop;
usingSystem.Windows.Media;
usingMicrosoft.Win32;
usingMicrosoft.Windows.Shell;
namespaceWPFDevelopers.Controls
{
internalenumAccentState
{
ACCENT_DISABLED=0,
ACCENT_ENABLE_GRADIENT=1,
ACCENT_ENABLE_TRANSPARENTGRADIENT=2,
ACCENT_ENABLE_BLURBEHIND=3,
ACCENT_ENABLE_ACRYLICBLURBEHIND=4,
ACCENT_INVALID_STATE=5
}
[StructLayout(LayoutKind.Sequential)]
internalstructAccentPolicy
{
publicAccentStateAccentState;
publicuintAccentFlags;
publicuintGradientColor;
publicuintAnimationId;
}
[StructLayout(LayoutKind.Sequential)]
internalstructWindowCompositionAttributeData
{
publicWindowCompositionAttributeAttribute;
publicIntPtrData;
publicintSizeOfData;
}
internalenumWindowCompositionAttribute
{
//...
WCA_ACCENT_POLICY=19
//...
}
internalclassWindowOldConfig
{
publicboolAllowsTransparency;
publicBrushBackground;
publicWindowChromeWindowChrome;
publicWindowStyleWindowStyle=WindowStyle.SingleBorderWindow;
}
internalclassWindowOSHelper
{
publicstaticVersionGetWindowOSVersion()
{
varregKey=Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\WindowsNT\CurrentVersion");
intmajor;
intminor;
intbuild;
intrevision;
try
{
varstr=regKey.GetValue("CurrentMajorVersionNumber")?.ToString();
int.TryParse(str,outmajor);
str=regKey.GetValue("CurrentMinorVersionNumber")?.ToString();
int.TryParse(str,outminor);
str=regKey.GetValue("CurrentBuildNumber")?.ToString();
int.TryParse(str,outbuild);
str=regKey.GetValue("BaseBuildRevisionNumber")?.ToString();
int.TryParse(str,outrevision);
returnnewVersion(major,minor,build,revision);
}
catch(Exception)
{
returnnewVersion(0,0,0,0);
}
finally
{
regKey.Close();
}
}
}
publicclassWindowAcrylicBlur:Freezable
{
privatestaticreadonlyColor_BackgtoundColor=Color.FromArgb(0x01,0,0,0);//设置透明色防止穿透
[DllImport("user32.dll")]
internalstaticexternintSetWindowCompositionAttribute(IntPtrhwnd,refWindowCompositionAttributeDatadata);
privatestaticboolEnableAcrylicBlur(Windowwindow,Colorcolor,doubleopacity,boolenable)
{
if(window==null)
returnfalse;
AccentStateaccentState;
varvOsVersion=WindowOSHelper.GetWindowOSVersion();
if(vOsVersion>newVersion(10,0,17763))//1809
accentState=enable?AccentState.ACCENT_ENABLE_ACRYLICBLURBEHIND:AccentState.ACCENT_DISABLED;
elseif(vOsVersion>newVersion(10,0))
accentState=enable?AccentState.ACCENT_ENABLE_BLURBEHIND:AccentState.ACCENT_DISABLED;
else
accentState=AccentState.ACCENT_DISABLED;
if(opacity>1)
opacity=1;
varwindowHelper=newWindowInteropHelper(window);
varaccent=newAccentPolicy();
varopacityIn=(uint)(255*opacity);
accent.AccentState=accentState;
if(enable)
{
varblurColor=(uint)((color.R<<0)|(color.G<<8)|(color.B<<16)|(color.A<<24));
varblurColorIn=blurColor;
if(opacityIn>0)
blurColorIn=(opacityIn<<24)|(blurColor&0xFFFFFF);
elseif(opacityIn==0&&color.A==0)
blurColorIn=(0x01<<24)|(blurColor&0xFFFFFF);
if(accent.GradientColor==blurColorIn)
returntrue;
accent.GradientColor=blurColorIn;
}
varaccentStructSize=Marshal.SizeOf(accent);
varaccentPtr=Marshal.AllocHGlobal(accentStructSize);
Marshal.StructureToPtr(accent,accentPtr,false);
vardata=newWindowCompositionAttributeData();
data.Attribute=WindowCompositionAttribute.WCA_ACCENT_POLICY;
data.SizeOfData=accentStructSize;
data.Data=accentPtr;
SetWindowCompositionAttribute(windowHelper.Handle,refdata);
Marshal.FreeHGlobal(accentPtr);
returntrue;
}
privatestaticvoidWindow_Initialized(objectsender,EventArgse)
{
if(!(senderisWindowwindow))
return;
varconfig=newWindowOldConfig
{
WindowStyle=window.WindowStyle,
AllowsTransparency=window.AllowsTransparency,
Background=window.Background
};
varvWindowChrome=WindowChrome.GetWindowChrome(window);
if(vWindowChrome==null)
{
window.WindowStyle=WindowStyle.None;//一定要将窗口的背景色改为透明才行
window.AllowsTransparency=true;//一定要将窗口的背景色改为透明才行
window.Background=newSolidColorBrush(_BackgtoundColor);//一定要将窗口的背景色改为透明才行
}
else
{
config.WindowChrome=newWindowChrome
{
GlassFrameThickness=vWindowChrome.GlassFrameThickness
};
window.Background=Brushes.Transparent;//一定要将窗口的背景色改为透明才行
varvGlassFrameThickness=vWindowChrome.GlassFrameThickness;
vWindowChrome.GlassFrameThickness=newThickness(0,vGlassFrameThickness.Top,0,0);
}
SetWindowOldConfig(window,config);
window.Initialized-=Window_Initialized;
}
privatestaticvoidWindow_Loaded(objectsender,RoutedEventArgse)
{
if(!(senderisWindowwindow))
return;
varvBlur=GetWindowAcrylicBlur(window);
if(vBlur!=null)
EnableAcrylicBlur(window,vBlur.BlurColor,vBlur.Opacity,true);
window.Loaded-=Window_Loaded;
}
protectedoverrideFreezableCreateInstanceCore()
{
thrownewNotImplementedException();
}
protectedoverridevoidOnChanged()
{
base.OnChanged();
}
protectedoverridevoidOnPropertyChanged(DependencyPropertyChangedEventArgse)
{
base.OnPropertyChanged(e);
}
#region开启Win11风格
publicstaticWindowAcrylicBlurGetWindowAcrylicBlur(DependencyObjectobj)
{
return(WindowAcrylicBlur)obj.GetValue(WindowAcrylicBlurProperty);
}
publicstaticvoidSetWindowAcrylicBlur(DependencyObjectobj,WindowAcrylicBlurvalue)
{
obj.SetValue(WindowAcrylicBlurProperty,value);
}
publicstaticreadonlyDependencyPropertyWindowAcrylicBlurProperty=
DependencyProperty.RegisterAttached("WindowAcrylicBlur",typeof(WindowAcrylicBlur),
typeof(WindowAcrylicBlur),
newPropertyMetadata(default(WindowAcrylicBlur),OnWindowAcryBlurPropertyChangedCallBack));
privatestaticvoidOnWindowAcryBlurPropertyChangedCallBack(DependencyObjectd,
DependencyPropertyChangedEventArgse)
{
if(!(disWindowwindow))
return;
if(e.OldValue==null&&e.NewValue==null)
return;
if(e.OldValue==null&&e.NewValue!=null)
{
window.Initialized+=Window_Initialized;
window.Loaded+=Window_Loaded;
}
if(e.OldValue!=null&&e.NewValue==null)
{
varvConfig=GetWindowOldConfig(d);
if(vConfig!=null)
{
window.WindowStyle=vConfig.WindowStyle;
window.AllowsTransparency=vConfig.AllowsTransparency;
window.Background=vConfig.Background;
if(vConfig.WindowChrome!=null)
{
varvWindowChrome=WidowChrome.GetWindowChrome(window);
if(vWindowChrome!=null)
vWindowChrome.GlassFrameThickness=vConfig.WindowChrome.GlassFrameThickness;
}
}
}
if(e.OldValue==e.NewValue)
{
if(!window.IsLoaded)
return;
varvBlur=e.NewValueasWindowAcrylicBlur;
if(vBlur==null)
return;
EnableAcrylicBlur(window,vBlur.BlurColor,vBlur.Opacity,true);
}
}
#endregion
#region内部设置
privatestaticWindowOldConfigGetWindowOldConfig(DependencyObjectobj)
{
return(WindowOldConfig)obj.GetValue(WindowOldConfigProperty);
}
privatestaticvoidSetWindowOldConfig(DependencyObjectobj,WindowOldConfigvalue)
{
obj.SetValue(WindowOldConfigProperty,value);
}
//UsingaDependencyPropertyasthebackingstoreforWindowOldConfig.Thisenablesanimation,styling,binding,etc...
privatestaticreadonlyDependencyPropertyWindowOldConfigProperty=
DependencyProperty.RegisterAttached("WindowOldConfig",typeof(WindowOldConfig),typeof(WindowAcrylicBlur),
newPropertyMetadata(default(WindowOldConfig)));
#endregion
#region
publicColorBlurColor
{
get=>(Color)GetValue(BlurColorProperty);
set=>SetValue(BlurColorProperty,value);
}
//UsingaDependencyPropertyasthebackingstoreforBlurColor.Thisenablesanimation,styling,binding,etc...
publicstaticreadonlyDependencyPropertyBlurColorProperty=
DependencyProperty.Register("BlurColor",typeof(Color),typeof(WindowAcrylicBlur),
newPropertyMetadata(default(Color)));
publicdoubleOpacity
{
get=>(double)GetValue(OpacityProperty);
set=>SetValue(OpacityProperty,value);
}
//UsingaDependencyPropertyasthebackingstoreforOpacity.Thisenablesanimation,styling,binding,etc...
publicstaticreadonlyDependencyPropertyOpacityProperty=
DependencyProperty.Register("Opacity",typeof(double),typeof(WindowAcrylicBlur),
newPropertyMetadata(default(double)));
#endregion
}
}
2) 使用
AcrylicBlurWindowExample.xaml如下:
<Windowx:Class="WPFDevelopers.Samples.ExampleViews.AcrylicBlurWindowExample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews"
xmlns:wpfdev="https://github.com/WPFDevelopersOrg/WPFDevelopers"
mc:Ignorable="d"WindowStartupLocation="CenterScreen"
ResizeMode="CanMinimize"
Title="Login"Height="350"Width="400">
<wpfdev:WindowChrome.WindowChrome>
<wpfdev:WindowChromeGlassFrameThickness="0100"/>
</wpfdev:WindowChrome.WindowChrome>
<wpfdev:WindowAcrylicBlur.WindowAcrylicBlur>
<wpfdev:WindowAcrylicBlurBlurColor="AliceBlue"Opacity="0.2"/>
</wpfdev:WindowAcrylicBlur.WindowAcrylicBlur>
<Grid>
<Grid.RowDefinitions>
<RowDefinitionHeight="40"/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanelHorizontalAlignment="Right"
Orientation="Horizontal"
Grid.Column="1"
wpfdev:WindowChrome.IsHitTestVisibleInChrome="True">
<ButtonStyle="{DynamicResourceWindowButtonStyle}"
Command="{BindingCloseCommand,RelativeSource={RelativeSourceAncestorType=local:AcrylicBlurWindowExample}}"Cursor="Hand">
<PathWidth="10"Height="10"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Data="{DynamicResourcePathMetroWindowClose}"
Fill="Red"
Stretch="Fill"/>
</Button>
</StackPanel>
<StackPanelGrid.Row="1"Margin="40,0,40,0"
wpfdev:WindowChrome.IsHitTestVisibleInChrome="True">
<ImageSource="/WPFDevelopers.ico"Width="80"Height="80"/>
<TextBoxwpfdev:ElementHelper.IsWatermark="True"wpfdev:ElementHelper.Watermark="账户"Margin="0,20,0,0"Cursor="Hand"/>
<PasswordBoxwpfdev:ElementHelper.IsWatermark="True"wpfdev:ElementHelper.Watermark="密码"Margin="0,20,0,0"Cursor="Hand"/>
<Buttonx:Name="LoginButton"
Content="登录"
Margin="0,20,0,0"
Style="{StaticResourcePrimaryButton}"/>
<GridMargin="02000">
<TextBlockFontSize="12">
<HyperlinkForeground="Black"TextDecorations="None">忘记密码</Hyperlink>
</TextBlock>
<TextBlockFontSize="12"HorizontalAlignment="Right"Margin="00-10">
<HyperlinkForeground="#4370F5"TextDecorations="None">注册账号</Hyperlink>
</TextBlock>
</Grid>
</StackPanel>
</Grid>
</Window>
3) 使用
AcrylicBlurWindowExample.xaml.cs如下:
usingSystem.Windows;
usingSystem.Windows.Input;
usingWPFDevelopers.Samples.Helpers;
namespaceWPFDevelopers.Samples.ExampleViews
{
///<summary>
///AcrylicBlurWindowExample.xaml的交互逻辑
///</summary>
publicpartialclassAcrylicBlurWindowExample:Window
{
publicAcrylicBlurWindowExample()
{
InitializeComponent();
}
publicICommandCloseCommand=>newRelayCommand(obj=>
{
Close();
});
}
}
实现效果
到此这篇关于WPF实现窗体亚克力效果的示例代码的文章就介绍到这了,更多相关WPF窗体亚克力内容请搜索中国红客联盟以前的文章或继续浏览下面的相关文章希望大家以后多多支持中国红客联盟!