첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
728x90
반응형
728x170

TestProject.zip
0.02MB

▶ 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

 

▶ DWMWINDOWATTRIBUTE.cs

namespace TestProject
{
    /// <summary>
    /// DWM 윈도우 어트리뷰트
    /// </summary>
    public enum DWMWINDOWATTRIBUTE : uint
    {
        /// <summary>
        /// NCRenderingEnabled
        /// </summary>
        NCRenderingEnabled = 1,

        /// <summary>
        /// NCRenderingPolicy
        /// </summary>
        NCRenderingPolicy,

        /// <summary>
        /// TransitionsForceDisabled
        /// </summary>
        TransitionsForceDisabled,

        /// <summary>
        /// AllowNCPaint
        /// </summary>
        AllowNCPaint,

        /// <summary>
        /// CaptionButtonBounds
        /// </summary>
        CaptionButtonBounds,

        /// <summary>
        /// NonClientRtlLayout
        /// </summary>
        NonClientRtlLayout,

        /// <summary>
        /// ForceIconicRepresentation
        /// </summary>
        ForceIconicRepresentation,

        /// <summary>
        /// Flip3DPolicy
        /// </summary>
        Flip3DPolicy,

        /// <summary>
        /// ExtendedFrameBounds
        /// </summary>
        ExtendedFrameBounds,

        /// <summary>
        /// HasIconicBitmap
        /// </summary>
        HasIconicBitmap,

        /// <summary>
        /// DisallowPeek
        /// </summary>
        DisallowPeek,

        /// <summary>
        /// ExcludedFromPeek
        /// </summary>
        ExcludedFromPeek,

        /// <summary>
        /// Cloak
        /// </summary>
        Cloak,

        /// <summary>
        /// Cloaked
        /// </summary>
        Cloaked,

        /// <summary>
        /// FreezeRepresentation
        /// </summary>
        FreezeRepresentation
    }
}

 

300x250

 

▶ WindowCompositionAttribute.cs

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

 

▶ 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
    }
}

 

▶ POINT.cs

namespace TestProject
{
    /// <summary>
    /// 포인트
    /// </summary>
    public struct POINT
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region Field

        /// <summary>
        /// X 좌표
        /// </summary>
        public int X;

        /// <summary>
        /// Y 좌표
        /// </summary>
        public int Y;

        #endregion
    }
}

 

▶ 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
    }
}

 

▶ BlockWindow.xaml

<Window x:Class="TestProject.BlockWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="800"
    Height="600"
    FontFamily="나눔고딕코딩"
    FontSize="16">
    <Grid>
        <StackPanel
            HorizontalAlignment="Center"
            VerticalAlignment="Center">
            <TextBlock Name="headerTextBlock"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                Foreground="Red"
                FontWeight="Bold"
                FontStretch="Expanded"
                FontSize="30"
                Text="" />
            <TextBlock Name="messageTextBlock"
                HorizontalAlignment="Center"
                VerticalAlignment="Center"
                Margin="0 10 0 0"
                Foreground="Blue"
                FontSize="20"
                Text="" />
        </StackPanel>
        <Button Name="returnButton"
            Margin="20"
            HorizontalAlignment="Right"
            VerticalAlignment="Bottom"
            Width="100"
            Height="30"
            Content="Return" />
    </Grid>
</Window>

 

▶ WallWindow.xaml.cs

using System;
using System.IO;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Markup;
using System.Xml;

namespace TestProject
{
    /// <summary>
    /// 블럭 윈도우
    /// </summary>
    public partial class BlockWindow : Window
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 최초 활성화 여부
        /// </summary>
        private bool firstActivated = true;

        /// <summary>
        /// 헤더
        /// </summary>
        private string header = null;

        /// <summary>
        /// 헤더 스팬
        /// </summary>
        private Span headerSpan = null;

        /// <summary>
        /// 메시지
        /// </summary>
        private string message = null;

        /// <summary>
        /// 메시지 스팬
        /// </summary>
        private Span messageSpan = null;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 헤더 - Header

        /// <summary>
        /// 헤더
        /// </summary>
        public string Header
        {
            get
            {
                return this.header;
            }
            set
            {
                this.header = value;

                this.headerSpan = GetSpan(this.header);

                SetTextBlock(this.headerTextBlock, this.header, this.headerSpan);
            }
        }

        #endregion
        #region 메시지 - Message

        /// <summary>
        /// 메시지
        /// </summary>
        public string Message
        {
            get
            {
                return this.message;
            }
            set
            {
                this.message = value;

                this.messageSpan = GetSpan(this.message);

                SetTextBlock(this.messageTextBlock, this.message, this.messageSpan);
            }
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public
        
        #region 생성자 - BlockWindow()

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

            Activated               += Window_Activated;
            this.returnButton.Click += returnButton_Click;
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method
        ////////////////////////////////////////////////////////////////////////////////////////// Private
        //////////////////////////////////////////////////////////////////////////////// Event

        #region 윈도우 활성화시 처리하기 - Window_Activated(sender, e)

        /// <summary>
        /// 윈도우 활성화시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void Window_Activated(object sender, EventArgs e)
        {
            if(this.firstActivated)
            {
                this.firstActivated = false;

                return;
            }

            if(WindowHelper.IsLocked)
            {
                if(WindowHelper.ScreenCount != System.Windows.Forms.Screen.AllScreens.Length)
                {
                    WindowHelper.CloseBlockWindows();

                    WindowHelper.ShowBlockWindows();
                }

#if DEBUG
                WindowHelper.ShowCursor();
#else
                WindowsHelper.DisableInput();

                WindowsHelper.HideCursor();
#endif
            }
        }

        #endregion
        #region Return 버튼 클릭시 처리하기 - returnButton_Click(sender, e)

        /// <summary>
        /// Return 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void returnButton_Click(object sender, RoutedEventArgs e)
        {
            WindowHelper.UnlockScreen();

        }

        #endregion

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

        #region XAML 구하기 - GetXAML(source)

        /// <summary>
        /// XAML 구하기
        /// </summary>
        /// <param name="source">소스 객체</param>
        /// <returns>XAML</returns>
        private string GetXAML(object source)
        {
            XmlWriterSettings setting = new XmlWriterSettings();

            setting.Indent              = true;
            setting.IndentChars         = new string(' ', 4);
            setting.NewLineOnAttributes = true;
            setting.OmitXmlDeclaration  = true;

            StringBuilder stringBuilder = new StringBuilder();

            XmlWriter writer = XmlWriter.Create(stringBuilder, setting);

            XamlWriter.Save(source, writer);

            return stringBuilder.ToString();
        }

        #endregion
        #region 객체 구하기 - GetObject<T>(reader)

        /// <summary>
        /// 객체 구하기
        /// </summary>
        /// <typeparam name="T">객체 타입</typeparam>
        /// <param name="reader">XML 텍스트 리더</param>
        /// <returns>객체</returns>
        private T GetObject<T>(XmlTextReader reader)
        {
            return (T)(XamlReader.Load(reader));
        }

        #endregion
        #region 객체 구하기 - GetObject<T>(xaml)

        /// <summary>
        /// 객체 구하기
        /// </summary>
        /// <typeparam name="T">객체 타입</typeparam>
        /// <param name="xaml">XAML</param>
        /// <returns>객체</returns>
        private T GetObject<T>(string xaml)
        {
            StringReader stringReader = new StringReader(xaml);

            XmlTextReader xmlTextReader = new XmlTextReader(stringReader);

            return GetObject<T>(xmlTextReader);
        }

        #endregion
        #region SPAN 객체 구하기 - GetSpan(text)

        /// <summary>
        /// SPAN 객체 구하기
        /// </summary>
        /// <param name="text">텍스트</param>
        /// <returns>SPAN 객체</returns>
        private Span GetSpan(string text)
        {
            string xaml = "<Span xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\">" +
                          text?.Replace("\r\n", "<LineBreak />").Replace("\n", "<LineBreak />")        +
                          "</Span>";

            Span span = null;

            try
            {
                span = GetObject<Span>(xaml);
            }
            catch
            {
            }

            return span;
        }

        #endregion
        #region 텍스트 블럭 설정하기 - SetTextBlock(textBlock, message, span)

        /// <summary>
        /// 텍스트 블럭 설정하기
        /// </summary>
        /// <param name="textBlock">텍스트 블럭</param>
        /// <param name="message">메시지</param>
        /// <param name="span">SPAN 객체</param>
        private void SetTextBlock(TextBlock textBlock, string message, Span span)
        {
            if(span == null)
            {
                textBlock.Text = message;
            }
            else
            {
                textBlock.Inlines.Clear();

                if(span != null)
                {
                    textBlock.Inlines.Add(span);
                }
            }
        }

        #endregion
    }
}

 

▶ WindowsHelper.cs

using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;

namespace TestProject
{
    /// <summary>
    /// 윈도우 헬퍼
    /// </summary>
    public class WindowHelper
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Structure
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region 키보드 저수준 후킹 구조체 - KBDLLHOOKSTRUCT

        /// <summary>
        /// 키보드 저수준 후킹 구조체
        /// </summary>
        private struct KBDLLHOOKSTRUCT
        {
            //////////////////////////////////////////////////////////////////////////////////////////////////// Field
            ////////////////////////////////////////////////////////////////////////////////////////// Public

            #region Field

            /// <summary>
            /// 가상 키 코드
            /// </summary>
            public int VirtualKeyCode;

            /// <summary>
            /// 스캔 코드
            /// </summary>
            public int ScanCode;

            /// <summary>
            /// 플래그
            /// </summary>
            public int Flags;

            /// <summary>
            /// 시간
            /// </summary>
            public int Time;

            /// <summary>
            /// 부가 정보
            /// </summary>
            public int ExtraInfo;

            #endregion
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Delegate
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region 키보드 후킹 처리 대리자 - ProcessKeyboardHookDelegate(code, wordParameter, longParameter)

        /// <summary>
        /// 키보드 후킹 처리 대리자
        /// </summary>
        /// <param name="code">코드</param>
        /// <param name="wordParameter">WORD 매개 변수</param>
        /// <param name="longParameter">LONG 매개 변수</param>
        /// <returns>처리 결과</returns>
        private delegate int ProcessKeyboardHookDelegate(int code, int wordParameter, ref KBDLLHOOKSTRUCT longParameter);

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Import
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Private

