첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
유용한 소스 코드가 있으면 icodebroker@naver.com으로 보내주시면 감사합니다.
블로그 자료는 자유롭게 사용하세요.

728x90
반응형

■ SplashScreenManager 클래스 : ShowOverlayForm 메소드를 사용해 오버레이 폼 표시하기

------------------------------------------------------------------------------------------------------------------------


TestProject.zip



CustomOverlayImagePainter.cs

 

 

using System;

using System.Drawing;

using System.Windows.Forms;

 

using DevExpress.XtraSplashScreen;

 

namespace TestProject

{

    /// <summary>

    /// 커스텀 오버레이 이미지 페인터

    /// </summary>

    public class CustomOverlayImagePainter : OverlayImagePainter

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

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

 

        #region Field

 

        /// <summary>

        /// 소유자 컨트롤

        /// </summary>

        private Control ownerControl;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - CustomOverlayImagePainter(ownerControl, image, hoverImage, Action)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="ownerControl">소유자 컨트롤</param>

        /// <param name="image">이미지</param>

        /// <param name="hoverImage">호버 이미지</param>

        /// <param name="clickAction">클릭 액션</param>

        public CustomOverlayImagePainter(Control ownerControl, Image image, Image hoverImage = null, Action clickAction = null) : base

        (

            image,

            hoverImage,

            clickAction

        )

        {

            this.ownerControl = ownerControl;

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Protected

 

        #region 이미지 경계 계산하기 - CalcImageBounds(e)

 

        /// <summary>

        /// 이미지 경계 계산하기

        /// </summary>

        /// <param name="e">이벤트 인자</param>

        /// <returns>이미지 경계</returns>

        protected override Rectangle CalcImageBounds(OverlayLayeredWindowObjectInfoArgs e)

        {

            Rectangle imageRectangle = new Rectangle

            (

                (this.ownerControl.ClientRectangle.Width  - Image.Width ) / 2,

                (this.ownerControl.ClientRectangle.Height - Image.Height) / 2 - e.ImageBounds.Height,

                Image.Width,

                Image.Height

            );

 

            return imageRectangle;

        }

 

        #endregion

    }

}

 

 

CustomOverlayTextPainter.cs

 

 

using System.Drawing;

using System.Windows.Forms;

 

using DevExpress.XtraSplashScreen;

 

namespace TestProject

{

    /// <summary>

    /// 커스텀 오버레이 텍스트 페인터

    /// </summary>

    public class CustomOverlayTextPainter : OverlayTextPainter

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

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

 

        #region Field

 

        /// <summary>

        /// 소유자 컨트롤

        /// </summary>

        private Control ownerControl;

 

        /// <summary>

        /// 텍스트 오프셋

        /// </summary>

        private int textOffsetY;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - CustomOverlayTextPainter(ownerControl, font, color, textOffsetY)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="ownerControl">소유자 컨트롤</param>

        /// <param name="font">폰트</param>

        /// <param name="color">색상</param>

        /// <param name="textOffsetY">텍스트 오프셋</param>

        public CustomOverlayTextPainter(Control ownerControl, Font font, Color color, int textOffsetY) : base()

        {

            this.ownerControl = ownerControl;

 

            Font  = font;

            Color = color;

 

            this.textOffsetY = textOffsetY;

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Protected

 

        #region 텍스트 경계 계산하기 - CalcTextBounds(e)

 

        /// <summary>

        /// 텍스트 경계 계산하기

        /// </summary>

        /// <param name="e">이벤트 인자</param>

        /// <returns>텍스트 경계</returns>

        protected override Rectangle CalcTextBounds(OverlayLayeredWindowObjectInfoArgs e)

        {

            using(Graphics graphics = this.ownerControl.CreateGraphics())

            {

                Size textSize = graphics.MeasureString(Text, Font).ToSize();

 

                Rectangle textRectangle = new Rectangle

                (

                    (this.ownerControl.ClientRectangle.Width  - textSize.Width ) / 2,

                    (this.ownerControl.ClientRectangle.Height - textSize.Height) / 2 + this.textOffsetY,

                    textSize.Width,

                    textSize.Height

                );

 

                return textRectangle;

            }

        }

 

        #endregion

    }

}

 

 

OverlayFormHelper.cs

 

 

using System;

using System.Drawing;

using System.Threading;

using System.Windows.Forms;

 

using DevExpress.LookAndFeel;

using DevExpress.Skins;

using DevExpress.Utils;

using DevExpress.Utils.Drawing;

using DevExpress.Utils.Svg;

using DevExpress.XtraSplashScreen;

 

namespace TestProject

{

    /// <summary>

    /// 오버레이 폼 헬퍼

    /// </summary>

    public class OverlayFormHelper

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

        ////////////////////////////////////////////////////////////////////////////////////////// Static

