BACKGROUND WPF achieve transparent frosted, and to achieve the pop-up frame by waiting assembly HandyControl

Original: WPF achieve transparent frosted background, and wait for the pop-up box to achieve by HandyControl components

Introduction: The previous version of Winform WPF do need to change the interface, the first contact with WPF, encountered during the conversion process needs a transparent background is blurred, it is similar to a Loading ...... the wait window, and other background and then finished off. Specifies the parent window is waiting for the caller through a class, and specify the topmost topmost be implemented in Winform. In WPF, this method not very good, through these days of exploration, find a WPF UI tool --HandyControl under (https://github.com/HandyOrg/HandyControl) thanked the author to share. It is achieved through a number of interface effects, with which it has a pop-up top (with mask) dialog, but this does not support background Close (authors said they could call the callback model, but did not find, nor which clearly stated). So I put this feature to extract from the inside out alone, to achieve a pop-up boxes, you can turn off the background mode.

Look at the Demo HandyControl provided in this dialog box.

 

Since I need is a pop-up, the background will execute the code, the code after the implementation of the initiative to close the dialog boxes. So I put inside this block of code to extract a bit singled out transformation, achieve results as follows.

 

This is new to WPF development, learned how to make the main form frosted transparent background, how Grid background blur transparent, how to make the Grid control does not come with Grid blur.

The following access codes:

First create a new WPF project, then reference HandyControl by Nuget.

Add the following in App.xaml, a reference to the style effects 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和Images

在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="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:mc="http://schemas.openxmlformats.org/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="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:hc="https://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" Width="100"/>
        <Button x:Name="BtnClose" Width="22" Height="22" Command="hc:ControlCommands.Close" Style="{StaticResource ButtonIcon}" Foreground="{DynamicResource PrimaryBrush}" hc:IconElement.Geometry="{StaticResource ErrorGeometry}" Padding="0" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,4,4,0" Visibility="Hidden" />
    </hc:SimplePanel>
</Border>

  TextDialog.xaml.cs 新增了一个CloseMe 用来后台调用关闭它

using System.Windows.Automation.Peers;
using System.Windows.Automation.Provider;
using WpfApp1.ViewModel;
 
namespace WpfApp1
{
    /// <summary>
    /// TextDialog_.xaml 的交互逻辑
    /// </summary>
    public partial class TextDialog
    {
        public DialogInfo info = new DialogInfo { MyTxt = "加载中……" };
        public TextDialog()
        {
            DataContext = info;
            InitializeComponent(); 
        }
        public void CloseMe()
        {
            var bam = new ButtonAutomationPeer(BtnClose);
            var iip = bam.GetPattern(PatternInterface.Invoke) as IInvokeProvider;
            iip?.Invoke();
        }
    }
}

  

Guess you like

Origin www.cnblogs.com/lonelyxmas/p/11100215.html