WPF实现背景透明磨砂,并通过HandyControl组件实现弹出等待框

WPF实现背景透明磨砂,并通过HandyControl组件实现弹出等待框
前⾔:上⼀个版本的Winform需要改成WPF来做界⾯,第⼀次接触WPF,在转换过程中遇到的需求就是⼀个背景透明模糊,⼀个是类似于加载中…… 这样的等待窗⼝,等后台执⾏完毕后再关掉。在Winform中是通过⼀个类指定等待窗⼝的parent为调⽤者,并指定topmost为最顶层来实现。在WPF中这个⽅法不太灵光,通过这⼏天的摸索,到⼀个WPF下的UI利器--HandyControl(github/HandyOrg/HandyControl)感谢作者分享。通过它来实现⼀些界⾯的效果,它⾥⾯带的有个顶部弹出对话框的功能(带遮罩),但没到后台代码关闭的⽅法。所以我就单独从⾥⾯把这个功能提取出来,实现了弹出提⽰框,后台可以关闭的模式。
最新更新:控件作者提供了有⼀个⾃动关闭的Demo,请以Demo的使⽤⽅法为准。下载地址:
先看⼀下HandyControl提供的Demo中的这种对话框。
由于我需要的是弹出后,后台会执⾏代码,代码执⾏完后主动关闭对话框的操作。于是我把⾥⾯的这块代码单独提取出来改造了⼀下,实现效果如下。
这是在新接触WPF开发中,学习到的,如何让主窗体背景磨砂透明、如何Grid背景透明模糊、如何让Grid的控件不随Grid来模糊。
下⾯进⼊代码:
⾸先新建⼀个WPF项⽬,然后通过Nuget引⽤HandyControl。
在App.xaml中添加以下内容,来引⽤HandyControl的样式效果。
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/SkinDefault.xaml"/>
<ResourceDictionary Source="pack://application:,,,/HandyControl;component/Themes/Theme.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
<ResourceDictionary>
易服癖<viewModel:ViewModelLocator x:Key="Locator" />
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
  添加⼀个类⽂件BlurBehind.cs,⽤来实现主窗体透明磨砂感。
using System;
using System.Runtime.InteropServices;
namespace WpfApp1
{
/
// <summary>
/// 背景磨砂
/// </summary>
public class BlurBehind
{
internal enum AccentState
{
ACCENT_DISABLED = 1,
ACCENT_ENABLE_GRADIENT = 0,
ACCENT_ENABLE_TRANSPARENTGRADIENT = 2,
ACCENT_ENABLE_BLURBEHIND = 3,
安徽地方志
ACCENT_INVALID_STATE = 4,
ACCENT_ENABLE_ACRYLICBLURBEHIND = 5
}
[StructLayout(LayoutKind.Sequential)]
internal struct AccentPolicy
{
public AccentState AccentState;
public int AccentFlags;
public int GradientColor;
public int AnimationId;
}
[StructLayout(LayoutKind.Sequential)]
internal struct WindowCompositionAttributeData
{
public WindowCompositionAttribute Attribute;
public IntPtr Data;
public int SizeOfData;
}
internal enum WindowCompositionAttribute
{
// ...
WCA_ACCENT_POLICY = 19
/
/ ...
}
}
}
然后新建两个⽬录:ViewModel和Images2012广东中考数学
在Images中放⼊⼀张图⽚,并设置⽣成时⾃动复制
在ViewModel中新建三个类⽂件
DialogDemoViewModel.cs ⽤来实现弹出框
using System;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using HandyControl.Controls;
namespace WpfApp1.ViewModel
茎叶图{
public class DialogDemoViewModel : ViewModelBase
{
private string _dialogResult;
public string DialogResult
{
get => _dialogResult;
#if netle40
set => Set(nameof(DialogResult), ref _dialogResult, value);
#else
set => Set(ref _dialogResult, value);
#endif
}
public RelayCommand<TextDialog> ShowTextCmd => new Lazy<RelayCommand<TextDialog>>(() =>
new RelayCommand<TextDialog>(ShowText)).Value;
private static void ShowText(TextDialog d)漏斗原理
{
Dialog.Show(d);
//获得句柄
//var dialogShow = Dialog.Show(d);
//var dialogShowHwnd = (HwndSource)PresentationSource.FromVisual(dialogShow);
//if (dialogShowHwnd == null) return;
//var hwnd = dialogShowHwnd.Handle;
}
}
}
  DialogInfo.cs ⽤来实现数据绑定给弹出框,⽐如指定显⽰⽂字