        //////////////////////////////////////////////////////////////////////////////// Public

 

        #region Field

 

        /// <summary>

        /// 디폴트 폰트 24

        /// </summary>

        public static Font DefaultFont24 = new Font("나눔고딕코딩", 24f);

 

        /// <summary>

        /// 디폴트 폰트 16

        /// </summary>

        public static Font DefaultFont16 = new Font("나눔고딕코딩", 16f);

 

        /// <summary>

        /// 디폴트 폰트 12

        /// </summary>

        public static Font DefaultFont12 = new Font("나눔고딕코딩", 12f);

 

        #endregion

 

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

 

        #region Field

 

        /// <summary>

        /// 취소 버튼 일반 이미지

        /// </summary>

        private static Image _cancelButtonNormalImage;

 

        /// <summary>

        /// 취소 버튼 활성 이미지

        /// </summary>

        private static Image _cancelButtonActiveImage;

 

        #endregion

 

        ////////////////////////////////////////////////////////////////////////////////////////// Instance

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

 

        #region Field

 

        /// <summary>

        /// 오버레이 텍스트 페인터

        /// </summary>

        private OverlayTextPainter overlayTextPainter;

 

        /// <summary>

        /// 오버레이 이미지 페인터

        /// </summary>

        private OverlayImagePainter overlayImagePainter;

 

        /// <summary>

        /// 소유자 컨트롤

        /// </summary>

        private Control ownerControl;

 

        /// <summary>

        /// 텍스트 폰트

        /// </summary>

        private Font textFont;

 

        /// <summary>

        /// 텍스트 색상

        /// </summary>

        private Color textColor;

 

        /// <summary>

        /// 취소 토큰 소스

        /// </summary>

        private CancellationTokenSource cancellationTokenSource;

 

        /// <summary>

        /// 오버레이 윈도우 페인터

        /// </summary>

        private IOverlayWindowPainter overlayWindowPainter;

 

        /// <summary>

        /// 오버레이 핸들

        /// </summary>

        private IOverlaySplashScreenHandle overlayHandle = null;

 

        /// <summary>

        /// 텍스트 오프셋 Y

        /// </summary>

        private int textOffsetY;

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 취소 여부 - IsCancelled

 

        /// <summary>

        /// 취소 여부

        /// </summary>

        public bool IsCancelled

