첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.

728x90
반응형
728x170

TestProject.zip
다운로드

▶ AccentState.cs

namespace TestProject
{
    /// <summary>
    /// 강조 상태
    /// </summary>
    public enum AccentState
    {
        /// <summary>
        /// ACCENT_DISABLED
        /// </summary>
        ACCENT_DISABLED,

        /// <summary>
        /// ACCENT_ENABLE_GRADIENT
        /// </summary>
        ACCENT_ENABLE_GRADIENT,

        /// <summary>
        /// ACCENT_ENABLE_TRANSPARENTGRADIENT
        /// </summary>
        ACCENT_ENABLE_TRANSPARENTGRADIENT,

        /// <summary>
        /// ACCENT_ENABLE_BLURBEHIND
        /// </summary>
        ACCENT_ENABLE_BLURBEHIND,

        /// <summary>
        /// ACCENT_INVALID_STATE
        /// </summary>
        ACCENT_INVALID_STATE
    }
}

 

728x90

 

▶ AccentPolicy.cs

using System.Runtime.InteropServices;

namespace TestProject
{
    /// <summary>
    /// 강조 정책
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct AccentPolicy
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region Field

        /// <summary>
        /// 강조 상태
        /// </summary>
        public AccentState AccentState;

        /// <summary>
        /// 강조 플래그
        /// </summary>
        public int AccentFlag;

        /// <summary>
        /// 그라디언트 색상
        /// </summary>
        public int GradientColor;

        /// <summary>
        /// 애니메이션 ID
        /// </summary>
        public int AnimationID;

        #endregion
    }
}

 

300x250

 

▶ WindowCompositionAttribute.cs

namespace TestProject
{
    /// <summary>
    /// 윈도우 구성 특성
    /// </summary>
    public enum WindowCompositionAttribute
    {
        /// <summary>
        /// WCA_ACCENT_POLICY
        /// </summary>
        WCA_ACCENT_POLICY = 19
    }
}

 

▶ WindowCompositionAttributeData.cs

using System;
using System.Runtime.InteropServices;

namespace TestProject
{
    /// <summary>
    /// 윈도우 구성 특성 데이터
    /// </summary>
    [StructLayout(LayoutKind.Sequential)]
    public struct WindowCompositionAttributeData
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region Field

        /// <summary>
        /// 윈도우 구성 특성
        /// </summary>
        public WindowCompositionAttribute Attribute;

        /// <summary>
        /// 데이터
        /// </summary>
        public IntPtr Data;

        /// <summary>
        /// 데이터 크기
        /// </summary>
        public int DataSize;

        #endregion
    }
}

 

▶ WindowBlurHelper.cs

using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Interop;

namespace TestProject
{
    /// <summary>
    /// 윈도우 반투명 헬퍼
    /// </summary>
    public class WindowBlurHelper
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Static

        #region 윈도우 구성 특성 설정하기 - SetWindowCompositionAttribute(windowHandle, data)

        /// <summary>
        /// 윈도우 구성 특성 설정하기
        /// </summary>
        /// <param name="windowHandle">윈도우 핸들</param>
        /// <param name="data">데이터</param>
        /// <returns>처리 결과</returns>
        [DllImport("user32.dll")]
        private static extern int SetWindowCompositionAttribute(IntPtr windowHandle, ref WindowCompositionAttributeData data);

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Public

        #region Field

        /// <summary>
        /// 이용 가능 여부 속성
        /// </summary>
        public static readonly DependencyProperty IsEnabledProperty = DependencyProperty.RegisterAttached
        (
            "IsEnabled",
            typeof(bool),
            typeof(WindowBlurHelper),
            new PropertyMetadata(false, IsEnabledPropertyChangedCallback)
        );

        /// <summary>
        /// 윈도우 반투명 헬퍼 속성
        /// </summary>
        public static readonly DependencyProperty WindowBlurHelperProperty = DependencyProperty.RegisterAttached
        (
            "WindowBlurHelper",
            typeof(WindowBlurHelper),
            typeof(WindowBlurHelper),
            new PropertyMetadata(null, WindowBlurHelperPropertyChangedCallback));

        #endregion

        ////////////////////////////////////////////////////////////////////////////////////////// Instance
        //////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 윈도우
        /// </summary>
        private Window window;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Public

        #region 이용 가능 여부 설정하기 - SetIsEnabled(dependencyObject, value)

        /// <summary>
        /// 이용 가능 여부 설정하기
        /// </summary>
        /// <param name="dependencyObject">의존 객체</param>
        /// <param name="value">값</param>
        public static void SetIsEnabled(DependencyObject dependencyObject, bool value)
        {
            dependencyObject.SetValue(IsEnabledProperty, value);
        }

        #endregion
        #region 이용 가능 여부 구하기 - GetIsEnabled(dependencyObject)

        /// <summary>
        /// 이용 가능 여부 구하기
        /// </summary>
        /// <param name="dependencyObject">의존 객체</param>
        /// <returns>이용 가능 여부</returns>
        public static bool GetIsEnabled(DependencyObject dependencyObject)
        {
            return (bool)dependencyObject.GetValue(IsEnabledProperty);
        }

        #endregion

        #region 윈도우 반투명 헬퍼 설정하기 - SetWindowBlurHelper(dependencyObject, value)

        /// <summary>
        /// 윈도우 반투명 헬퍼 설정하기
        /// </summary>
        /// <param name="dependencyObject">의존 객체</param>
        /// <param name="value">값</param>
        public static void SetWindowBlurHelper(DependencyObject dependencyObject, WindowBlurHelper value)
        {
            dependencyObject.SetValue(WindowBlurHelperProperty, value);
        }

        #endregion
        #region 윈도우 반투명 헬퍼 구하기 - GetWindowBlurHelper(dependencyObject)

        /// <summary>
        /// 윈도우 반투명 헬퍼 구하기
        /// </summary>
        /// <param name="dependencyObject">의존 객체</param>
        /// <returns>윈도우 반투명 헬퍼</returns>
        public static WindowBlurHelper GetWindowBlurHelper(DependencyObject dependencyObject)
        {
            return (WindowBlurHelper)dependencyObject.GetValue(WindowBlurHelperProperty);
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////// Private

        #region 이용 가능 여부 속성 변경시 콜백 처리하기 - IsEnabledPropertyChangedCallback(dependencyObject, e)

        /// <summary>
        /// 이용 가능 여부 속성 변경시 콜백 처리하기
        /// </summary>
        /// <param name="dependencyObject">의존 객체</param>
        /// <param name="e">이벤트 인자</param>
        private static void IsEnabledPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            if(dependencyObject is Window window)
            {
                if(true.Equals(e.OldValue))
                {
                    GetWindowBlurHelper(window)?.Detach();

                    window.ClearValue(WindowBlurHelperProperty);
                }

                if(true.Equals(e.NewValue))
                {
                    WindowBlurHelper helper = new WindowBlurHelper();

                    helper.Attach(window);

                    window.SetValue(WindowBlurHelperProperty, helper);
                }
            }
        }

        #endregion
        #region 윈도우 반투명 헬퍼 속성 변경시 콜백 처리하기 - WindowBlurHelperPropertyChangedCallback(dependencyObject, e)

