2015-03-03 22 views
0

如何保留我绘制在绘图盒上的绘画?在调整大小或刷新后保留绘画

我画了一个圆圈,并通过ExtFloodFill API填充它。 这工作正常。

当我调整窗体大小(或最小化)并将其大小调整回原始大小时,部分绘画消失了。

CompleteResizedMissing part

当我刷新图片框画会完全消失

我试图重新绘制它的Paint事件,但是这造成它不断为自己引发的绘画重绘绘画事件也是如此。

请参阅下面的测试项目。

  • 当您单击图片框时,绘画将被绘制。
  • 当你双击画框时会刷新。

[1个表格1个PictureBox的命名pictureBox1]

using System; 
using System.Drawing; 
using System.Windows.Forms; 
using System.Runtime.InteropServices; 


namespace FloodFill 
{ 
    public partial class Form1 : Form 
    { 
     [DllImport("gdi32.dll")] 
     public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj); 
     [DllImport("gdi32.dll")] 
     public static extern IntPtr CreateSolidBrush(int crColor); 
     [DllImport("gdi32.dll")] 
     public static extern bool ExtFloodFill(IntPtr hdc, int nXStart, int nYStart, int crColor, uint fuFillType); 
     [DllImport("gdi32.dll")] 
     public static extern bool DeleteObject(IntPtr hObject); 
     [DllImport("gdi32.dll")] 
     public static extern int GetPixel(IntPtr hdc, int x, int y); 
     public static uint FLOODFILLSURFACE = 1; 

     public Form1() 
     { 
      InitializeComponent(); 
     } 

     private void pictureBox1_Click(object sender, EventArgs e) 
     { 
      DrawCircle(); 
      FillGreen(); 
     } 

     private void DrawCircle() 
     { 
      Graphics graBox = Graphics.FromHwnd(pictureBox1.Handle); 
      graBox.DrawEllipse(Pens.Red, 10, 10, 100, 100); 
     } 

     private void FillGreen() 
     { 
      Graphics graBox = Graphics.FromHwnd(pictureBox1.Handle); 
      IntPtr ptrHdc = graBox.GetHdc(); 
      IntPtr ptrBrush = CreateSolidBrush(ColorTranslator.ToWin32(Color.Green)); 
      SelectObject(ptrHdc, ptrBrush); 
      ExtFloodFill(ptrHdc, 50, 50, GetPixel(ptrHdc, 50, 50), FLOODFILLSURFACE); 
      DeleteObject(ptrBrush); 
      graBox.ReleaseHdc(ptrHdc); 
     } 

     private void pictureBox1_DoubleClick(object sender, EventArgs e) 
     { 
      pictureBox1.Refresh(); 
     } 

    } 
} 

我怎样才能保持我画画的时候做我的窗体或PictureBox的调整大小或以任何其他方式被刷新?

[编辑]

我改变了我的Paint事件如下:

private void pictureBox1_Paint(object sender, PaintEventArgs e) 
    { 
     DrawCircle(); 
     FillGreen(); 
    } 

而现在的圆圈是大小后重绘正,但此时,floodFill不是

paint event

(我还给了picturebox一个浅蓝色的背景作为另一个测试)

[EDIT2]

我改变Paint事件使用Graphics克如下:

private void pictureBox1_Paint(object sender, PaintEventArgs e) 
    { 
     Graphics g = e.Graphics; 
     DrawCircle(g); 
     FillGreen(g); 
    } 

    private void DrawCircle(Graphics g) 
    { 
     g.DrawEllipse(Pens.Red, 10, 10, 100, 100); 
    } 

    private void FillGreen(Graphics g) 
    { 
     IntPtr ptrHdc = g.GetHdc(); 
     IntPtr ptrBrush = CreateSolidBrush(ColorTranslator.ToWin32(Color.Green)); 
     SelectObject(ptrHdc, ptrBrush); 
     ExtFloodFill(ptrHdc, 50, 50, GetPixel(ptrHdc, 50, 50), FLOODFILLSURFACE); 
     DeleteObject(ptrBrush); 
     g.ReleaseHdc(ptrHdc); 
    } 

