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

728x90
반응형
728x170

TestProject.zip
0.01MB

▶ MainForm.cs

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace TestProject
{
    /// <summary>
    /// 메인 폼
    /// </summary>
    public partial class MainForm : Form
    {
        //////////////////////////////////////////////////////////////////////////////////////////////////// Import
        ////////////////////////////////////////////////////////////////////////////////////////// Static
        //////////////////////////////////////////////////////////////////////////////// Private

        #region 디바이스 컨텍스트 생성하기 - CreateDC(driverName, deviceName, port, initialDataHandle)

        /// <summary>
        /// 디바이스 컨텍스트 생성하기
        /// </summary>
        /// <param name="driverName">드라이버명</param>
        /// <param name="deviceName">장치명</param>
        /// <param name="port">포트</param>
        /// <param name="initialDataHandle">초기 데이터 핸들</param>
        /// <returns>디바이스 컨텍스트 핸들</returns>
        [DllImport("gdi32")]
        private static extern IntPtr CreateDC(string driverName, string deviceName, string port, IntPtr initialDataHandle);

        #endregion
        #region 디바이스 컨텍스트 삭제하기 - DeleteDC(deviceContextHandle)

        /// <summary>
        /// 디바이스 컨텍스트 삭제하기
        /// </summary>
        /// <param name="deviceContextHandle">디바이스 컨텍스트 핸들</param>
        /// <returns>처리 결과</returns>
        [DllImport("gdi32")]
        private static extern bool DeleteDC(IntPtr deviceContextHandle);

        #endregion
        #region 클라이언트 좌표에서 화면 좌표 구하기 - ClientToScreen(windowHandle, screenPoint)

        /// <summary>
        /// 클라이언트 좌표에서 화면 좌표 구하기
        /// </summary>
        /// <param name="windowHandle">윈도우 핸들</param>
        /// <param name="screenPoint">화면 좌표계 포인트</param>
        /// <returns>처리 결과</returns>
        [DllImport("user32")]
        private static extern bool ClientToScreen(IntPtr windowHandle, ref Point screenPoint);

        #endregion
        #region 비트맵 복사하기 - BitBlt(targetDeviceContextHandle, targetX, targetY, width, height, sourceDeviceContextHandle, sourceX, sourceY, rasterOperationCode

        /// <summary>
        /// 비트맵 복사하기
        /// </summary>
        /// <param name="targetDeviceContextHandle">타겟 디바이스 컨텍스트 핸들</param>
        /// <param name="targetX">타겟 X</param>
        /// <param name="targetY">타겟 Y</param>
        /// <param name="width">너비</param>
        /// <param name="height">높이</param>
        /// <param name="sourceDeviceContextHandle">소스 디바이스 컨텍스트 핸들</param>
        /// <param name="sourceX">소스 X</param>
        /// <param name="sourceY">소스 Y</param>
        /// <param name="rasterOperationCode">래스터 연산 코드</param>
        /// <returns>처리 결과</returns>
        [DllImport("gdi32")]
        private static extern bool BitBlt
        (
            IntPtr targetDeviceContextHandle,
            int targetX,
            int targetY,
            int width,
            int height,
            IntPtr sourceDeviceContextHandle,
            int sourceX,
            int sourceY,
            int rasterOperationCode
        );

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field
        ////////////////////////////////////////////////////////////////////////////////////////// Private

        #region Field

        /// <summary>
        /// SRCCOPY
        /// </summary>
        private const int SRCCOPY = 0xcc0020;

        /// <summary>
        /// 드래그 문자열
        /// </summary>
        private string dragString;

        /// <summary>
        /// 드래그 문자열 포인트
        /// </summary>
        private Point dragStringPoint;

        /// <summary>
        /// 드래그 문자열 폰트
        /// </summary>
        private Font dragStringFont;

        /// <summary>
        /// 드래그 이미지 크기
        /// </summary>
        private Size dragImageSize;

        /// <summary>
        /// 마우스 DOWN 여부
        /// </summary>
        private bool mouseDown = false;

        /// <summary>
        /// 마우스 델타 포인트
        /// </summary>
        private Point mouseDeltaPoint;

        /// <summary>
        /// 전체 화면 디바이스 컨텍스트 핸들
        /// </summary>
        private IntPtr displayDeviceContextHandle;

        /// <summary>
        /// 전체 화면 그래픽스
        /// </summary>
        private Graphics displayGraphics;

        /// <summary>
        /// 백업 저장소 비트맵
        /// </summary>
        private Bitmap backingStoreBitmap;

        /// <summary>
        /// 백업 저장소 그래픽스
        /// </summary>
        private Graphics backingStoreGraphics;

        /// <summary>
        /// 백업 저장소 디바이스 컨텍스트 핸들
        /// </summary>
        private IntPtr backingStoreDeviceContextHandle;

        /// <summary>
        /// 백업 저장소 포인트
        /// </summary>
        private Point backingStorePoint;

        #endregion

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor
        ////////////////////////////////////////////////////////////////////////////////////////// Public

        #region 생성자 - MainForm()

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

            this.dragString         = "Drag Me!";
            this.dragStringPoint = new Point(100, 100);
            this.dragStringFont     = new Font("Times New Roman", 14, FontStyle.Bold);

            Load      += Form_Load;
            MouseDown += Form_MouseDown;
            MouseMove += Form_MouseMove;
            MouseUp   += Form_MouseUp;
            Paint     += Form_Paint;
        }

        #endregion

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

        #region 폼 로드시 처리하기 - Form_Load(sender, e)

        /// <summary>
        /// 폼 로드시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void Form_Load(object sender, EventArgs e)
        {
            Graphics graphics = CreateGraphics();

            SizeF dragStringSize = graphics.MeasureString(this.dragString, this.dragStringFont);

            this.dragImageSize = new Size((int)dragStringSize.Width, (int)dragStringSize.Height);

            graphics.Dispose();
        }

        #endregion
        #region 폼 마우스 DOWN 처리하기 - Form_MouseDown(sender, e)

        /// <summary>
        /// 폼 마우스 DOWN 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void Form_MouseDown(object sender, MouseEventArgs e)
        {
            Rectangle dragStringRectangle = new Rectangle
            (
                this.dragStringPoint,
                new Size(this.dragImageSize.Width, this.dragImageSize.Height)
            );

            if(dragStringRectangle.Contains(e.Location))
            {
                this.mouseDown = true;

                this.mouseDeltaPoint = new Point(e.X - this.dragStringPoint.X, e.Y - this.dragStringPoint.Y);

                Point screenPoint = GetScreenPoint(e.X, e.Y);

                screenPoint.X -= this.mouseDeltaPoint.X;
                screenPoint.Y -= this.mouseDeltaPoint.Y;

                SetDisplayGraphics();

                this.backingStoreBitmap = new Bitmap(this.dragImageSize.Width, this.dragImageSize.Height);

                this.backingStoreGraphics = Graphics.FromImage(backingStoreBitmap);

                this.backingStoreDeviceContextHandle = this.backingStoreGraphics.GetHdc();

                BitBlt
                (
                    this.backingStoreDeviceContextHandle,
                    0,
                    0,
                    this.backingStoreBitmap.Width, this.backingStoreBitmap.Height,
                    this.displayDeviceContextHandle,
                    screenPoint.X,
                    screenPoint.Y,
                    SRCCOPY
                );

                this.backingStorePoint = new Point(screenPoint.X, screenPoint.Y);

                DrawDragImage(this.displayGraphics, true, screenPoint.X, screenPoint.Y, dragString);
            }
        }

        #endregion
        #region 폼 마우스 이동시 처리하기 - Form_MouseMove(sender, e)

        /// <summary>
        /// 폼 마우스 이동시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void Form_MouseMove(object sender, MouseEventArgs e)
        {
            if(this.mouseDown)
            {
                Point screenPoint = GetScreenPoint(e.X, e.Y);

                screenPoint.X -= this.mouseDeltaPoint.X;
                screenPoint.Y -= this.mouseDeltaPoint.Y;

                BitBlt
                (
                    this.displayDeviceContextHandle,
                    this.backingStorePoint.X,
                    this.backingStorePoint.Y,
                    this.backingStoreBitmap.Width,
                    this.backingStoreBitmap.Height,
                    this.backingStoreDeviceContextHandle,
                    0,
                    0,
                    SRCCOPY
                );

                BitBlt
                (
                    this.backingStoreDeviceContextHandle,
                    0,
                    0,
                    this.backingStoreBitmap.Width,
                    this.backingStoreBitmap.Height,
                    this.displayDeviceContextHandle,
                    screenPoint.X,
                    screenPoint.Y,
                    SRCCOPY
                );

                this.backingStorePoint = new Point(screenPoint.X, screenPoint.Y);

                DrawDragImage(this.displayGraphics, true, screenPoint.X, screenPoint.Y, this.dragString);
            }
        }

        #endregion
        #region 폼 마우스 UP 처리하기 - Form_MouseUp(sender, e)

        /// <summary>
        /// 폼 마우스 UP 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void Form_MouseUp(object sender, MouseEventArgs e)
        {
            if(this.mouseDown)
            {
                this.mouseDown = false;

                BitBlt
                (
                    this.displayDeviceContextHandle,
                    this.backingStorePoint.X,
                    this.backingStorePoint.Y,
                    this.backingStoreBitmap.Width,
                    this.backingStoreBitmap.Height,
                    this.backingStoreDeviceContextHandle,
                    0,
                    0,
                    SRCCOPY
                );

                DisposeDisplayDeviceContext();

                this.backingStoreGraphics.ReleaseHdc(this.backingStoreDeviceContextHandle);

                this.backingStoreGraphics.Dispose();

                this.backingStoreBitmap.Dispose();

                this.backingStoreBitmap = null;
            }
        }

        #endregion
        #region 폼 페인트시 처리하기 - Form_Paint(sender, e)

        /// <summary>
        /// 폼 페인트시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void Form_Paint(object sender, PaintEventArgs e)
        {
            Graphics graphics = e.Graphics;

            graphics.FillRectangle(Brushes.Bisque, ClientRectangle);

            Font font = new Font("Times New Roman", 32);

            graphics.DrawString("Hello, World!", font, Brushes.Blue, 10, 10);

            font.Dispose();

            DrawDragImage(graphics, false, this.dragStringPoint.X, this.dragStringPoint.X, this.dragString);
        }

        #endregion

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

        #region 화면 포인트 구하기 - GetScreenPoint(x, y)

        /// <summary>
        /// 화면 포인트 구하기
        /// </summary>
        /// <param name="x">X</param>
        /// <param name="y">Y</param>
        /// <returns>화면 포인트</returns>
        private Point GetScreenPoint(int x, int y)
        {
            Point screenPoint = new Point(x, y);

            ClientToScreen(Handle, ref screenPoint);

            return screenPoint;
        }

        #endregion
        #region 전체 화면 그래픽스 설정하기 - SetDisplayGraphics()

        /// <summary>
        /// 전체 화면 그래픽스 설정하기
        /// </summary>
        private void SetDisplayGraphics()
        {
            this.displayDeviceContextHandle = CreateDC("DISPLAY", null, null, (IntPtr)null); 

            this.displayGraphics = Graphics.FromHdc(this.displayDeviceContextHandle);
        }

        #endregion
        #region 드래그 이미지 그리기 - DrawDragImage(graphics, alphaBlending, x, y, text)

        /// <summary>
        /// 드래그 이미지 그리기
        /// </summary>
        /// <param name="graphics">그래픽스</param>
        /// <param name="alphaBlending">알파 블렌딩 적용 여부</param>
        /// <param name="x">X</param>
        /// <param name="y">Y</param>
        /// <param name="text">텍스트</param>
        private void DrawDragImage(Graphics graphics, bool alphaBlending, int x, int y, string text)
        {
            Rectangle rectangle = new Rectangle(x, y, this.dragImageSize.Width, this.dragImageSize.Height);

            if(alphaBlending)
            {
                Color color1 = Color.FromArgb(0 , Color.Red);
                Color color2 = Color.FromArgb(80, Color.Red);

                Rectangle rectangle1 = new Rectangle
                (
                    rectangle.Left,
                    rectangle.Top,
                    rectangle.Width / 2,
                    rectangle.Height
                );

                Rectangle rectangle2 = new Rectangle
                (
                    rectangle.Left + rectangle.Width / 2,
                    rectangle.Top,
                    rectangle.Width / 2,
                    rectangle.Height
                );

                LinearGradientBrush brush1 = new LinearGradientBrush(rectangle1, color1, color2, 0f);
                LinearGradientBrush brush2 = new LinearGradientBrush(rectangle2, color2, color1, 0f);

                graphics.FillRectangle
                (
                    brush1,
                    new Rectangle
                    (
                        rectangle1.Left + 1,
                        rectangle1.Top,
                        rectangle1.Width + 1,
                        rectangle1.Height
                    )
                );

                graphics.FillRectangle(brush2, rectangle2);

                brush1.Dispose();
                brush2.Dispose();
            }
            else
            {
                graphics.FillRectangle(Brushes.Red, rectangle);
            }

            Color textColor;

            if(alphaBlending)
            {
                textColor = Color.FromArgb(80, Color.Black);
            }
            else
            {
                textColor = Color.Black;
            }

            Brush textBrush = new SolidBrush(textColor);

            graphics.DrawString(text, this.dragStringFont, textBrush, rectangle);

            textBrush.Dispose();
        }

        #endregion
        #region 전체 화면 디바이스 컨텍스트 리소스 해제하기 - DisposeDisplayDeviceContext()

        /// <summary>
        /// 전체 화면 디바이스 컨텍스트 리소스 해제하기
        /// </summary>
        private void DisposeDisplayDeviceContext()
        {
            this.displayGraphics.Dispose();

            DeleteDC(this.displayDeviceContextHandle);
        }

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

댓글을 달아 주세요