无法在全屏表单的底部或右侧绘制

时间:2011-12-23 10:46:04

标签: c# .net winforms graphics

下面的代码应该是从全屏表单的顶部到底部绘制线条。

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

欢迎任何人创建一个空项目,设置表单属性(最大化,最顶层,无边框)并复制粘贴此代码以重现我遇到的问题。

3 个答案:

答案 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);
  }

}

差异:

enter image description here

答案 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));
        }
    }
}