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

namespace MyScreenCap.Ctrl {

    /// <summary>
    /// Rectangle画像切り出し
    /// </summary>
    class FormRectCap : Form {

        /// <summary>
        /// Rectangleで囲まれた範囲の画像
        /// </summary>
        public Bitmap BmpRect { get; set; }

        /// <summary>
        /// FullScreen画像
        /// </summary>
        private Bitmap bmp = null;

        /// <summary>
        /// Rectangle Start Position
        /// </summary>
        private Point startPos;

        /// <summary>
        /// Rectangle Current Position
        /// </summary>
        private Point currentPos;

        /// <summary>
        /// Rectangle Drawing Flg
        /// </summary>
        private bool drawing;

        /// <summary>
        /// コンストラクタ
        /// </summary>
        public FormRectCap() {
            bmp = new Bitmap(Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height);
            using (Graphics g = Graphics.FromImage(bmp)) {
                g.CopyFromScreen(new Point(0, 0), new Point(0, 0), bmp.Size);
            }
            this.BackgroundImage = bmp;
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
            this.WindowState = FormWindowState.Maximized;
            this.ShowInTaskbar = false;
            this.DoubleBuffered = true;

            this.MouseDown += new MouseEventHandler(FormRectCap_MouseDown);
            this.MouseMove += new MouseEventHandler(FormRectCap_MouseMove);
            this.MouseUp += new MouseEventHandler(FormRectCap_MouseUp);

            this.Shown += new EventHandler(FormRectCap_Shown);
            this.FormClosed += new FormClosedEventHandler(FormRectCap_FormClosed);
            this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.FormRectCap_KeyDown);

        }

        /// <summary>
        /// FormRectCap Shown
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void FormRectCap_Shown(object sender, EventArgs e) {

            this.BringToFront();
            this.Activate();
            Cursor.Hide();
        }

        /// <summary>
        /// FormRectCap FormClosed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void FormRectCap_FormClosed(object sender, FormClosedEventArgs e) {

            Cursor.Show();
        }

        /// <summary>
        /// FormRectCap MouseDown
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FormRectCap_MouseDown(object sender, MouseEventArgs e) {
            currentPos = startPos = e.Location;
            drawing = true;
        }

        /// <summary>
        /// FormRectCap MouseMove
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FormRectCap_MouseMove(object sender, MouseEventArgs e) {
            currentPos = e.Location;
            this.Invalidate();
        }

        /// <summary>
        /// FormRectCap MouseUp
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FormRectCap_MouseUp(object sender, MouseEventArgs e) {
            if (drawing) {
                drawing = false;
                Rectangle rect = GetRectangle();
                if (rect.Width != 0 && rect.Height != 0) {
                    BmpRect = new Bitmap(rect.Width, rect.Height);
                    using (Graphics g = Graphics.FromImage(BmpRect)) {
                        g.DrawImage(bmp, 0, 0, rect, GraphicsUnit.Pixel);
                    }
                } else {
                    BmpRect = null;
                }
                this.DialogResult = System.Windows.Forms.DialogResult.OK;
                this.Close();
            }
        }

        /// <summary>
        /// KeyDown
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FormRectCap_KeyDown(object sender, KeyEventArgs e) {
            if (e.KeyData == Keys.Escape) {
                this.Close();
            }
        }

        /// <summary>
        /// OnPaint
        /// </summary>
        /// <param name="e"></param>
        protected override void OnPaint(PaintEventArgs e) {
            base.OnPaint(e);

            e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighSpeed;

            int magnification = 4;
            int loupeSize = 80;
            int srcImageSize = 20;
            int loupeSpace = 10;
            Point loupePos = new Point(currentPos.X + loupeSpace, currentPos.Y + loupeSpace);
            int labelHeight = 12;
            int srcImageCenter = srcImageSize / 2;
            int destImageSize = srcImageSize * magnification;
            int destImageStartPos = (loupeSize - destImageSize) / 2;
            int destImageCenter = destImageStartPos + destImageSize / 2;

            if (loupePos.X + loupeSize > Screen.PrimaryScreen.Bounds.Width) {
                loupePos.X = currentPos.X - loupeSize - loupeSpace;
            }
            if (loupePos.Y + loupeSize + labelHeight > Screen.PrimaryScreen.Bounds.Height) {
                loupePos.Y = currentPos.Y - loupeSize - loupeSpace - labelHeight;
            }

            Bitmap bitmap = new Bitmap(loupeSize, loupeSize);
            using (Graphics g = Graphics.FromImage(bitmap)) {
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor;
                g.FillRectangle(Brushes.Black, new Rectangle(0, 0, bitmap.Width, bitmap.Height));
                g.DrawImage(bmp,
                    new Rectangle(destImageStartPos, destImageStartPos, destImageSize, destImageSize),
                    currentPos.X - srcImageCenter,
                    currentPos.Y - srcImageCenter,
                    srcImageSize,
                    srcImageSize,
                    GraphicsUnit.Pixel);
                g.DrawRectangle(new Pen(Brushes.Red, 4), new Rectangle(0, 0, bitmap.Width, bitmap.Height));

                g.FillRectangle(Brushes.Red,
                    destImageCenter,
                    0,
                    magnification,
                    destImageSize);
                g.FillRectangle(Brushes.Red,
                    0,
                    destImageCenter,
                    destImageSize,
                    magnification);
            }
            e.Graphics.DrawImage(bitmap, loupePos);

            if (drawing) {
                Rectangle rect = GetRectangle();
                e.Graphics.DrawRectangle(Pens.Red, GetRectangle());

                Point strDrawPos = new Point(loupePos.X, loupePos.Y + loupeSize);
                e.Graphics.FillRectangle(Brushes.White, new Rectangle(strDrawPos, new Size(loupeSize, labelHeight)));
                e.Graphics.DrawRectangle(Pens.Red, new Rectangle(strDrawPos, new Size(loupeSize, labelHeight)));
                e.Graphics.DrawString(string.Format("W：{0},H：{1}", rect.Width, rect.Height), new Font("MS UI Gothic", 9F), Brushes.Red, strDrawPos);
            } else {
                Rectangle rect = Screen.PrimaryScreen.Bounds;
                e.Graphics.FillRectangle(Brushes.Red,
                    currentPos.X,
                    0,
                    1,
                    rect.Bottom);
                e.Graphics.FillRectangle(Brushes.Red,
                    0,
                    currentPos.Y,
                    rect.Right,
                    1);
            }


        }

        /// <summary>
        /// Get Rectangle
        /// </summary>
        /// <returns></returns>
        private Rectangle GetRectangle() {
            return new Rectangle(
                Math.Min(startPos.X, currentPos.X),
                Math.Min(startPos.Y, currentPos.Y),
                Math.Abs(startPos.X - currentPos.X),
                Math.Abs(startPos.Y - currentPos.Y));
        }
    }
}
