首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# GDI+ 截圖實戰(三·核心代碼)— Catch 視窗雙緩衝離屏繪製完整實作

     編輯:關於C語言

Catch 視窗完整實作代碼(續)


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace Client
{
    public partial class Catch : Form
    {
        public Catch() { InitializeComponent(); }

        #region 用戶變量
        private Point DownPoint = Point.Empty;
        private bool CatchFinished = false;
        private bool CatchStart = false;
        private Bitmap originBmp;
        private Rectangle CatchRect;
        #endregion

        private void Catch_Load(object sender, EventArgs e)
        {
            // 雙緩衝設定
            this.SetStyle(ControlStyles.OptimizedDoubleBuffer | 
                          ControlStyles.AllPaintingInWmPaint | 
                          ControlStyles.UserPaint, true);
            this.UpdateStyles();

            originBmp = new Bitmap(this.BackgroundImage);
        }

        private void Catch_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Right)
            {
                this.DialogResult = DialogResult.OK;
                this.Close();
            }
        }

        private void Catch_MouseDown(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left && !CatchStart)
            {
                CatchStart = true;
                DownPoint = new Point(e.X, e.Y);
            }
        }

        private void Catch_MouseMove(object sender, MouseEventArgs e)
        {
            if (CatchStart)
            {
                Bitmap destBmp = (Bitmap)originBmp.Clone();
                Point newPoint = new Point(DownPoint.X, DownPoint.Y);
                Graphics g = Graphics.FromImage(destBmp);
                Pen p = new Pen(Color.Blue, 1);

                int width = Math.Abs(e.X - DownPoint.X);
                int height = Math.Abs(e.Y - DownPoint.Y);
                if (e.X < DownPoint.X) newPoint.X = e.X;
                if (e.Y < DownPoint.Y) newPoint.Y = e.Y;

                CatchRect = new Rectangle(newPoint, new Size(width, height));
                g.DrawRectangle(p, CatchRect);
                g.Dispose(); p.Dispose();

                Graphics g1 = this.CreateGraphics();
                g1.DrawImage(destBmp, new Point(0, 0));
                g1.Dispose();
                destBmp.Dispose();
            }
        }

        private void Catch_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left && CatchStart)
            {
                CatchStart = false;
                CatchFinished = true;
            }
        }

        private void Catch_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left && CatchFinished && 
                CatchRect.Contains(new Point(e.X, e.Y)))
            {
                Bitmap caughtBmp = new Bitmap(CatchRect.Width, CatchRect.Height);
                Graphics g = Graphics.FromImage(caughtBmp);
                g.DrawImage(originBmp, 
                    new Rectangle(0, 0, CatchRect.Width, CatchRect.Height),
                    CatchRect, GraphicsUnit.Pixel);
                
                Clipboard.SetImage(caughtBmp);
                g.Dispose();
                CatchFinished = false;
                this.BackgroundImage = originBmp;
                caughtBmp.Dispose();
                this.DialogResult = DialogResult.OK;
                this.Close();
            }
        }
    }
}

核心技術深度解析

1. 雙緩衝原理

  • originBmp:永不修改的原始全螢幕截圖
  • 每幀:Clone() → 畫矩形 → DrawImage 整體呈現
  • 避免直接在視窗疊加繪製導致殘影

2. 座標計算邏輯

  • DownPoint:滑鼠按下起點
  • e.X, e.Y:滑鼠當前位置
  • 寬高取絕對值,左上角取較小座標 → 正確構建 Rectangle

3. 截取邏輯


g.DrawImage(originBmp, 
    new Rectangle(0, 0, CatchRect.Width, CatchRect.Height), // 目標矩形
    CatchRect,                                              // 來源矩形
    GraphicsUnit.Pixel);

從 originBmp 的 CatchRect 區域,按像素單位繪製到新建立的等大 Bitmap。

4. 資源管理鐵律

  • 每個 Graphics、Pen、Bitmap 用完即 Dispose()
  • destBmp 每幀建立每幀釋放,防止記憶體洩漏
  • caughtBmp 存入剪貼簿後釋放(剪貼簿內部複製)

5. 雙擊確認機制

  • CatchFinished 確保已完成選取
  • CatchRect.Contains() 確保雙擊在選區內
  • 右鍵可隨時取消
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved