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

C# GDI+ 截圖實戰(三)— 仿 QQ 截圖完整實作與雙緩衝防閃爍技術

     編輯:關於C語言

仿 QQ 截圖效果展示

核心思路

  1. 聊天視窗點擊截圖按鈕
  2. 隱藏自身,建立全螢幕無邊框視窗 (Catch)
  3. 截取全螢幕畫面為 Bitmap 設為 Catch 背景
  4. 在 Catch 上滑鼠拖曳繪製選取矩形
  5. 雙擊矩形內部 → 截取該區域存入剪貼簿 → 貼回聊天視窗

關鍵技術:雙緩衝解決殘影問題

**問題**:直接在視窗繪製矩形,滑鼠移動會留下大量殘影矩形。

**方案二(採用)**:雙重緩衝離屏繪製

  1. 保存原始全螢幕圖片 originBmp
  2. 每次繪製:Clone() 原始圖 → 在副本上畫矩形 → 整體繪製到視窗
  3. 原始圖不變,每幀從乾淨基底重繪,**零殘影**

Catch 視窗完整代碼


public partial class Catch : Form
{
    private Point DownPoint = Point.Empty;
    private bool CatchFinished = false;
    private bool CatchStart = false;
    private Bitmap originBmp;
    private Rectangle CatchRect;

    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_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(); caughtBmp.Dispose();

            this.BackgroundImage = originBmp;
            CatchFinished = false;
            this.DialogResult = DialogResult.OK;
            this.Close();
        }
    }

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

主視窗調用代碼


private void bCatch_Click(object sender, EventArgs e)
{
    if (bCatch_HideCurrent.Checked)
    {
        this.Hide();
        Thread.Sleep(50);
        
        Catch catchForm = new Catch();
        Bitmap screenBmp = new Bitmap(Screen.AllScreens[0].Bounds.Width, 
                                      Screen.AllScreens[0].Bounds.Height);
        Graphics g = Graphics.FromImage(screenBmp);
        g.CopyFromScreen(Point.Empty, Point.Empty, screenBmp.Size);
        catchForm.BackgroundImage = screenBmp;

        if (catchForm.ShowDialog() == DialogResult.OK)
        {
            if (Clipboard.GetDataObject().GetDataPresent(DataFormats.Bitmap))
            {
                richtextbox1.Paste(DataFormats.GetFormat(DataFormats.Bitmap));
                Clipboard.Clear();
            }
            this.Show();
        }
    }
}

關鍵技術點總結

  • CopyFromScreen:高效全螢幕截圖
  • Bitmap.Clone():快速複製原始圖避免修改
  • Graphics.DrawImage:離屏繪製後整體呈現
  • ControlStyles.OptimizedDoubleBuffer:系統級雙緩衝
  • Clipboard.SetImage/GetDataObject:跨視窗圖片傳遞
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved