C# WinForms:提取子矩形并移动至(0,0)位置
问题:提取局部矩形并移动到(0,0)位置
需求:开发Windows Forms应用,从覆盖全屏的第一个矩形中提取第二个局部矩形,并将该局部矩形的内容移动到(0,0)位置。
当前效果

期望效果

原代码
namespace ClipWindowsFormsApplication { partial class Form1 { /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// Clean up any resources being used. /// </summary> /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.SuspendLayout(); // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(725, 509); this.Name = "Form1"; this.Text = "Form1"; this.Paint += new System.Windows.Forms.PaintEventHandler(this.Form1_Paint); this.ResumeLayout(false); } #endregion } } using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Drawing.Drawing2D; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace ClipWindowsFormsApplication { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.Clear(this.BackColor); //Create rectangles and regions Rectangle rect1 = new Rectangle(0, 0, 500, 500); Rectangle rect2 = new Rectangle(0, 100, 500, 200); Region r1 = new Region(rect1); Region r2 = new Region(rect2); //Call SetClip g.SetClip(r1, CombineMode.Intersect); g.DrawString("THIS IS GOING TO BE DELETED", this.Font, Brushes.Black, rect1); //Call IntersectClip g.IntersectClip(r2); //Fill rectangle g.FillRectangle(Brushes.Magenta, 0, 0, 500, 300); g.DrawString("TEST MY APP", this.Font, Brushes.White, rect2); //Call ResetClip g.ResetClip(); //Draw rectangles g.DrawRectangle(new Pen(Color.Red, 6), rect1); g.DrawRectangle(new Pen(Color.Black, 6), rect2); g.SetClip(rect2, CombineMode.Exclude); g.Clear(Color.White); g.ResetClip(); } } }
问题分析
原代码通过裁剪(Clip)操作限制绘制区域,但这只是控制了内容的显示范围,并没有实现**提取局部区域并平移到(0,0)**的核心需求。需要通过离线绘制或屏幕复制的方式实现目标。
解决方案
方案1:针对自定义绘制内容(推荐)
先将所有内容绘制到离线Bitmap中,再截取目标局部区域,最后绘制到(0,0)位置:
private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.Clear(this.BackColor); // 定义矩形:rect1为原始大区域,rect2为需要提取的局部区域 Rectangle rect1 = new Rectangle(0, 0, 500, 500); Rectangle rect2 = new Rectangle(0, 100, 500, 200); // 1. 将原始内容绘制到离线Bitmap using (Bitmap sourceBitmap = new Bitmap(rect1.Width, rect1.Height)) { using (Graphics bitmapGraphics = Graphics.FromImage(sourceBitmap)) { // 绘制原始内容 bitmapGraphics.DrawString("THIS IS GOING TO BE DELETED", this.Font, Brushes.Black, rect1); bitmapGraphics.FillRectangle(Brushes.Magenta, rect2); bitmapGraphics.DrawString("TEST MY APP", this.Font, Brushes.White, rect2); } // 2. 截取rect2区域,绘制到(0,0)位置 Rectangle destRect = new Rectangle(0, 0, rect2.Width, rect2.Height); g.DrawImage(sourceBitmap, destRect, rect2, GraphicsUnit.Pixel); } // 可选:绘制原始矩形边框用于对比 g.DrawRectangle(new Pen(Color.Red, 6), rect1); g.DrawRectangle(new Pen(Color.Black, 6), rect2); }
方案2:针对屏幕内容提取
如果需要提取整个屏幕(rect1为屏幕区域)的局部内容,使用CopyFromScreen直接复制屏幕像素:
private void Form1_Paint(object sender, PaintEventArgs e) { Graphics g = e.Graphics; g.Clear(this.BackColor); // rect1为整个屏幕区域,rect2为屏幕上的局部区域 Rectangle rect1 = Screen.PrimaryScreen.Bounds; Rectangle rect2 = new Rectangle(0, 100, 500, 200); // 将rect2区域的屏幕内容复制到当前窗体的(0,0)位置 g.CopyFromScreen(rect2.Location, Point.Empty, rect2.Size); }
说明
- 方案1适用于你自己绘制的内容,能精准控制要提取的区域和内容;
- 方案2适用于截取屏幕上的现有内容,无需提前绘制。
内容的提问来源于stack exchange,提问作者Xtremexploit
相关产品推荐
相关产品推荐