        {

            get

            {

                return this.cancellationTokenSource != null && this.cancellationTokenSource.Token.IsCancellationRequested;

            }

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Static

 

        #region 생성자 - OverlayFormHelper()

 

        /// <summary>

        /// 생성자

        /// </summary>

        static OverlayFormHelper()

        {

            _cancelButtonNormalImage = GetCancelButtonNormalImage();

            _cancelButtonActiveImage = GetCancelButtonActiveImage();

        }

 

        #endregion

 

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - OverlayFormHelper(ownerControl, textFont, textColor, allowCancel, textOffsetY)

 

        /// <summary>

        /// 생성자

        /// </summary>

        /// <param name="ownerControl">소유자 컨트롤</param>

        /// <param name="textFont">텍스트 폰트</param>

        /// <param name="textColor">텍스트 색상</param>

        /// <param name="allowCancel">취소 허용 여부</param>

        /// <param name="textOffsetY">텍스트 오프셋 Y</param>

        public OverlayFormHelper(Control ownerControl, Font textFont, Color textColor, bool allowCancel, int textOffsetY = 0)

        {

            this.ownerControl = ownerControl;

            this.textFont     = textFont;

            this.textColor    = textColor;

            this.textOffsetY  = textOffsetY;

 

            if(allowCancel)

            {

                this.cancellationTokenSource = new CancellationTokenSource();

            }

            else

            {

                this.cancellationTokenSource = null;

            }

 

            this.overlayTextPainter = new CustomOverlayTextPainter(this.ownerControl, this.textFont, this.textColor, this.textOffsetY);

 

            if(this.cancellationTokenSource == null)

            {

                this.overlayWindowPainter = new OverlayWindowCompositePainter(this.overlayTextPainter);

            }

            else

            {

                this.overlayImagePainter = new CustomOverlayImagePainter

                (

                    this.ownerControl,

                    _cancelButtonNormalImage,

                    _cancelButtonActiveImage,

                    new Action(ProcessClick)

                );

 

                this.overlayWindowPainter = new OverlayWindowCompositePainter

                (

                    this.overlayTextPainter,

                    this.overlayImagePainter

                );

            }

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Static

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

 

        #region 이미지 생성하기 - CreateImage(imageByteArray, skinProvider)

 

        /// <summary>

        /// 이미지 생성하기

        /// </summary>

        /// <param name="imageByteArray">이미지 바이트 배열</param>

        /// <param name="skinProvider">스킨 제공자</param>

        /// <returns>이미지</returns>

        private static Image CreateImage(byte[] imageByteArray, ISkinProvider skinProvider = null)

        {

            SvgBitmap svgBitmap = new SvgBitmap(imageByteArray);

 

            return svgBitmap.Render

            (

                SvgPaletteHelper.GetSvgPalette(skinProvider ?? UserLookAndFeel.Default, ObjectState.Normal),

                ScaleUtils.GetScaleFactor().Height

            );

        }

 

        #endregion

        #region 취소 버튼 일반 이미지 구하기 - GetCancelButtonNormalImage()

 

        /// <summary>

        /// 취소 버튼 일반 이미지 구하기

        /// </summary>

        /// <returns>취소 버튼 이미지</returns>

        private static Image GetCancelButtonNormalImage()

        {

            return CreateImage(Properties.Resources.CancelNormal);

        }

 

        #endregion

        #region 취소 버튼 활성 이미지 구하기 - GetCancelButtonActiveImage()

 

        /// <summary>

        /// 취소 버튼 활성 이미지 구하기

        /// </summary>

        /// <returns>활성 취소 버튼 이미지</returns>

        private static Image GetCancelButtonActiveImage()

        {

            return CreateImage(Properties.Resources.CancelActive);

        }

 

        #endregion

 

        ////////////////////////////////////////////////////////////////////////////////////////// Instance

        //////////////////////////////////////////////////////////////////////////////// Public

 

        #region 표시하기 - Show()

 

        /// <summary>

        /// 표시하기

        /// </summary>

        public void Show()

        {

            this.overlayHandle = SplashScreenManager.ShowOverlayForm

            (

                this.ownerControl,

                customPainter : this.overlayWindowPainter

            );

        }

 

        #endregion

        #region 메시지 설정하기 - SetMessage(message)

 

        /// <summary>

        /// 메시지 설정하기

        /// </summary>

        /// <param name="message">메시지</param>

        public void SetMessage(string message)

        {

            this.overlayTextPainter.Text = message;

        }

 

        #endregion

        #region 닫기 - Close()

 

        /// <summary>

        /// 닫기

        /// </summary>

        public void Close()

        {

            SplashScreenManager.CloseOverlayForm(this.overlayHandle);

 

            if(this.cancellationTokenSource != null)

            {

                this.cancellationTokenSource.Dispose();

 

                this.cancellationTokenSource = null;

            }

        }

 

        #endregion

 

        #region 취소 요청시 예외 발생시키기 - ThrowIfCancellationRequested()

 

        /// <summary>

        /// 취소 요청시 예외 발생시키기

        /// </summary>

        public void ThrowIfCancellationRequested()

        {

            if(this.cancellationTokenSource != null && this.cancellationTokenSource.Token != null)

            {

                this.cancellationTokenSource.Token.ThrowIfCancellationRequested();

            }

        }

 

        #endregion

 

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

 

        #region 클릭시 처리하기 - ProcessClick()

 

        /// <summary>

        /// 클릭시 처리하기

        /// </summary>

        private void ProcessClick()

        {

            if(this.cancellationTokenSource != null)

            {

                this.cancellationTokenSource.Cancel();

            }

        }

 

        #endregion

    }

}

 

 

MainForm.cs

 

 

using System;

using System.Threading.Tasks;

 

using DevExpress.XtraEditors;

 

namespace TestProject

{

    /// <summary>

    /// 메인 폼

    /// </summary>

    public partial class MainForm : XtraForm

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 생성자 - MainForm()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public MainForm()

        {

            InitializeComponent();

 

            this.executeButton.Click += executeButton_Click;

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

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

 

        #region 실행 버튼 클릭시 처리하기 - executeButton_Click(sender, e)

 

        /// <summary>

        /// 실행 버튼 클릭시 처리하기

        /// </summary>

        /// <param name="sender">이벤트 발생자</param>

        /// <param name="e">이벤트 인자</param>

        private async void executeButton_Click(object sender, EventArgs e)

        {

            OverlayFormHelper helper = new OverlayFormHelper(this.rootTableLayoutPanel, Font, ForeColor, true);

 

            try

            {

                helper.Show();

 

                await Task.Run

                (

                    () => {

 

                        for(int i = 0; i < 30; i++)

                        {

                            helper.SetMessage($"데이터를 로드하고 있습니다. ({i}/30)");

 

                            System.Threading.Thread.Sleep(500);

 

                            if(helper.IsCancelled)

                            {

                                XtraMessageBox.Show(this, "작업 취소");

 

                                return;

                            }

                        }

                    }

                );

            }

            finally

            {

                helper.Close();

            }

        }

 

        #endregion

    }

}

 

------------------------------------------------------------------------------------------------------------------------

728x90
반응형
Posted by 사용자 icodebroker

댓글을 달아 주세요