        #region 윈도우 후킹 설정하기 - SetWindowsHookEx(hookID, processKeyboardHookDelegate, moduleHandle, threadID)

        /// <summary>
        /// 윈도우 후킹 설정하기
        /// </summary>
        /// <param name="hookID">후킹 ID</param>
        /// <param name="processKeyboardHookDelegate">키보드 후킹 처리 대리자</param>
        /// <param name="moduleHandle">모듈 핸들</param>
        /// <param name="threadID">스레드 ID</param>
        /// <returns>처리 결과</returns>
        [DllImport("user32", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int SetWindowsHookEx
        (
            int                         hookID,
            ProcessKeyboardHookDelegate processKeyboardHookDelegate,
            IntPtr                      moduleHandle,
            uint                        threadID
        );

        #endregion
        #region 윈도우 후킹 해제하기 - UnhookWindowsHookEx(hookHandle)

        /// <summary>
        /// 윈도우 후킹 해제하기
        /// </summary>
        /// <param name="hookHandle">후킹 핸들</param>
        /// <returns>처리 결과</returns>
        [DllImport("user32", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool UnhookWindowsHookEx(int hookHandle);

        #endregion
        #region 다음 후킹 호출하기 - CallNextHookEx(hookHandle, code, wordParameter, longParameter)

        /// <summary>
        /// 다음 후킹 호출하기
        /// </summary>
        /// <param name="hookHandle">후킹 핸들</param>
        /// <param name="code">코드</param>
        /// <param name="wordParameter">WORD 매개 변수</param>
        /// <param name="longParameter">LONG 매개 변수</param>
        /// <returns>처리 결과</returns>
        [DllImport("user32", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int CallNextHookEx(int hookHandle, int code, int wordParameter, ref KBDLLHOOKSTRUCT longParameter);

        #endregion
        #region 모듈 핸들 구하기 - GetModuleHandle(modulName)

        /// <summary>
        /// 모듈 핸들 구하기
        /// </summary>
        /// <param name="modulName">모듈명</param>
        /// <returns>모듈 핸들</returns>
        [DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern IntPtr GetModuleHandle(string modulName);

        #endregion
        #region 입력 방지하기 - BlockInput(blocking)

        /// <summary>
        /// 입력 방지하기
        /// </summary>
        /// <param name="blocking">입력 방지 여부</param>
        /// <returns>처리 결과</returns>
        [return: MarshalAs(UnmanagedType.Bool)]
        [DllImport("user32", CharSet = CharSet.Auto, ExactSpelling = true)]
        private static extern bool BlockInput([In, MarshalAs(UnmanagedType.Bool)]bool blocking);

        #endregion
        #region 커서 표시하기 - ShowCursor(show)

        /// <summary>
        /// 커서 표시하기
        /// </summary>
        /// <param name="show">표시 여부</param>
        /// <returns>디스플레이 카운트</returns>
        [DllImport("user32")]
        private static extern int ShowCursor(bool show);

        #endregion
        #region 윈도우 찾기 (확장) - FindWindowEx(parentWindowHandle, childAfterWindowHandle, className, windowText)

        /// <summary>
        /// 윈도우 찾기 (확장)
        /// </summary>
        /// <param name="parentWindowHandle">부모 윈도우 핸들</param>
        /// <param name="childAfterWindowHandle">찾기 이후 자식 윈도우 핸들</param>
        /// <param name="className">클래스명</param>
        /// <param name="windowText">윈도우 텍스트</param>
        /// <returns>윈도우 핸들</returns>
        [DllImport("user32")]
        private static extern IntPtr FindWindowEx
        (
            IntPtr parentWindowHandle,
            IntPtr childAfterWindowHandle,
            string className,
            string windowText
        );

        #endregion
        #region 윈도우 표시 여부 구하기 - IsWindowVisible(windowHandle)

        /// <summary>
        /// 윈도우 표시 여부 구하기
        /// </summary>
        /// <param name="windowHandle">윈도우 핸들</param>
        /// <returns>윈도우 표시 여부</returns>
        [DllImport("user32")]
        private static extern bool IsWindowVisible(IntPtr windowHandle);

        #endregion
        #region 윈도우 최소화 여부 구하기 - IsIconic(windowHandle)

        /// <summary>
        /// 윈도우 최소화 여부 구하기
        /// </summary>
        /// <param name="windowHandle">윈도우 핸들</param>
        /// <returns>윈도우 최소화 여부</returns>
        [DllImport("user32")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool IsIconic(IntPtr windowHandle);

        #endregion
        #region 윈도우 표시하기 (비동기) - ShowWindowAsync(windowHandle, command)

        /// <summary>
        /// 윈도우 표시하기 (비동기)
        /// </summary>
        /// <param name="windowHandle">윈도우 핸들</param>
        /// <param name="command">명령</param>
        /// <returns>처리 결과</returns>
        [DllImport("user32")]
        private static extern bool ShowWindowAsync(IntPtr windowHandle, int command);

        #endregion
        #region 전경 윈도우 구하기 - GetForegroundWindow()

        /// <summary>
        /// 전경 윈도우 구하기
        /// </summary>
        /// <returns>윈도우 핸들</returns>
        [DllImport("user32")]
        private static extern IntPtr GetForegroundWindow();

        #endregion
        #region 클래스명 구하기 - GetClassName(windowHandle, classNameStringBuilder, maximumCount)

        /// <summary>
        /// 클래스명 구하기
        /// </summary>
        /// <param name="windowHandle">윈도우 핸들</param>
        /// <param name="classNameStringBuilder">클래스명 문자열 빌더</param>
        /// <param name="maximumCount">최대 카운트</param>
        /// <returns>처리 결과</returns>
        [DllImport("user32")]
        private static extern int GetClassName(IntPtr windowHandle, StringBuilder classNameStringBuilder, int maximumCount);

        #endregion
        #region 윈도우 텍스트 구하기 - GetWindowText(windowHandle, windowTextStringBuilder, maximumCount)

        /// <summary>
        /// 윈도우 텍스트 구하기
        /// </summary>
        /// <param name="windowHandle">윈도우 핸들</param>
        /// <param name="windowTextStringBuilder">윈도우 텍스트 문자열 빌더</param>
        /// <param name="maximumCount">최대 카운트</param>
        /// <returns>윈도우 텍스트</returns>
        [DllImport("user32.dll")]
        private static extern int GetWindowText(IntPtr windowHandle, StringBuilder windowTextStringBuilder, int maximumCount);

        #endregion
        #region DWM 윈도우 어트리뷰트 구하기 - DwmGetWindowAttribute(windowHandle, attribute, value, valueSize)

        /// <summary>
        /// DWM 윈도우 어트리뷰트 구하기
        /// </summary>
        /// <param name="windowHandle">윈도우 핸들</param>
        /// <param name="attribute">어트리뷰트</param>
        /// <param name="value">값</param>
        /// <param name="valueSize">값 크기</param>
        /// <returns>처리 결과</returns>
        [DllImport("dwmapi")]
        private static extern int DwmGetWindowAttribute(IntPtr windowHandle, DWMWINDOWATTRIBUTE attribute, out bool value, int valueSize);

        #endregion
        #region 전경 윈도우 설정하기 - SetForegroundWindow(windowHandle)

        /// <summary>
        /// 전경 윈도우 설정하기
        /// </summary>
        /// <param name="windowHandle">윈도우 핸들</param>
        /// <returns>처리 결과</returns>
        [DllImport("user32")]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool SetForegroundWindow(IntPtr windowHandle);

        #endregion
        #region 데스크톱 윈도우 구하기 - GetDesktopWindow()

        /// <summary>
        /// 데스크톱 윈도우 구하기
        /// </summary>
        /// <returns>데스크톱 윈도우 핸들</returns>
        [DllImport("user32")]
        private static extern IntPtr GetDesktopWindow();

        #endregion
        #region 커서 위치 구하기 - GetCursorPos(point)

        /// <summary>
        /// 커서 위치 구하기
        /// </summary>
        /// <param name="point">포인트</param>
        /// <returns>처리 결과</returns>
        [DllImport("user32")]
        private static extern int GetCursorPos(out POINT point);

        #endregion
        #region 커서 위치 설정하기 - SetCursorPos(x, y)

        /// <summary>
        /// 커서 위치 설정하기
        /// </summary>
        /// <param name="x">X 좌표</param>
        /// <param name="y">Y 좌표</param>
        /// <returns>처리 결과</returns>
        [DllImport("user32")]
        private static extern bool SetCursorPos(int x, int y);

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// 키보드 후킹 처리 대리자
        /// </summary>
        private static ProcessKeyboardHookDelegate _processKeyboardHookDelegate = ProcessKeyboardHook;

        /// <summary>
        /// 후킹 ID
        /// </summary>
        private static int _hookID = 0;

        /// <summary>
        /// 태스크 관리자 이용 가능 여부
        /// </summary>
        private static bool _taskManagerEnabled = true;

        /// <summary>
        /// 특수 키보드 입력 이용 가능 여부
        /// </summary>
        private static bool _specialKeyboardInputEnabled = true;

        /// <summary>
        /// 잠금 여부
        /// </summary>
        private static bool _isLocked = false;

        /// <summary>
        /// 화면 리스트
        /// </summary>
        private static List<System.Windows.Forms.Screen> _screenList = null;

        /// <summary>
        /// 벽 윈도우 리스트
        /// </summary>
        private static List<BlockWindow> _windowList = null;

        /// <summary>
        /// 화면 카운트
        /// </summary>
        private static int _screenCount = 0; 

        /// <summary>
        /// UWP 윈도우 핸들 리스트
        /// </summary>
        private static List<IntPtr> _uwpWindowHandleList = null;

        /// <summary>
        /// 헤더
        /// </summary>
        private static string _header = null;

        /// <summary>
        /// 메시지
        /// </summary>
        private static string _message = null;

        /// <summary>
        /// 커서 포인트
        /// </summary>
        private static POINT _cursorPoint;

        /// <summary>
        /// 배경 브러시
        /// </summary>
        private static SolidColorBrush _backgroundBrush;

        #endregion

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

        #region Field

        /// <summary>
        /// WH_KEYBOARD_LL
        /// </summary>
        private const int WH_KEYBOARD_LL = 13;

        /// <summary>
        /// WM_KEYDOWN
        /// </summary>
        private const int WM_KEYDOWN = 0x0100;

        /// <summary>
        /// WM_KEYUP
        /// </summary>
        private const int WM_KEYUP = 0x0101;

        /// <summary>
        /// WM_SYSKEYDOWN
        /// </summary>
        private const int WM_SYSKEYDOWN = 0x0104;

        /// <summary>
        /// WM_SYSKEYUP
        /// </summary>
        private const int WM_SYSKEYUP = 0x0105;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Public

        #region 화면 카운트 - ScreenCount

        /// <summary>
        /// 화면 카운트
        /// </summary>
        public static int ScreenCount
        {
            get
            {
                return _screenCount;
            }
        }

        #endregion
        #region 잠금 여부 - IsLocked

        /// <summary>
        /// 잠금 여부
        /// </summary>
        public static bool IsLocked
        {
            get
            {
                return _isLocked;
            }
        }

        #endregion

        #region 헤더 - Header

        /// <summary>
        /// 헤더
        /// </summary>
        public static string Header
        {
            get
            {
                return _header;
            }
            set
            {
                _header = value;

                if(IsLocked)
                {
                    try
                    {
                        foreach(BlockWindow window in _windowList)
                        {
                            window.Header = _header;
                        }
                    }
                    catch
                    {
                    }
                }
            }
        }

        #endregion
        #region 디스패처 헤더 - DispatcherHeader

        /// <summary>
        /// 디스패처 헤더
        /// </summary>
        public static string DispatcherHeader
        {
            get
            {
                return _header;
            }
            set
            {
                _header = value;

                if(IsLocked)
                {
                    try
                    {
                        foreach(BlockWindow window in _windowList)
                        {
                            window.Header = _header;

                            window.headerTextBlock.Dispatcher.Invoke((ThreadStart)(() => { }), DispatcherPriority.ApplicationIdle);
                        }
                    }
                    catch
                    {
                    }
                }
            }
        }

        #endregion
        #region 메시지 - Message

        /// <summary>
        /// 메시지
        /// </summary>
        public static string Message
        {
            get
            {
                return _message;
            }
            set
            {
                _message = value;

                if(IsLocked)
                {
                    try
                    {
                        foreach(BlockWindow window in _windowList)
                        {
                            window.Message = _message;
                        }
                    }
                    catch
                    {
                    }
                }
            }
        }

        #endregion
        #region 디스패처 메시지 - DispatcherMessage

        /// <summary>
        /// 디스패처 메시지
        /// </summary>
        public static string DispatcherMessage
        {
            get
            {
                return _message;
            }
            set
            {
                _message = value;

                if(IsLocked)
                {
                    try
                    {
                        foreach(BlockWindow window in _windowList)
                        {
                            window.Message = _message;

                            window.messageTextBlock.Dispatcher.Invoke((ThreadStart)(() => { }), DispatcherPriority.ApplicationIdle);
                        }
                    }
                    catch
                    {
                    }
                }
            }
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Static

        #region 생성자 - WindowsHelper()

        /// <summary>
        /// 생성자
        /// </summary>
        static WindowHelper()
        {
            SystemEvents.DisplaySettingsChanged += systemEvents_DisplaySettingsChanged;

            _backgroundBrush = new SolidColorBrush(Color.FromArgb(18, 0, 0, 0));

            _backgroundBrush.Freeze();
        }

        #endregion

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

        #region 시스템 윈도우 숨기기 - HideSystemWindow()

        /// <summary>
        /// 시스템 윈도우 숨기기
        /// </summary>
        public static void HideSystemWindow()
        {
            IntPtr foregroundWindowHandle = GetForegroundWindow();

            if(foregroundWindowHandle == IntPtr.Zero)
            {
                return;
            }

            StringBuilder classNameStringBuilder = new StringBuilder(100);

            GetClassName(foregroundWindowHandle, classNameStringBuilder, 100);

            string className = classNameStringBuilder.ToString();

            if(className == "Windows.UI.Core.CoreWindow")
            {
                StringBuilder windowTextStringBuilder = new StringBuilder(100);

                GetWindowText(foregroundWindowHandle, windowTextStringBuilder, 100);

                string windowText = windowTextStringBuilder.ToString();

                if(windowText == "작업 보기" || windowText == "Task View")
                {
                    System.Windows.Forms.SendKeys.SendWait("{ESC}");
                }
                else
                {
                    System.Windows.Forms.SendKeys.SendWait("{ESC}");

                    SetForegroundWindow(GetDesktopWindow());
                }
            }
            else // Shell_TrayWnd, Shell_SecondaryTrayWnd, LauncherTipWnd, HwndWrapper[
            {
                System.Windows.Forms.SendKeys.SendWait("{ESC}");

                SetForegroundWindow(GetDesktopWindow());
            }
        }

        #endregion

        #region UWP 애플리케이션 최소화하기 - MinimizeUWPApplications()

        /// <summary>
        /// UWP 애플리케이션 최소화하기
        /// </summary>
        public static void MinimizeUWPApplications()
        {
            if(_uwpWindowHandleList == null)
            {
                _uwpWindowHandleList = new List<IntPtr>();
            }
            else
            {
                _uwpWindowHandleList.Clear();
            }

            IntPtr windowHandle = IntPtr.Zero;

            do
            {
                windowHandle = FindWindowEx(IntPtr.Zero, windowHandle, "ApplicationFrameWindow", null);

                if(windowHandle == IntPtr.Zero)
                {
                    break;
                }

                if(!IsWindowVisible(windowHandle))
                {
                    continue;
                }

                if(IsIconic(windowHandle))
                {
                    continue;
                }

                DwmGetWindowAttribute(windowHandle, DWMWINDOWATTRIBUTE.Cloaked, out bool isCloacked, Marshal.SizeOf(typeof(bool)));

                if(isCloacked)
                {
                    continue;
                }

                _uwpWindowHandleList.Add(windowHandle);

                ShowWindowAsync(windowHandle, 6); // SW_MINIMIZE
            }
            while(true);
        }

        #endregion
        #region UWP 애플리케이션 복원하기 - RestoreUWPApplications()

        /// <summary>
        /// UWP 애플리케이션 복원하기
        /// </summary>
        public static void RestoreUWPApplications()
        {
            if(_uwpWindowHandleList == null)
            {
                return;
            }

            foreach(IntPtr windowHandle in _uwpWindowHandleList)
            {
                ShowWindowAsync(windowHandle, 9); // SW_RESTORE
            }

            _uwpWindowHandleList.Clear();
        }

        #endregion

        #region 커서 숨기기 - HideCursor()

        /// <summary>
        /// 커서 숨기기
        /// </summary>
        public static void HideCursor()
        {
            while(ShowCursor(false) >= 0)
            {
                ShowCursor(false);
            }
        }

        #endregion
        #region 커서 보여주기 - ShowCursor()

        /// <summary>
        /// 커서 보여주기
        /// </summary>
        public static void ShowCursor()
        {
            while(ShowCursor(true) < 0)
            {
                ShowCursor(true);
            }
        }

        #endregion

        #region 태스크 관리자 비활성화 하기 - DisableTaskManager()

        /// <summary>
        /// 태스크 관리자 비활성화 하기
        /// </summary>
        /// <remarks>Ctrl + Alt + Delete 키 입력을 거부한다.</remarks>
        public static void DisableTaskManager()
        {
            //if(!_taskManagerEnabled)
            //{
            //    return;
            //}
            //
            //RegistryKey registryKey;
            //int         keyValue = 1;
            //string      subKey   = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System";
            //
            //registryKey = Registry.CurrentUser.CreateSubKey(subKey);
            //
            //registryKey.SetValue("DisableTaskMgr", keyValue);
            //
            //registryKey.Close();
            //
            //_taskManagerEnabled = false;
        }

        #endregion
        #region 태스크 관리자 활성화 하기 - EnableTaskManager()

        /// <summary>
        /// 태스크 관리자 활성화 하기
        /// </summary>
        /// <remarks>Ctrl + Alt + Delete 키 입력을 허용한다.</remarks>
        public static void EnableTaskManager()
        {
            //if(_taskManagerEnabled)
            //{
            //    return;
            //}
            //
            //RegistryKey currentUserRegistryKey = Registry.CurrentUser;
            //string      subKey                 = "Software\\Microsoft\\Windows\\CurrentVersion\\Policies\\System";
            //RegistryKey registryKey            = currentUserRegistryKey.OpenSubKey(subKey);
            //
            //if(registryKey != null)
            //{
            //    currentUserRegistryKey.DeleteSubKeyTree(subKey);
            //}
            //
            //_taskManagerEnabled = true;
        }

        #endregion

        #region 특수 키보드 입력 비활성 화기 - DisableSpecialKeyboardInput()

        /// <summary>
        /// 특수 키보드 입력 비활성 화기
        /// </summary>
        public static void DisableSpecialKeyboardInput()
        {
            if(!_specialKeyboardInputEnabled)
            {
                return;
            }

            _hookID = SetHook(_processKeyboardHookDelegate);

            _specialKeyboardInputEnabled = false;
        }

        #endregion
        #region 특수 키보드 입력 활성화 하기 - EnableSpecialKeyboardInput()

        /// <summary>
        /// 특수 키보드 입력 활성화 하기
        /// </summary>
        public static void EnableSpecialKeyboardInput()
        {
            if(_specialKeyboardInputEnabled)
            {
                return;
            }

            UnhookWindowsHookEx(_hookID);

            _specialKeyboardInputEnabled = true;
        }

        #endregion

        #region 입력 비활성화 하기 - DisableInput()

        /// <summary>
        /// 입력 비활성화 하기
        /// </summary>
        /// <returns>처리 결과</returns>
        public static bool DisableInput()
        {
            return BlockInput(true);
        }

        #endregion
        #region 입력 활성화 하기 - EnableInput()

        /// <summary>
        /// 입력 활성화 하기
        /// </summary>
        /// <returns>처리 결과</returns>
        public static bool EnableInput()
        {
            return BlockInput(false);
        }

        #endregion

        #region 블럭 윈도우 보여주기 - ShowBlockWindows()

        /// <summary>
        /// 블럭 윈도우 보여주기
        /// </summary>
        public static void ShowBlockWindows()
        {
            _screenList = System.Windows.Forms.Screen.AllScreens.ToList();

            _screenCount = _screenList.Count;

            if(_windowList == null)
            {
                _windowList = new List<BlockWindow>();
            }

            int count = _screenList.Count - _windowList.Count;

            if(count > 0)
            {
                for(int i = 0; i < count; i++)
                {
                    _windowList.Add(new BlockWindow());
                }
            }

            for(int i = 0; i < _screenList.Count; i++)
            {
                BlockWindow window = _windowList[i];

                window.Header  = _header;
                window.Message = _message;

                window.WindowStyle        = WindowStyle.None;
                window.ShowInTaskbar      = false;
                window.AllowsTransparency = true;
                window.Background         = _backgroundBrush;

                WindowBlurHelper.SetIsEnabled(window, true);

                window.WindowStartupLocation = WindowStartupLocation.Manual;
                window.WindowState           = WindowState.Normal;
                window.Left                  = _screenList[i].Bounds.Left;
                window.Top                   = _screenList[i].Bounds.Top;
                window.Width                 = _screenList[i].Bounds.Width;
                window.Height                = _screenList[i].Bounds.Height;
                window.Topmost               = true;

#if DEBUG
                window.returnButton.Visibility = Visibility.Visible;
#else
                window.returnButton.Visibility = Visibility.Hidden;
#endif

                window.Show();

                window.WindowState = WindowState.Maximized;

                window.Activate();
            }
        }

        #endregion
        #region 블럭 윈도우 닫기 - CloseBlockWindows()

        /// <summary>
        /// 블럭 윈도우 닫기
        /// </summary>
        public static void CloseBlockWindows()
        {
            if(_windowList != null && _windowList.Count > 0)
            {
                for(int i = 0; i < _windowList.Count; i++)
                {
                    _windowList[i].WindowState = WindowState.Normal;

                    _windowList[i].Hide();
                }
            }
        }

        #endregion

        #region 화면 잠그기 - LockScreen()

        /// <summary>
        /// 화면 잠그기
        /// </summary>
        public static bool LockScreen()
        {
            if(_isLocked)
            {
                return false;
            }

            SetCursorPosition();

            HideSystemWindow();

            #region UWP 애플리케이션을 최소화한다.

            try
            {
                MinimizeUWPApplications();
            }
            catch
            {
                try
                {
                    RestoreCursorPosition();

                    RestoreUWPApplications();
                }
                catch
                {
                }

                throw;
            }

            #endregion
            #region 커서를 숨기고 태스크 관리자를 비활성하고 특수 키보드 입력을 비활성화한다.

            try
            {
                HideCursor();

                // DisableTaskManager();

                DisableSpecialKeyboardInput();
            }
            catch
            {
                try
                {
                    RestoreCursorPosition();

                    RestoreUWPApplications();

                    ShowCursor();

                    //EnableTaskManager();

                    EnableSpecialKeyboardInput();
                }
                catch
                {
                }

                throw;
            }

            #endregion
            #region 입력을 비활성화한다.

            try
            {
                bool result = DisableInput();

                if(!result)
                {
                    RestoreCursorPosition();

                    RestoreUWPApplications();

                    ShowCursor();

                    //EnableTaskManager();

                    EnableSpecialKeyboardInput();

                    return false;
                }
            }
            catch(Exception)
            {
                try
                {
                    RestoreCursorPosition();

                    RestoreUWPApplications();

                    ShowCursor();

                    //EnableTaskManager();

                    EnableSpecialKeyboardInput();
                }
                catch
                {
                }

                throw;
            }

            #endregion

            ShowBlockWindows();

            _isLocked = true;

            return true;
        }

        #endregion
        #region 화면 잠금 취소하기 - UnlockScreen()

        /// <summary>
        /// 화면 잠금 취소하기
        /// </summary>
        public static bool UnlockScreen()
        {
            if(!_isLocked)
            {
                return false;
            }

            try
            {
                RestoreCursorPosition();

                RestoreUWPApplications();

                CloseBlockWindows();

                EnableInput();

                EnableSpecialKeyboardInput();

                ShowCursor();

                _isLocked = false;

                return true;
            }
            catch
            {
                throw;
            }
        }

        #endregion

        #region 리소스 해제하기 - Dispose()

        /// <summary>
        /// 리소스 해제하기
        /// </summary>
        public static void Dispose()
        {
            if(_windowList != null && _windowList.Count > 0)
            {
                for(int i = _windowList.Count - 1; i > -1; i--)
                {
                    BlockWindow window = _windowList[i];

                    _windowList.Remove(window);

                    window.Close();
                }

                _windowList.Clear();
            }
        }

        #endregion

        //////////////////////////////////////////////////////////////////////////////// Private
        ////////////////////////////////////////////////////////////////////// Event

        #region 시스템 이벤트 디스플레이 설정 변경시 처리하기 - systemEvents_DisplaySettingsChanged(sender, e)

        /// <summary>
        /// 시스템 이벤트 디스플레이 설정 변경시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private static void systemEvents_DisplaySettingsChanged(object sender, EventArgs e)
        {
            if(_isLocked)
            {
                if(_screenCount != System.Windows.Forms.Screen.AllScreens.Length)
                {
                    CloseBlockWindows();

                    ShowBlockWindows();
                }

                HideCursor();
            }
        }

        #endregion

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

        #region 커서 위치 설정하기 - SetCursorPosition()

        /// <summary>
        /// 커서 위치 설정하기
        /// </summary>
        private static void SetCursorPosition()
        {
            GetCursorPos(out _cursorPoint);

            SetCursorPos(300, 300);
        }

        #endregion
        #region 커서 위치 복원하기 - RestoreCursorPosition()

        /// <summary>
        /// 커서 위치 복원하기
        /// </summary>
        private static void RestoreCursorPosition()
        {
            SetCursorPos(_cursorPoint.X, _cursorPoint.Y);
        }

        #endregion

        #region 후킹 설정하기 - SetHook(processKeyboardHookDelegate)

        /// <summary>
        /// 후킹 설정하기
        /// </summary>
        /// <param name="processKeyboardHookDelegate">키보드 후킹 처리 대리자</param>
        /// <returns>처리 결과</returns>
        private static int SetHook(ProcessKeyboardHookDelegate processKeyboardHookDelegate)
        {
            using(Process process = Process.GetCurrentProcess())
            {
                using(ProcessModule processModule = process.MainModule)
                {
                    return SetWindowsHookEx(WH_KEYBOARD_LL, processKeyboardHookDelegate, GetModuleHandle(processModule.ModuleName), 0);
                }
            }
        }

        #endregion
        #region 키보드 후킹 처리하기 - ProcessKeyboardHook(code, wordParameter, longParameter)

        /// <summary>
        /// 키보드 후킹 처리하기
        /// </summary>
        /// <param name="code">코드</param>
        /// <param name="wordParameter">WORD 매개 변수</param>
        /// <param name="longParameter">LONG 매개 변수</param>
        /// <returns>처리 결과</returns>
        private static int ProcessKeyboardHook(int code, int wordParameter, ref KBDLLHOOKSTRUCT longParameter)
        {
            bool result = false;

            switch(wordParameter)
            {
                case WM_KEYDOWN    :
                case WM_KEYUP      :
                case WM_SYSKEYDOWN :
                case WM_SYSKEYUP   :

                    result = ((longParameter.VirtualKeyCode == 0x09) && (longParameter.Flags == 0x20)) || // Alt + Tab
                             ((longParameter.VirtualKeyCode == 0x1B) && (longParameter.Flags == 0x20)) || // Alt + Esc
                             ((longParameter.VirtualKeyCode == 0x1B) && (longParameter.Flags == 0x00)) || // Ctrl + Esc
                             ((longParameter.VirtualKeyCode == 0x5B) && (longParameter.Flags == 0x01)) || // Left Windows Key
                             ((longParameter.VirtualKeyCode == 0x5C) && (longParameter.Flags == 0x01)) || // Right Windows Key
                             ((longParameter.VirtualKeyCode == 0x73) && (longParameter.Flags == 0x20));   // Alt + F4

                    break;
            }

            if(result == true)
            {
                return 1;
            }
            else
            {
                return CallNextHookEx(0, code, wordParameter, ref longParameter);
            }
        }

        #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"
    Width="800"
    Height="600"
    Title="잠금 화면 설정하기 (기능 개선)"
    FontFamily="나눔고딕코딩"
    FontSize="16">
    <Grid>
        <StackPanel
            HorizontalAlignment="Right"
            VerticalAlignment="Bottom"
            Margin="10"
            Orientation="Horizontal">
            <Button Name="lockButton"
                Width="100"
                Height="30"
                Content="Lock" />
            <Button Name="unlockButton"
                Margin="10 0 0 0"
                Width="100"
                Height="30"
                Content="Unlock" />
        </StackPanel>
    </Grid>
</Window>

 

▶ MainWindow.xaml.cs

using System.ComponentModel;
using System.Windows;

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

        #region 생성자 - MainWindow()

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

            Closing                 += Window_Closing;
            this.lockButton.Click   += lockButton_Click;
            this.unlockButton.Click += unlockButton_Click;
        }

        #endregion

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

        #region 윈도우 닫을 경우 처리하기 - Window_Closing(sender, e)

        /// <summary>
        /// 윈도우 닫을 경우 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void Window_Closing(object sender, CancelEventArgs e)
        {
            WindowHelper.Dispose();
        }

        #endregion
        #region Lock 버튼 클릭시 처리하기 - lockButton_Click(sender, e)

        /// <summary>
        /// Lock 버튼 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void lockButton_Click(object sender, RoutedEventArgs e)
        {
            WindowHelper.Header  = "아래와 같은 사유로 잠금 화면이 설정되었습니다.";
            WindowHelper.Message = "2명 이상의 얼굴이 탐지되었습니다.";

            WindowHelper.LockScreen();
        }

        #endregion
        #region Unlock 버튼 클릭시 처리하기 - unlockButton_Click(sender, e)

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

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

댓글을 달아 주세요