用C#的GDI+来绘图时按下alt后发现绘制的全没了(窗体应用)
private void field_MouseDown(object sender, MouseEventArgs e)//用来记录点击鼠标时的指针位置
{
//if (type == 2)
//{
Brush brush = new SolidBrush(Color.Blue);
Point[] pts_tmp = new Point[4];
pts_tmp[0] = new Point(40, 40);
pts_tmp[1] = new Point(80, 40);
pts_tmp[2] = new Point(80, 80);
pts_tmp[3] = new Point(40, 80);
fill(pts_tmp);
//}
}
其中fill如下:
private void fill(Point[] pts_tmp)
{
Brush brush = new SolidBrush(Color.Blue);
g.FillPolygon(brush, pts_tmp);
}
g也进行了定义:
```c#
Graphics g;//这个语句是全局定义的
g = this.CreateGraphics();//这个语句是在field_Load执行的
点击按钮后再点击网格中任意一处生成了蓝色的块,效果如下:
但如果按下alt键后蓝块就消失了,效果如下:
绘制的网格不变,是因为鼠标的点击造成了什么吗?
谢谢
放个picture,在picture里绘制。
绘制的时机不对,在painter中绘制即可。
代码已经修改,参照一下代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO;
namespace WindowsForms
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
buffer = new Bitmap(this.Width, this.Height);
}
private void Form1_Load(object sender, EventArgs e)
{
//g = this.CreateGraphics();//这个语句是在field_Load执行的
}
//Graphics g;//这个语句是全局定义的
private Bitmap buffer; // 位图对象
private void Form1_Click(object sender, EventArgs e)
{
using (Graphics g = Graphics.FromImage(buffer))
{
Brush brush = new SolidBrush(Color.Blue);
Point[] pts_tmp = new Point[4];
pts_tmp[0] = new Point(40, 40);
pts_tmp[1] = new Point(80, 40);
pts_tmp[2] = new Point(80, 80);
pts_tmp[3] = new Point(40, 80);
g.FillPolygon(brush, pts_tmp);
}
this.Invalidate();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawImage(buffer, 0, 0);
}
}
}
你每次鼠标点击时,都调用CreateGraphics()来获取一个新的Graphics对象。
而按下Alt键会刷新窗口,导致之前的Graphics对象失效,所以绘制的内容就没有了
当窗口最小化或者按Alt建时,Form上的图画都会消失,原来这是因为最小化后还原时窗体要重绘,图画被覆盖消失。
解决方法有两个:一是在窗口Form的Paint事件中重新绘制图画;二是把图画在位图上,然后把位图赋给能显示图片的窗口或控件上。
一. 在窗口Form的Paint事件中重新绘制图画
具体做法就是把你绘图的代码写在Paint事件中
二. 把图画在位图上
重写窗体应用的PreProcessMessage方法来处理Alt键的按下,避免清除绘制的内容
引用chatgpt内容作答:
按下Alt键会触发窗体的系统菜单,这可能导致绘图被清除或隐藏。这是因为在窗体中使用CreateGraphics方法创建的Graphics对象是临时的,并不会持久保存绘图内容。当窗体需要重绘时,原先的绘图内容就会被清除。
为了解决这个问题,你可以使用以下方法之一:
在窗体的Paint事件中进行绘图:将绘图操作移动到窗体的Paint事件处理程序中,这样每次窗体重绘时都会执行绘图操作。你可以在field_Load事件处理程序中注册Paint事件的处理程序,或者直接在窗体的构造函数中添加。
public Form1()
{
InitializeComponent();
this.Paint += Form1_Paint;
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
// 在这里进行绘图操作
Brush brush = new SolidBrush(Color.Blue);
Point[] pts_tmp = new Point[4];
pts_tmp[0] = new Point(40, 40);
pts_tmp[1] = new Point(80, 40);
pts_tmp[2] = new Point(80, 80);
pts_tmp[3] = new Point(40, 80);
e.Graphics.FillPolygon(brush, pts_tmp);
}
使用双缓冲绘图:创建一个临时的Bitmap对象,在其上进行绘图操作,然后将绘制结果复制到窗体的CreateGraphics返回的Graphics对象上。这样可以避免窗体重绘时绘图被清除。
private Bitmap buffer; // 用于双缓冲绘图的位图对象
public Form1()
{
InitializeComponent();
buffer = new Bitmap(this.Width, this.Height);
}
private void field_MouseDown(object sender, MouseEventArgs e)
{
using (Graphics g = Graphics.FromImage(buffer))
{
Brush brush = new SolidBrush(Color.Blue);
Point[] pts_tmp = new Point[4];
pts_tmp[0] = new Point(40, 40);
pts_tmp[1] = new Point(80, 40);
pts_tmp[2] = new Point(80, 80);
pts_tmp[3] = new Point(40, 80);
g.FillPolygon(brush, pts_tmp);
}
using (Graphics g = this.CreateGraphics())
{
g.DrawImage(buffer, 0, 0);
}
}
使用双缓冲绘图的方法会将绘图内容保存在位图对象中,并在需要时进行绘制,因此按下Alt键时绘图不会被清除。