using System.Windows.Automation.Peers;
using System.Windows.Automation.Provider;
using System.ComponentModel;
namespace WpfApp1.ViewModel
{
public class DialogInfo : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public DialogInfo()
{
MyTxt = "加载中,请稍后。";
}
private string myTxt;
public string MyTxt
{
get => myTxt;
set
{
myTxt = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("MyTxt"));
}
}
}
}
  ViewModelLocator.cs⽤来实现构建弹出框实例
using System;
using System.Windows;
using CommonServiceLocator;
using GalaSoft.MvvmLight.Ioc;
namespace WpfApp1.ViewModel
{
public class ViewModelLocator
{
public ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<DialogDemoViewModel>();
}
public static ViewModelLocator Instance => new Lazy<ViewModelLocator>(() =>
Application.Current.TryFindResource("Locator") as ViewModelLocator).Value;
#region Vm
public DialogDemoViewModel DialogDemo => ServiceLocator.Current.GetInstance<DialogDemoViewModel>();        #endregion
}
}
  MainWindow.xaml 主窗体的内容
<Window
xmlns="schemas.microsoft/winfx/2006/xaml/presentation"
xmlns:d="schemas.microsoft/expression/blend/2008"
xmlns:x="schemas.microsoft/winfx/2006/xaml"
xmlns:mc="/markup-compatibility/2006"
x:Class="WpfApp1.MainWindow"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800"
DataContext="{Binding DialogDemo,Source={StaticResource Locator}}"
Loaded="MainWindow_OnLoaded"
Background="#727A7A7A"
AllowsTransparency="True"
WindowStyle="None"
MouseDown="MainWindow_OnMouseDown"
>
<Grid HorizontalAlignment="Left" Height="397" Margin="10,10,0,0" VerticalAlignment="Top" Width="790" ZIndex="0" >
<Grid Margin="0,10,10,97">
<Grid.Background>
<ImageBrush ImageSource="/WpfApp1;component/Images/wow_cataclysm_artwork-wallpaper-960x540.jpg"></ImageBrush>
</Grid.Background>
<Grid.Effect>
<BlurEffect Radius="8"></BlurEffect>
</Grid.Effect>
</Grid>
<Button x:Name="Btn_Show" Content="Button" HorizontalAlignment="Left" Margin="430,185,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"  />
<TextBlock x:Name="txtBlock" HorizontalAlignment="Left" Margin="614,120,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top" Height="120" Width="145" Foreground="White"/>    </Grid>
</Window>
  MainWindow.xaml.cs
