c# - 使用来自 OnMouseMove 的 froms OnPaint 方法中的图形绘制时的 C# 大延迟
问题描述
我的目标是在表单上绘制图像(屏幕截图)并使用橡皮筋矩形突出显示选定区域。我希望图像变暗并且选择区域正常。
我试图通过使用鼠标事件来获取用户选择的区域,在表单上绘制图像,然后使用区域(用于变暗/突出显示效果)在图像上绘制不透明的黑色叠加层来实现这一点,除了使用以下代码选择区域:
class ExampleForm : Form {
private Bitmap screenshot;
private Rectangle r;
private Region reg;
private SolidBrush brush;
public ExampleForm() {
r = Screen.PrimaryScreen.Bounds;
screenshot = new Bitmap(r.Width, r.Height);
Graphics.FromImage(screenshot).CopyFromScreen(r.Left, r.Top, 0, 0, r.Size);
SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true);
FormBorderStyle = FormBorderStyle.None;
WindowState = FormWindowState.Maximized;
TopMost = true;
DoubleBuffered = true;
ShowInTaskbar = false;
reg = new Region(r);
brush = new SolidBrush(Color.FromArgb(200, Color.Black));
}
private Point startDrag, endDrag;
private bool mouseDown;
protected override void OnMouseDown(MouseEventArgs e) {
mouseDown = true;
startDrag = e.Location;
}
protected override void OnMouseUp(MouseEventArgs e) {
mouseDown = false;
}
protected override void OnMouseMove(MouseEventArgs e) {
if (!mouseDown) return;
endDrag = e.Location;
UpdatePaint();
}
private void UpdatePaint() {
Rectangle window = new Rectangle(
Math.Min(startDrag.X, endDrag.X),
Math.Min(startDrag.Y, endDrag.Y),
Math.Abs(startDrag.X - endDrag.X),
Math.Abs(startDrag.Y - endDrag.Y)
);
reg = new Region(ClientRectangle);
reg.Xor(window);
Invalidate();
}
protected override void OnPaint(PaintEventArgs e) {
Graphics g = e.Graphics;
g.DrawImage(screenshot, r);
g.FillRegion(brush, reg);
}
}
但是,这样做时,在我移动鼠标和“突出显示”区域更新到鼠标位置之间存在相当大的延迟。
我试图在没有图像的情况下进行区域突出显示,甚至只是在没有图像和区域的情况下绘制一个矩形,并且延迟更少,但是与 Windows 资源管理器突出显示或 lightshot 之类的东西相比(这就是我想要的功能重新创建)在鼠标移动和表单中显示的内容之间仍然存在更多延迟。
我什至尝试使用两种形式:一种用于图像,另一种用于变暗/高亮效果,因此不必每次都重新绘制图像,但无法在顶部绘制不透明颜色的同时使表单透明。
我也尝试过 OnPaintBackground,使用标签或图像框,但都有相同的延迟。
那么有没有更有效的方法来进行绘图和/或我使用的突出显示效果?
解决方案
基于 Taw 的评论,这里我们将BackgroundImage
Form 设置为屏幕截图的深色版本,并且我们只OnPaint()
在当前选择的位置绘制原始版本(“变亮”版本,不是真的)。我还将代码简化为完成任务所需的最低限度:
public partial class ExampleForm : Form
{
private Point startDrag;
private SolidBrush brush;
private Rectangle selectionRc;
private Bitmap originalScreenShot;
public ExampleForm()
{
this.SetStyle(ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint | ControlStyles.UserPaint, true);
this.FormBorderStyle = FormBorderStyle.None;
this.WindowState = FormWindowState.Maximized;
this.TopMost = true;
this.DoubleBuffered = true;
this.ShowInTaskbar = false;
this.brush = new SolidBrush(Color.FromArgb(200, Color.Black));
Rectangle screenRc = Screen.PrimaryScreen.Bounds;
this.originalScreenShot = new Bitmap(screenRc.Width, screenRc.Height);
using (Graphics G = Graphics.FromImage(this.originalScreenShot))
{
G.CopyFromScreen(screenRc.Left, screenRc.Top, 0, 0, screenRc.Size);
}
Bitmap darkenedScreenshot = new Bitmap(this.originalScreenShot);
using (Graphics G = Graphics.FromImage(darkenedScreenshot))
{
G.FillRectangle(this.brush, screenRc);
}
this.BackgroundImageLayout = ImageLayout.None;
this.BackgroundImage = darkenedScreenshot;
}
protected override void OnMouseDown(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
this.startDrag = e.Location;
}
}
protected override void OnMouseUp(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
// ... do something with "selectionRc" in here? ...
}
}
protected override void OnMouseMove(MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
this.selectionRc = new Rectangle(
Math.Min(this.startDrag.X, e.Location.X),
Math.Min(this.startDrag.Y, e.Location.Y),
Math.Abs(this.startDrag.X - e.Location.X),
Math.Abs(this.startDrag.Y - e.Location.Y)
);
this.Invalidate();
}
}
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = e.Graphics;
g.DrawImage(this.originalScreenShot, this.selectionRc, this.selectionRc, GraphicsUnit.Pixel);
}
}
推荐阅读
- arrays - 获取数字数组元素的前 5 个字符
- java - 使用流计算对象的多个字段
- ios - 存档失败:将 Xcode 从 9.1 更新到 10.1 后
- spring-boot - 使用 Java 和 CloudWatch 触发器安排 AWS-Lambda
- powershell-v5.1 - 函数的基于注释的帮助不显示
- javascript - 使用表中的 javascript 根据用户 ID 更改颜色
- sql - 重新排序类别 - SQL 案例
- react-native - 构建 React Native 项目时出错
- javascript - 如何删除所有其他元素上的类,除了被点击的元素
- python - Django模板变量字符串为html