• 给WPF程序增加玻璃效果


    在Vista中增加了一种Aero新界面,也就是我们所说的玻璃效果,这种效果比较酷,我也常常喜欢在自己写的小程序中加入这种效果。

        

    实现这种效果并不难,也就是两个API,MSDN的文章将玻璃框扩展到 WPF 应用程序详细介绍了如何实现这种效果。在google上拿"C# DwmExtendFrameIntoClientArea"做关键字,也能搜到一大把。

    我一般是用的CodeProject的文章Adding Glass Effect to WPF using Attached Properties上所述的那样,通过依赖属性注入这种效果,只要在窗口中加一句话src:GlassEffect.IsEnabled="True"即可使能这种效果,用起来非常方便。通过这种方式实现起来的效果如下:

        

    看起来一起都非常简单,但这种方法只是仅仅实现了玻璃效果,还有几个不完善的地方:

    1. 这种方法只能实现全屏玻璃效果,不能实现部分玻璃效果。
    2. 实现玻璃效果后,我们往往还需要隐藏标题栏中的图标和文字。
    3. 那些玻璃化的部分不能像标题栏那样通过鼠标拖动窗口。

    因此,我将那个代码改动了一下,增加了上述功能,代码如下:  

    代码
        public class GlassInfo: System.Windows.Markup.MarkupExtension
        {
            
    public int TopMargin { getset; }
            
    public bool ShowIcon { getset; }
            
    public bool ShowTitle { getset; }

            
    public GlassInfo()
            {
                TopMargin 
    = -1;
                ShowIcon 
    = true;
                ShowTitle 
    = true;
            }

            
    public override object ProvideValue(IServiceProvider serviceProvider)
            {
                
    return this;
            }
        }
        
        
    public class GlassEffect
        {
            
    public static GlassInfo GetInfo(DependencyObject obj)
            {
                
    return (GlassInfo)obj.GetValue(InfoProperty);
            }

            
    public static void SetInfo(DependencyObject obj, GlassInfo value)
            {
                obj.SetValue(InfoProperty, value);
            }

            
    public static readonly DependencyProperty InfoProperty =
                DependencyProperty.RegisterAttached(
    "Info"typeof(GlassInfo), typeof(GlassEffect), new FrameworkPropertyMetadata(OnIsEnabledChanged));


            
    public static void OnIsEnabledChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
            {
                
    if (System.ComponentModel.DesignerProperties.GetIsInDesignMode(obj))
                    
    return;
                
                (obj 
    as Window).Loaded += (s, e) => ApplyGlassEffect(obj as Window, args.NewValue as GlassInfo);

                EnableMouseDrag(obj 
    as Window,(args.NewValue as GlassInfo).TopMargin);
            }

            
    static void ApplyGlassEffect(Window window, GlassInfo info)
            {
                
    if (!DwmIsCompositionEnabled())
                    
    return;

                var originalBackground 
    = window.Background;
                window.Background 
    = Brushes.Transparent;

                
    try
                {
                    IntPtr mainWindowPtr 
    = new WindowInteropHelper(window).Handle;
                    HwndSource mainWindowSrc 
    = HwndSource.FromHwnd(mainWindowPtr);
                    mainWindowSrc.CompositionTarget.BackgroundColor 
    = Color.FromArgb(0000);

                    var margins 
    = info.TopMargin == -1 ? new MARGINS(-1-1-1-1) : new MARGINS { Top = info.TopMargin };
                    DwmExtendFrameIntoClientArea(mainWindowPtr, 
    ref margins);

                    ApplyWindowThemeAttribute(info, mainWindowPtr);
                }
                
    catch (DllNotFoundException)
                {
                    window.Background 
    = originalBackground;
                }
            }

            
    static void ApplyWindowThemeAttribute(GlassInfo info, IntPtr mainWindowPtr)
            {
                WTA_OPTIONS ops 
    = new WTA_OPTIONS();

                
    // We Want To Hide the Caption and the Icon
                ops.Flags = WTNCA_NODRAWCAPTION | WTNCA_NODRAWICON | WTNCA_NOSYSMENU;

                
    // If we set the Mask to the same value as the Flags, the Flags are Added. If Not They are Removed
                if (!info.ShowTitle)
                {
                    ops.Mask 
    |= WTNCA_NODRAWCAPTION;
                }
                
    if (!info.ShowIcon)
                {
                    ops.Mask 
    |= WTNCA_NODRAWICON | WTNCA_NOSYSMENU;
                }

                
    // Set It, The Marshal.Sizeof() stuff is to get the right size of the custom struct, and in UINT/DWORD Form
                SetWindowThemeAttribute(mainWindowPtr, WindowThemeAttributeType.WTA_NONCLIENT,
                    
    ref ops, (uint)Marshal.SizeOf(typeof(WTA_OPTIONS)));
            }

            
    #region 设置任意位置拖动效果API
            
    const int WM_NCLBUTTONDOWN = 0xA1;
            
    const int HT_CAPTION = 0x2;

            [DllImportAttribute(
    "user32.dll")]
            
    static extern int SendMessage(IntPtr hWnd,
                             
    int Msg, int wParam, int lParam);
            [DllImportAttribute(
    "user32.dll")]
            
    static extern bool ReleaseCapture();

            
    static void EnableMouseDrag(Window window,int topMargin)
            {
                window.MouseLeftButtonDown 
    += (s, e) =>
                {
                    var win 
    = s as Window;

                    var point 
    = e.GetPosition(win);
                    
    if (point.Y > topMargin)
                        
    return;
                
                    Console.WriteLine(e.OriginalSource);
                    var mainWindowPtr 
    = new WindowInteropHelper(win).Handle;
                    ReleaseCapture();
                    SendMessage(mainWindowPtr, WM_NCLBUTTONDOWN, HT_CAPTION, 
    0);
                };
            }
            
    #endregion

            
    #region 设置玻璃效果API
            [StructLayout(LayoutKind.Sequential)]
            
    struct MARGINS
            {
                
    public int Left;
                
    public int Right;
                
    public int Top;
                
    public int Bottom;

                
    public MARGINS(int left,int right,int top,int bottom)
                {
                    
    this.Left = left;
                    
    this.Right = right;
                    
    this.Top = top;
                    
    this.Bottom = bottom;
                }

                
    public MARGINS(Thickness margin)
                {
                    
    this.Left = (int)margin.Left;
                    
    this.Right = (int)margin.Right;
                    
    this.Top = (int)margin.Top;
                    
    this.Bottom = (int)margin.Bottom;
                }
            };


            [DllImport(
    "DwmApi.dll")]
            
    static extern int DwmExtendFrameIntoClientArea(IntPtr hwnd, ref MARGINS pMarInset);

            [DllImport(
    "dwmapi.dll", PreserveSig = false)]
            
    static extern bool DwmIsCompositionEnabled();

            
    public static readonly DependencyProperty IsEnabledProperty =
                DependencyProperty.RegisterAttached(
    "IsEnabled",
                    
    typeof(Boolean),
                    
    typeof(GlassEffect),
                    
    new FrameworkPropertyMetadata(OnIsEnabledChanged)); 
            
    #endregion

            
    #region 设置标题栏属性

            
    /// <summary>
            
    /// Do Not Draw The Caption (Text)
            
    /// </summary>
            public static uint WTNCA_NODRAWCAPTION = 0x00000001;
            
    /// <summary>
            
    /// Do Not Draw the Icon
            
    /// </summary>
            public static uint WTNCA_NODRAWICON = 0x00000002;
            
    /// <summary>
            
    /// Do Not Show the System Menu
            
    /// </summary>
            public static uint WTNCA_NOSYSMENU = 0x00000004;
            
    /// <summary>
            
    /// Do Not Mirror the Question mark Symbol
            
    /// </summary>
            public static uint WTNCA_NOMIRRORHELP = 0x00000008;

            
    /// <summary>
            
    /// The Options of What Attributes to Add/Remove
            
    /// </summary>
            [StructLayout(LayoutKind.Sequential)]
            
    struct WTA_OPTIONS
            {
                
    public uint Flags;
                
    public uint Mask;
            }

            
    /// <summary>
            
    /// What Type of Attributes? (Only One is Currently Defined)
            
    /// </summary>
            enum WindowThemeAttributeType
            {
                WTA_NONCLIENT 
    = 1,
            };

            
    /// <summary>
            
    /// Set The Window's Theme Attributes
            
    /// </summary>
            
    /// <param name="hWnd">The Handle to the Window</param>
            
    /// <param name="wtype">What Type of Attributes</param>
            
    /// <param name="attributes">The Attributes to Add/Remove</param>
            
    /// <param name="size">The Size of the Attributes Struct</param>
            
    /// <returns>If The Call Was Successful or Not</returns>
            [DllImport("UxTheme.dll")]
            
    static extern int SetWindowThemeAttribute(IntPtr hWnd, WindowThemeAttributeType wtype, ref WTA_OPTIONS attributes, uint size); 
            
    #endregion

        }

    使用示例如下:

    <Window x:Class="WpfApplication.MainWindow"
        … …

        src:GlassEffect.Info="{util:GlassInfo TopMargin=32, ShowIcon=False, ShowTitle=False}">

    最终效果如下:

      

  • 相关阅读:
    信息安全系统设计基础第一次实验报告
    信息安全系统设计基础第十二周学习总结
    信息安全系统设计基础第十一周学习报告
    信息安全系统设计基础第十周学习报告
    信息安全系统设计基础第九周学习总结
    Arduino智能小车实践学习报告
    信息安全系统设计基础期中总结
    信息安全系统设计基础第七周学习总结
    信息安全系统设计基础第六周学习总结
    信息安全系统设计基础第五周学习总结
  • 原文地址:https://www.cnblogs.com/TianFang/p/1669275.html
Copyright © 2020-2023  润新知