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

TestProject.zip
다운로드

▶ MainForm.cs

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

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

        #region Field

        /// <summary>
        /// 소스 비트맵
        /// </summary>
        private Bitmap sourceBitmap;

        /// <summary>
        /// 현재 스케일
        /// </summary>
        private float currentScale;

        /// <summary>
        /// 타겟 비트맵
        /// </summary>
        private Bitmap targetBitmap = null;

        /// <summary>
        /// 타겟 그래픽스
        /// </summary>
        private Graphics targetGraphics = null;

        /// <summary>
        /// 뷰포트 X
        /// </summary>
        private int viewportX = 0;
        
        /// <summary>
        /// 뷰포트 Y
        /// </summary>
        private int viewportY = 0;

        /// <summary>
        /// 드래그 여부
        /// </summary>
        private bool isDragging = false;

        /// <summary>
        /// 마지막 X
        /// </summary>
        private int lastX;
        
        /// <summary>
        /// 마지막 Y
        /// </summary>
        private int lastY;

        #endregion

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

        #region 생성자 - MainForm()

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

            #region 이벤트를 설정한다.

            Load                            += Form_Load;
            Resize                          += Form_Resize;
            this.exitMenuItem.Click         += exitMenuItem_Click;
            this.fullScaleMenuItem.Click    += sacleMenuItem_Click;
            this.halfScaleMenuItem.Click    += sacleMenuItem_Click;
            this.quarterScaleMenuItem.Click += sacleMenuItem_Click;
            this.canvasPictureBox.MouseDown += canvasPictureBox_MouseDown;
            this.canvasPictureBox.MouseMove += canvasPictureBox_MouseMove;
            this.canvasPictureBox.MouseUp   += canvasPictureBox_MouseUp;

            #endregion
        }

        #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)
        {
            this.canvasPictureBox.Cursor = new Cursor("hand2.cur");

            this.sourceBitmap = Bitmap.FromFile("map.png") as Bitmap;

            PrepareGraphics();

            this.fullScaleMenuItem.PerformClick();
        }

        #endregion
        #region 폼 크기 조정시 처리하기 - Form_Resize(sender, e)

        /// <summary>
        /// 폼 크기 조정시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void Form_Resize(object sender, EventArgs e)
        {
            PrepareGraphics();

            DrawBitmap();
        }

        #endregion
        #region 스케일 메뉴 항목 클릭시 처리하기 - sacleMenuItem_Click(sender, e)

        /// <summary>
        /// 스케일 메뉴 항목 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void sacleMenuItem_Click(object sender, EventArgs e)
        {
            ToolStripMenuItem currentMenuItem = sender as ToolStripMenuItem;

            foreach(ToolStripMenuItem menuItem in scaleMenuItem.DropDownItems)
            {
                menuItem.Checked = (menuItem == currentMenuItem);
            }

            this.currentScale = float.Parse(currentMenuItem.Tag.ToString());

            DrawBitmap();
        }

        #endregion
        #region 종료 메뉴 항목 클릭시 처리하기 - exitMenuItem_Click(sender, e)

        /// <summary>
        /// 종료 메뉴 항목 클릭시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void exitMenuItem_Click(object sender, EventArgs e)
        {
            Close();
        }

        #endregion
        #region 캔버스 픽처 박스 마우스 DOWN 처리하기 - canvasPictureBox_MouseDown(sender, e)

        /// <summary>
        /// 캔버스 픽처 박스 마우스 DOWN 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void canvasPictureBox_MouseDown(object sender, MouseEventArgs e)
        {
            this.lastX = e.X;
            this.lastY = e.Y;

            this.isDragging = true;
        }

        #endregion
        #region 캔버스 픽처 박스 마우스 이동시 처리하기 - canvasPictureBox_MouseMove(sender, e)

        /// <summary>
        /// 캔버스 픽처 박스 마우스 이동시 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void canvasPictureBox_MouseMove(object sender, MouseEventArgs e)
        {
            if(!this.isDragging)
            {
                return;
            }
            
            this.viewportX += e.X - this.lastX;
            this.viewportY += e.Y - this.lastY;

            this.lastX = e.X;
            this.lastY = e.Y;

            DrawBitmap();
        }

        #endregion
        #region 캔버스 픽처 박스 마우스 UP 처리하기 - canvasPictureBox_MouseUp(sender, e)

        /// <summary>
        /// 캔버스 픽처 박스 마우스 UP 처리하기
        /// </summary>
        /// <param name="sender">이벤트 발생자</param>
        /// <param name="e">이벤트 인자</param>
        private void canvasPictureBox_MouseUp(object sender, MouseEventArgs e)
        {
            this.isDragging = false;
        }

        #endregion

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

        #region 그래픽스 준비하기 - PrepareGraphics()

        /// <summary>
        /// 그래픽스 준비하기
        /// </summary>
        private void PrepareGraphics()
        {
            if((this.canvasPictureBox.ClientSize.Width == 0) || (this.canvasPictureBox.ClientSize.Height == 0))
            {
                return;
            }

            if(this.targetGraphics != null)
            {
                this.canvasPictureBox.Image = null;

                this.targetGraphics.Dispose();

                this.targetBitmap.Dispose();
            }

            this.targetBitmap = new Bitmap
            (
                this.canvasPictureBox.ClientSize.Width,
                this.canvasPictureBox.ClientSize.Height
            );

            this.targetGraphics = Graphics.FromImage(this.targetBitmap);

            this.targetGraphics.InterpolationMode = InterpolationMode.High;

            this.canvasPictureBox.Image = this.targetBitmap;
        }

        #endregion
        #region 뷰포트 원점 설정하기 - SetViewportOrigin()

        /// <summary>
        /// 뷰포트 원점 설정하기
        /// </summary>
        private void SetViewportOrigin()
        {
            float scaleWidth = this.currentScale * this.sourceBitmap.Width;

            int minimumX = (int)(this.canvasPictureBox.ClientSize.Width - scaleWidth);

            if(minimumX > 0)
            {
                minimumX = 0;
            }

            if(this.viewportX < minimumX)
            {
                this.viewportX = minimumX;
            }
            else if(this.viewportX > 0)
            {
                this.viewportX = 0;
            }

            float scaleHeight = this.currentScale * this.sourceBitmap.Height;

            int minimumY = (int)(this.canvasPictureBox.ClientSize.Height - scaleHeight);

            if(minimumY > 0)
            {
                minimumY = 0;
            }

            if(this.viewportY < minimumY)
            {
                this.viewportY = minimumY;
            }
            else if(this.viewportY > 0)
            {
                this.viewportY = 0;
            }
        }

        #endregion
        #region 비트맵 그리기 - DrawBitmap()

        /// <summary>
        /// 비트맵 그리기
        /// </summary>
        private void DrawBitmap()
        {
            SetViewportOrigin();

            float scaleWidth  = this.currentScale * this.sourceBitmap.Width;
            float scaleHeight = this.currentScale * this.sourceBitmap.Height;

            PointF[] targetPointArray =
            {
                new PointF(this.viewportX, this.viewportY),
                new PointF(this.viewportX + scaleWidth, this.viewportY),
                new PointF(this.viewportX, this.viewportY + scaleHeight)
            };

            RectangleF sourceRectangle = new RectangleF
            (
                0,
                0,
                this.sourceBitmap.Width,
                this.sourceBitmap.Height
            );

            this.targetGraphics.Clear(this.canvasPictureBox.BackColor);

            this.targetGraphics.DrawImage
            (
                this.sourceBitmap,
                targetPointArray,
                sourceRectangle,
                GraphicsUnit.Pixel
            );

            this.canvasPictureBox.Refresh();
        }

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

댓글을 달아 주세요