Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# PictureBox.Invalidate未正确重新渲染_C#_Winforms - Fatal编程技术网

C# PictureBox.Invalidate未正确重新渲染

C# PictureBox.Invalidate未正确重新渲染,c#,winforms,C#,Winforms,我正在尝试构建一个小的测试应用程序(我的WinForm技能已经有些生锈),上面有一个图像和一些覆盖层 我的图像在PictureBox中设置为拉伸,但我右侧的字段希望来自图像的原点。因此,我决定直接在PictureBox使用的图像上渲染,以确保坐标始终正确。以下是白盒渲染: private void pbImage_Paint(object sender, PaintEventArgs e) { try { if (this.r

我正在尝试构建一个小的测试应用程序(我的WinForm技能已经有些生锈),上面有一个图像和一些覆盖层

我的图像在PictureBox中设置为拉伸,但我右侧的字段希望来自图像的原点。因此,我决定直接在PictureBox使用的图像上渲染,以确保坐标始终正确。以下是白盒渲染:

  private void pbImage_Paint(object sender, PaintEventArgs e)
    {
        try
        {
            if (this.rdFront.Checked)
                RenderFront(pbImage.Image, true);
            else
                RenderBack(pbImage.Image, true);

        }
        catch (ArgumentNullException ex)
        { }
    }

public void RenderFront(Image image, bool includeBoxes)
    {
        // If we have no image then we can't render
        if (image == null)
            throw new ArgumentNullException("image");

        Graphics gfx = Graphics.FromImage(image);

        // Get the top label
        foreach (MessageConfiguration config in this.config.Values.Where(c => c.Front))
        {
            if (includeBoxes)
            {
                // Fill a White rectangle and then surround with a black border
                gfx.FillRectangle(Brushes.White, config.X, config.Y, config.Width, config.Height);
                gfx.DrawRectangle(Pens.Black, config.X - 1, config.Y - 1, config.Width + 2, config.Height + 2);
            }

            gfx.DrawString(config.Text, new Font(FontFamily.GenericMonospace, config.FontSize), Brushes.Black, new PointF(config.X, config.Y));
        }
    }
我遇到的问题是,如果我这样做,并且总是在基础图像上绘制,那么当我移动白色覆盖层时,我最终会得到图像中未绘制的部分。因此,我决定在每次重新渲染之前克隆图像(基于我不关心性能)

因此,我决定在需要手动使图像无效时克隆图像,并在设置更改时调用此选项:

    public void Refresh()
    {
        if (this.rdFront.Checked)
            pbImage.Image = new Bitmap(front);
        else
            pbImage.Image = new Bitmap(back);

        this.pbImage.Invalidate();
    }
现在我确信我肯定遗漏了一些明显的东西——如果我修改企鹅渲染的值之一而没有覆盖。但是,如果我强制调整应用程序的大小,企鹅和覆盖层都会突然出现

有人能告诉我可能做错了什么吗

编辑


这里有一个项目的下载链接,因为它很小。将路径粘贴到“前图像”框中的图像,然后尝试使用右侧的控件(设置100x100高度和宽度)。尝试重新调整大小以查看所需的效果

控件和窗体已经有了
刷新
方法。你真的在调用你的
刷新
方法吗?难道你没有收到警告,说你应该使用
new
关键字吗?最好给你的
Refresh
方法起另一个名字(例如
RefreshImage


我真的不知道你为什么要用画框,然后决定画你的画。我建议在屏幕外绘制图像,然后简单地将其分配到图片框:

public void RefreshImage()
{
    Bitmap bmp;
    if (this.rdFront.Checked)
        bmp = new Bitmap(front);
    else
        bmp = new Bitmap(back);

    using (Graphics gfx = Graphics.FromImage(bmp)) {
        foreach (MessageConfiguration config in this.config.Values.Where(c => c.Front))
        {
            if (includeBoxes) {
                // Fill a White rectangle and then surround with a black border
                gfx.FillRectangle(Brushes.White, config.X, config.Y, config.Width, config.Height);
                gfx.DrawRectangle(Pens.Black, config.X - 1, config.Y - 1, config.Width + 2, config.Height + 2);
            }
            gfx.DrawString(config.Text, new Font(FontFamily.GenericMonospace, config.FontSize), Brushes.Black, new PointF(config.X, config.Y));
        }
    }

    pbImage.Image = bmp;
}
然后移除
pbImage\u Paint
方法


另一种可能是以另一种方式使用事件处理程序。调用绘制图像但保持图像本身不变的图片框的
base.Paint()
处理程序。而是使用
PaintEventArgs e
参数给出的
Graphics
对象在其上绘制。此图形对象表示图片框的客户端区域。这不会改变指定给图片框的位图,但仅在屏幕上绘制

private void pbImage_Paint(object sender, PaintEventArgs e)
{
    base.Paint(); // Paints the image
    if (this.rdFront.Checked)
        RenderFront(e.Graphics, true);
    else
        RenderBack(e.Graphics, true);
}

public void RenderFront(Graphics g, bool includeBoxes)
{
    foreach (MessageConfiguration config in this.config.Values.Where(c => c.Front)) {
        if (includeBoxes) {
            g.FillRectangle(Brushes.White, config.X, config.Y, config.Width, config.Height);
            g.DrawRectangle(Pens.Black, config.X - 1, config.Y - 1, config.Width + 2, config.Height + 2);
        }
        g.DrawString(config.Text, new Font(FontFamily.GenericMonospace, config.FontSize), Brushes.Black, new PointF(config.X, config.Y));
    }
}

我真的不完全理解这个问题。对不起。但是,为什么不直接在PictureBox中绘制呢?好的,如果您决定在
Image
中绘制,那么您需要绘制一次,缓存图像并显示它。无论何时更新值,都需要使缓存无效。另外,我也不确定
Refresh
方法中的
front
back
来自何处。@SriramSakthivel:front/back,因为我有两个图像可以切换。直接绘制到PictureBox的问题是坐标0,0可能不在图像上(因为PictureBox已经缩放并居中),而在图像上它会。@SriramSakthivel:我已经添加了项目的下载链接-认为它可能有用。这是真的-但不是问题所在。