using System;
using System.Linq;
using System.Runtime.InteropServices;
using System.Timers;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;
using WpfApp1.ViewModel;
namespace WpfApp1
{
/// <summary>
/// MainWindow.xaml 的交互逻辑
/// </summary>男根
public partial class MainWindow
{
[DllImport("user32.dll")]
private static extern int SetWindowCompositionAttribute(IntPtr hwnd, ref BlurBehind.WindowCompositionAttributeData data);
private uint _blurOpacity;
public double BlurOpacity
{
get { return _blurOpacity; }
set { _blurOpacity = (uint)value; EnableBlur(); }
}
private uint _blurBackgroundColor = 0x990000; /* BGR color format */
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var newWindow = new TextDialog();
var dialog = new DialogDemoViewModel();
if (dialog.ShowTextCmd.CanExecute(newWindow))
{
dialog.ShowTextCmd.Execute(newWindow);
}
newWindow.info.MyTxt="加载中";
//if (DataContext is DialogDemoViewModel MyVM && MyVM.ShowTextCmd.CanExecute(newWindow))
//    MyVM.ShowTextCmd.Execute(newWindow);
var i = 0;
var timer = new Timer(1000);
timer.Elapsed+=delegate
{
Dispatcher.BeginInvoke(new Action(() =>
{
if (i < 5)
{
txtBlock.Text +=$"{5 - i}秒后关闭"+ Environment.NewLine;
i++;
}
else
{
newWindow.CloseMe();
}
}));
};
timer.AutoReset = true;
timer.Enabled = true;
}
/// <summary>
/
//    获取当前应⽤中处于激活的⼀个窗⼝
/// </summary>
/// <returns></returns>
private static Window GetActiveWindow() => Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive);
private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
{
EnableBlur();
}
private void EnableBlur()
{
var windowHelper = new WindowInteropHelper(this);
var accent = new BlurBehind.AccentPolicy
{
AccentState = BlurBehind.AccentState.ACCENT_ENABLE_BLURBEHIND,
//GradientColor = (int) ((_blurOpacity << 24) | (_blurBackgroundColor & 0xFFFFFF))
};
var accentStructSize = Marshal.SizeOf(accent);
var accentPtr = Marshal.AllocHGlobal(accentStructSize);
Marshal.StructureToPtr(accent, accentPtr, false);
var data = new BlurBehind.WindowCompositionAttributeData
{
Attribute = BlurBehind.WindowCompositionAttribute.WCA_ACCENT_POLICY,
SizeOfData = accentStructSize,
Data = accentPtr
};
SetWindowCompositionAttribute(windowHelper.Handle, ref data);
Marshal.FreeHGlobal(accentPtr);
}
private void MainWindow_OnMouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
DragMove();
}
}
}
  TextDialog.xaml 对话框
<Border x:Class="WpfApp1.TextDialog"
xmlns="schemas.microsoft/winfx/2006/xaml/presentation"
xmlns:x="schemas.microsoft/winfx/2006/xaml"
xmlns:hc="handyorg.github.io/handycontrol"
CornerRadius="10"
Width="400"
Height="247"
Background="{DynamicResource RegionBrush}"
>
<hc:SimplePanel>
<TextBlock x:Name="TextBlock" Style="{StaticResource TextBlockLargeBold}" Text="{Binding MyTxt,UpdateSourceTrigger=PropertyChanged}" HorizontalAlignment="Left" Margin="100,0,0,119" VerticalAlignment="Bottom" Height="68" Wi        <Button x:Name="BtnClose" Width="22" Height="22" Command="hc:ControlCommands.Close" Style="{StaticResource ButtonIcon}" Foreground="{DynamicResource PrimaryBrush}" hc:IconElement.Geometry="{StaticResource ErrorGeome    </hc:SimplePanel>
</Border>
  TextDialog.xaml.cs 新增了⼀个CloseMe ⽤来后台调⽤关闭它
1using System.Windows.Automation.Peers;
2using System.Windows.Automation.Provider;
3using WpfApp1.ViewModel;
4
5namespace WpfApp1
6 {
7///<summary>
8/// TextDialog_.xaml 的交互逻辑
9///</summary>
10public partial class TextDialog
11    {
12public DialogInfo info = new DialogInfo { MyTxt = "加载中……" };
13public TextDialog()
14        {
15            DataContext = info;
16            InitializeComponent();
17        }
18public void CloseMe()
19        {
20try
21            {
22                BtnClose.Visibility = Visibility.Visible;
23                BtnClose.OnClick();
24            }
25catch
26            {
27//
28            }
29
30        }
31    }
32///<summary>
33/// ButtonBase 扩展
34///</summary>
35public static class ButtonBaseExtension
36    {
37///<summary>
38///引发<see>
39///<cref>Primitives.ButtonBase.Click</cref>
40///</see>
41///路由事件。
42///</summary>
43///<param name="buttonBase">要引发路由事件的按钮</param>
44public static void OnClick(this System.Windows.Controls.Primitives.ButtonBase buttonBase)
45        {
46            buttonBase.GetType().GetMethod(nameof(OnClick), BindingFlags.Instance | BindingFlags.NonPublic)?.Invoke(buttonBase, null);
47        }
48    }
49
50 }

本文发布于:2024-09-21 23:28:48,感谢您对本站的认可!

本文链接:https://www.17tex.com/xueshu/222561.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:实现   关闭   后台   弹出   透明
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议