        /// <summary>
        /// 윈도우 반투명 헬퍼 속성 변경시 콜백 처리하기
        /// </summary>
        /// <param name="dependencyObject">의존 객체</param>
        /// <param name="e">이벤트 인자</param>
        private static void WindowBlurHelperPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            if(dependencyObject is Window window)
            {
                (e.OldValue as WindowBlurHelper)?.Detach();

                (e.NewValue as WindowBlurHelper)?.Attach(window);
            }
        }

        #endregion

        ////////////////////////////////////////////////////////////////////////////////////////// Instance
        //////////////////////////////////////////////////////////////////////////////// Private
        ////////////////////////////////////////////////////////////////////// Event

        #region 윈도우 소스 초기화시 처리하기 - window_SourceInitialized(sender, e)

        /// <summary>
        /// 윈도우 소스 초기화시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void window_SourceInitialized(object sender, EventArgs e)
        {
            ((Window)sender).SourceInitialized -= window_SourceInitialized;

            AttachCore();
        }

        #endregion

        ////////////////////////////////////////////////////////////////////// Function

        #region 반투명 이용 가능 여부 설정하기 - EnableBlur(window)

        /// <summary>
        /// 반투명 이용 가능 여부 설정하기
        /// </summary>
        /// <param name="window">윈도우</param>
        private static void EnableBlur(Window window)
        {
            WindowInteropHelper helper = new WindowInteropHelper(window);

            AccentPolicy accentPolicy = new AccentPolicy
            {
                AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND
            };

            int accentPolicySize = Marshal.SizeOf(accentPolicy);

            IntPtr accentPolicyHandle = Marshal.AllocHGlobal(accentPolicySize);

            Marshal.StructureToPtr(accentPolicy, accentPolicyHandle, false);

            WindowCompositionAttributeData data = new WindowCompositionAttributeData
            {
                Attribute = WindowCompositionAttribute.WCA_ACCENT_POLICY,
                DataSize  = accentPolicySize,
                Data      = accentPolicyHandle
            };

            SetWindowCompositionAttribute(helper.Handle, ref data);

            Marshal.FreeHGlobal(accentPolicyHandle);
        }

        #endregion

        #region 첨부하기 (코어) - AttachCore()

        /// <summary>
        /// 첨부하기 (코어)
        /// </summary>
        private void AttachCore()
        {
            EnableBlur(this.window);
        }

        #endregion
        #region 분리하기 (코어) - DetachCore()

        /// <summary>
        /// 분리하기 (코어)
        /// </summary>
        private void DetachCore()
        {
            this.window.SourceInitialized += window_SourceInitialized;
        }

        #endregion

        #region 첨부하기 - Attach(window)

        /// <summary>
        /// 첨부하기
        /// </summary>
        /// <param name="window">윈도우</param>
        private void Attach(Window window)
        {
            this.window = window;

            HwndSource source = PresentationSource.FromVisual(window) as HwndSource;

            if(source == null)
            {
                window.SourceInitialized += window_SourceInitialized;
            }
            else
            {
                AttachCore();
            }
        }

        #endregion
        #region 분리하기 - Detach()

        /// <summary>
        /// 분리하기
        /// </summary>
        private void Detach()
        {
            try
            {
                DetachCore();
            }
            finally
            {
                this.window = null;
            }
        }

        #endregion
    }
}

 

▶ MainWindow.xaml

<Window x:Class="TestProject.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    WindowStartupLocation="CenterScreen"
    Width="800"
    Height="600"
    WindowStyle="None"
    AllowsTransparency="True"
    BorderThickness="1"
    BorderBrush="Black"
    Background="#12000000"
    FontFamily="나눔고딕코딩"
    FontSize="16">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*"    />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        <TextBlock Grid.Row="0"
            HorizontalAlignment="Left"
            VerticalAlignment="Center"
            Margin="5"
            Foreground="RoyalBlue">
            반투명 윈도우 사용하기
        </TextBlock>
        <Button Name="closeButton" Grid.Row="2"
            HorizontalAlignment="Right"
            VerticalAlignment="Center"
            Margin="5"
            Width="100"
            Height="30"
            Content="종료" />
    </Grid>
</Window>

 

▶ MainWindow.xaml.cs

using System.Windows;

namespace TestProject
{
    /// <summary>
    /// 메인 윈도우
    /// </summary>
    public partial class MainWindow : Window
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - MainWindow()

        /// <summary>
        /// 생성자
        /// </summary>
        public MainWindow()
        {
            InitializeComponent();

            Loaded                 += Window_Loaded;
            this.closeButton.Click += closeButton_Click;
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region 윈도우 로드시 처리하기 - Window_Loaded(sender, e)

        /// <summary>
        /// 윈도우 로드시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            WindowBlurHelper.SetIsEnabled(this, true);
        }

        #endregion
        #region 종료 버튼 클릭시 처리하기 - closeButton_Click(sender, e)

        /// <summary>
        /// 종료 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void closeButton_Click(object sender, RoutedEventArgs e)
        {
            Close();
        }

        #endregion
    }
}
728x90
반응형
그리드형(광고전용)
Posted by icodebroker

댓글을 달아 주세요