但是,当我调整回原来的大小此时,floodFill的一些行被跳过,尤其是当我调整慢慢

graphics missing lines

+0

你需要使用绘图参数中的e.Graphics绘制或绘制事件。图片框的图像位图。使用从位图创建的图形!其他任何东西都不会像你所看到的那样持续下去。我也看不出为什么你不使用gdi +绘图,假设你正在使用winforms .. – TaW 2015-03-03 11:58:14

+0

我来自VB6,并试图将我的应用程序转换为C#...我编辑我的问题添加一个新的Paint事件我试过,其结果是:圆圈现在正在重绘,但填充不是 – Hrqls 2015-03-03 12:52:48

+0

您能否解释如何使用Paint参数中的e.Graphics?和我做什么相比,gdi +绘图呢? – Hrqls 2015-03-03 12:54:08

回答

1

使用GDI +方法绘制的代码很简单:

private void pictureBox1_Paint(object sender, PaintEventArgs e) 
{ 
    Rectangle rect = new Rectangle(10, 10, 100, 100); 
    e.Graphics.FillEllipse(Brushes.Green, rect); 
    using (Pen pen = new Pen(Color.Red, 2f)) 
    { 
     e.Graphics.DrawEllipse(pen , rect); 
    } 
} 

您根本不需要DllImport或常量。

注意,我选择使用一个笔与2f的宽度,以演示使用using子句的正确创建和GDI+(非标准)的对象的处置Pen

这将持续存在,因为它是在需要时绘制。要画出它,最初你必须拨打pictureBox1.Invalidate();一次!

如果你想改变坐标,你应该将变量rect移动到课程级别,将其设置为新的数据,并且在PictureBox上调用Invalidate!这同样适用于ColorsPen.Width:使用类级的变量和每次更改后调用Invalidate()触发Paint事件..

一旦你明白,学习GDI+绘制的最重要的部分是做..

为了填充任何图纸,你有三种选择:

  • 简单的形状与DrawXXX方法都画有FillXXX方法。
  • 可以使用GraphicsPath创建复杂的形状,它同时具有DrawXXX方法和FillXXX方法。
  • 区域不是由形状创建的,而是由绘制的像素创建的,必须填充填充方法。 GDI+中没有内置输入,但可以简单地编写自己的输入。也许像the Fill4 in this answer ..

更新:如果你感觉更好用FloodFillgdi32.dll你可以这样做,但请更改代码使用Graphics对象从Paint事件:

FillGreen(e.Graphics); 

private void FillGreen(Graphics graBox) 
{ 
    IntPtr ptrHdc = graBox.GetHdc(); 
    IntPtr ptrBrush = CreateSolidBrush(ColorTranslator.ToWin32(Color.Green)); 
    SelectObject(ptrHdc, ptrBrush); 
    ExtFloodFill(ptrHdc, 50, 50, GetPixel(ptrHdc, 50, 50), FLOODFILLSURFACE); 
    DeleteObject(ptrBrush); 
    graBox.ReleaseHdc(ptrHdc); 
} 

更好的灵活性,你可能可以使参数都动态,但我不习惯那个旧库。

请注意,次订购的来电事项FillXXX将涵盖由DrawXXX所画的部分像素,所以必须先到达。 FloodFill然而取决于边界线,在你的情况下,首先被绘制的圆,所以它必须在后面。

+0

感谢这个例子!最终,我想在picturebox(或其Graphics)上绘制位图(png文件),并动态地填充该位图的某些奇怪形状的区域...fillcolor将取决于我通过tcp连接接收到的数据 – Hrqls 2015-03-03 14:36:44

+0

为我的java applet创建了我自己的floodfill方法,但工作正常,但在我的VB6程序中使用了ExtFloodFill API ... VB6程序进一步开发比java小应用程序,所以我想转换那一个......它很容易在VB6中使用ExtFloodFill API :-) – Hrqls 2015-03-03 14:39:38

+0

DrawImage方法用于位图上的绘图。填充你可能确实需要一个填充方法,就像链接中的一个.. – TaW 2015-03-03 14:40:50

相关问题