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

前言:上一个版本的Winform需要改成WPF来做界面,第一次接触WPF,在转换过程中遇到的需求就是一个背景透明模糊,一个是类似于 加载中…… 这样的等待窗口,等后台执行完毕后再关掉。在Winform中是通过一个类指定等待窗口的parent为调用者,并指定topmost为最顶层来实现。在WPF中这个方法不太灵光,通过这几天的摸索,找到一个WPF下的UI利器--HandyControl(https://github.com/HandyOrg/HandyControl)感谢作者分享。通过它来实现一些界面的效果,它里面带的有个顶部弹出对话框的功能(带遮罩),但这个不支持后台关闭(作者说是可以调用带回调的模式,但没有找到,也没有明确说明是哪个)。所以我就单独从里面把这个功能提取出来,实现了弹出提示框,后台可以关闭的模式。

先看一下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和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();
        }
    }
}

  

原文地址:https://www.cnblogs.com/wdw984/p/11049550.html

时间: 2024-10-06 09:32:15

WFP实现背景透明磨砂,并通过HandyControl组件实现弹出等待框的相关文章

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

原文:WPF实现背景透明磨砂,并通过HandyControl组件实现弹出等待框 前言:上一个版本的Winform需要改成WPF来做界面,第一次接触WPF,在转换过程中遇到的需求就是一个背景透明模糊,一个是类似于 加载中…… 这样的等待窗口,等后台执行完毕后再关掉.在Winform中是通过一个类指定等待窗口的parent为调用者,并指定topmost为最顶层来实现.在WPF中这个方法不太灵光,通过这几天的摸索,找到一个WPF下的UI利器--HandyControl(https://github.c

android 透明弹出搜索框

1.在QQ一些APP当中有是弹出一个半透明的搜索框的,其实这种效果就是很多种方法,自定义一个Dialog,或者直接将activity的背景变成半透明的也可以的. 下面就是将activity变成半透明的方法.效果图如下: 2.代码如下: 在styles.xml文件中添加自定义Theme 1 <style name="MyTranspaent"> 2 3 <item name="android:windowBackground">@color/t

登录界面,body上有背景图,点击输入框时,弹出的手机键盘会把背景图顶变形,而且会把footer顶上去

js: //防止背景图被手机键盘压缩变形 $(document).ready(function () { $('body').css({'height':$(window).height()}) }); //当点击input出现手机键盘时,窗口大小改变,隐藏footer以防止footer被手机键盘顶上来 $(function(){ var oHeight = $(window).height(); //浏览器当前的高度 $(window).resize(function(){ //当浏览器窗口的

MFC 加入背景图片并让控件背景透明

/*加入背景图片*/ BOOL CTOOLDlg::OnEraseBkgnd(CDC* pDC) { // TODO: 在此加入消息处理程序代码和/或调用默认值 CDialog::OnEraseBkgnd(pDC); HBITMAP   m_hBitmap; HDC           m_hBkDC; m_hBitmap   =   ::LoadBitmap(::GetModuleHandle(NULL),MAKEINTRESOURCE(IDB_BITMAP2)); m_hBkDC     =

如何实现背景透明,文字不透明,兼容所有浏览器?

IE专属滤镜 filter:Alpha(opacity=x) 使用说明:IE浏览器专属,问题多多,本文以设置背景透明为例子,如下: 仅支持IE6.7.8.9,在IE10版本被废除 在IE6.7中,需要激活IE的haslayout属性(如:*zoom:1或者*overflow:hidden),让它读懂filter:Alpha 在IE6.7.8中,设置了filter:Alpha的元素,父元素设置position:static(默认属性),其子元素为相对定位,可让子元素不透明 <!DOCTYPE ht

位图背景透明与设置位图透明度

位图怎么像PNG图片背景透明呢? 关键在于对单色位图的使用,单色位图,黑色表示前景颜色(可代表任意),白色代表图片背景颜色 实现API :Transparentblt来理解单色位图 函数原型:BOOL TransparentBlt(HDC hdcDest, int nXOriginDest, int nYOriginDest, int nWidthDest, int hHeightDest, HDC hdcSrc, int nXOriginSrc, int nYOriginSrc, int nW

cocos2dx背景透明处理

以最新的Cocos2d-x 3.2 release为例,介绍如何在Cocos2d-x中让程序背景透明. 一样,先上图. 修改的东西不多.主要有3步. 1.在AndroidManifest.xml中设置Activity背景透明 ? 1 android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" 如图, 2.在libcocos2dx项目的org.cocos2dx.lib项目中的Cocos2dxActivity

背景透明文字不透明的最佳方法兼容IE(以背景黑色透明度0.5为例)

以背景黑色,透明度0.5举例为大家详细介绍下关于背景透明,文字不透明的最佳方法同时兼容IE,具体实现如下,感兴趣的朋友可以参考下哈希望对大家有所帮助 以背景黑色,透明度0.5举例 非IE:background:rgba(0,0,0,0.5); IE: filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#7f000000,endColorstr=#7f000000); PS:#7f000000 其中7f是透明度0.5转换

flash背景透明兼容ie火狐

<embed src="1234.swf" quality="high" type="application/x-shockwave-flash" width="400" height="80" wmode="transparent"/> flash背景透明兼容ie火狐,布布扣,bubuko.com