下面的代码应该是从全屏表单的顶部到底部绘制线条。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
Graphics g;
public Form1()
{
InitializeComponent();
g = CreateGraphics();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
Pen pen = new Pen(Color.Black);
for (int i = 0; i < this.ClientSize.Height; i++)
{
g.DrawLine(pen, 100, i, 50, i);
}
}
}
}
有问题的表格(Form1)最大化,无边框和最顶层。代码的结果是,表格显示,线条一个接一个地绘制,但是当循环的数字i达到1055时,DrawLine开始不起作用,直到循环结束,从那时起,其他地方被绘制,因此有一个空白表格底部的空格。
一些额外信息
我的桌面分辨率为1920 x 1080
this.Size = 1920 x 1080
this.ClientSize = 1920 x 1080
欢迎任何人创建一个空项目,设置表单属性(最大化,最顶层,无边框)并复制粘贴此代码以重现我遇到的问题。
答案 0 :(得分:4)
这是固定代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication4
{
public partial class Form1 : Form
{
// Graphics g;
public Form1()
{
InitializeComponent();
// g = CreateGraphics();
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
Pen pen = new Pen(Color.Black);
for (int i = 0; i < this.ClientSize.Height; i++)
{
// g.DrawLine(pen, 100, i, 50, i);
e.Graphics.DrawLine(pen, 100, i, 50, i);
}
}
}
}
图形对象应立即使用然后处理。主要原因是,图形对象使用了真正的Windows设备上下文(HDC)。这是一个有限的资源,如果你在程序窗口中占用太多会关闭程序。如果你有太多的程序使用太多,你实际上会崩溃Windows的UI,或者至少是它的一部分,尽管每个后续版本的Windows都会添加保护以防止这种情况发生。在完成绘图时,需要使用.Dispose或using构造立即处理HDC ;当GC到达它时,你可以全部使用它们。
框架将在paint事件中为您创建Graphics和Dispose。所以当你画画(推荐)时,你不必处理图形。
无论何时在表单或Graphics.FromImage等上使用creategraphics,都应该尽快使用它并尽快处理它。
由于这种设计以及随之而来的要求,HDC会在抓取窗口时对窗口做出假设。在内部,窗口可以最大化或调整自身,然后再次进行绘制。 paint事件还从同一窗口句柄中抓取另一个 - 这是HDC的一种不寻常的用法 - 所以它可能是造成这种奇怪行为的问题之一。
答案 1 :(得分:2)
尝试使用Paint事件中的e.Graphics
而不是CreateGraphics()
方法。
示例:
private void Form1_Paint(object sender, PaintEventArgs e) {
// using your CreateGraphics:
Pen pen = new Pen(Color.Black);
for (int i = 0; i < this.ClientSize.Height; i++) {
g.DrawLine(pen, 100, i, 50, i);
}
// using e.Graphics:
for (int i = 0; i < this.ClientSize.Height; i++) {
e.Graphics.DrawLine(Pens.Black, 200, i, 250, i);
}
}
差异:
答案 2 :(得分:1)
据我所知,Windows Forms图形坐标在Y方向上是y = 0(最上边缘)到高度-1(最下边缘),x = 0(最左边缘)到宽度-1(最右边缘) )在X方向。
如果是这样,第一个例子将不起作用,因为您只是在可视区域之外绘制,但是第二个示例将在绘制垂直线时仅绘制可视区域之外的一个像素。
尝试更改为1079并查看是否呈现。如果做不到这一点,请尝试在第一个示例中递增y并找出它停止的位置。你有一些表格Chrome需要考虑吗?例如,高度= 1080的窗体窗体可能在标题栏和底边使用20个像素,因此实际可视区域可能更小。
修改1
在您的代码添加到问题后编辑。我修改了如下代码,它在我的系统上绘制了一个完美的矩形。出于兴趣,为什么要在表单的构造函数中创建图形对象?你应该使用paint事件args提供的那个。每次重新绘制表单时,.NET运行时都将创建和处理Graphics对象。
我还添加了一个resize事件处理程序来重新绘制表单。如果在调整大小时没有这个,则不会将矩形设置为新的表单大小。
你可以测试一下并告诉我你是否遇到同样的问题?我还缺少其他什么属性(即:Form.Borderstyle等)以获得与您相同的问题?
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
this.Paint += new PaintEventHandler(Form1_Paint);
this.Resize += new EventHandler(Form1_Resize);
}
void Form1_Resize(object sender, EventArgs e)
{
this.Invalidate(true);
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
using (Pen pen = new Pen(Color.Red, 2.0f))
{
e.Graphics.DrawRectangle(pen, new Rectangle(0, 0, ClientSize.Width-1, ClientSize.Height-1));
}
}
}