将图形绘制到用户控件时出现问题

发布于 2024-07-09 19:12:22 字数 777 浏览 11 评论 0原文

我的应用程序弹出一个窗体作为主窗体的子窗体。 表格上有
带有渲染图形的面板的用户控件。 执行时 在调试模式下的 Visual Studio 中,绘图通常会按预期呈现, 想象一个简单的 XY 图。 如果面板的图形未绘制,则添加 绘图例程的两个或三个断点通常可以解决问题。

当在 Visual Studio 中以发布模式执行时,或在任何模式下从 .exe 中执行时, 尽管用户控件的 Paint 方法是 叫。 当然,调整表单大小会导致重新调用重绘, 现在图像已正确渲染。

谁能给我一些关于行为差异的见解 在调试和发布模式之间,从 VS 内部执行到 VS 外部执行, 为什么断点有时可以解决问题? 我怎样才能得到 图形始终可见。

谢谢,

里克

替代文本 http://img160.imageshack.us/my.php ?image=profilebeforeresizeti4.png替代文本 http://img512。 imageshack.us/my.php?image=profileafterresizeenw2.png

My application pops a form as a child of the main form. On the form is
User Control with a Panel where Graphics are rendered. When executed
from Visual Studio in debug mode the drawing is often rendered as expected,
imagine a simply XY graph. If the panel's graphic aren't drawn then adding
two or three break points to the drawing routines usually fix the problem.

When executed inside Visual Studio in release mode, or from the.exe in any mode,
the graphics are never rendered, although the user control's Paint method is
called. Resizing the form cause the repaint to be called again, of course,
and the image is now rendered correctly.

Can anyone give me some insight as to why there's a difference in the behavior
between Debug and Release modes, from execution within VS and out side VS,
any why are the break points sometimes fixing things? And how can I get the
graphics to be consistently visible.

Thanks,

Rick

alt text http://img160.imageshack.us/my.php?image=profilebeforeresizeti4.pngalt text http://img512.imageshack.us/my.php?image=profileafterresizenw2.png

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

初雪 2024-07-16 19:12:22

如果没有更多信息,我无法确定为什么您会看到行为差异(我建议您看到同样的问题,因为您承认调试版本并不总是有效),但您可能会发现断点会通常“修复”绘画问题,因为切换回 Visual Studio 最终会使整个绘画表面(而不是一小部分)失效。 因此,您启动应用程序,但它没有正确绘制,您在 Visual Studio 中命中断点,切换查看一些变量,返回到应用程序,它的绘制正确,因为 OnPaint 是使用正确的剪切矩形调用的,以重新绘制整个表面(通常也调用 OnPaintBackground,见下文)。

如果是这种情况,您应该能够通过最小化和恢复应用程序在发布版本中复制它。 如果这“修复”了控件的显示,那么很可能是由于您的绘制方法出现问题而导致的,假设它正在绘制整个控件,但事实可能并非如此。

您还可以查看 PaintBackground 以确保正确擦除控件的表面。 您可能会留下旧的显示器,然后在其上重新绘制,而不是从“新”画布开始。

根据您对正在发生的情况的描述以及重新绘制的方式,这些是我最好的建议。 我需要一些更具体的细节(绘制代码、所发生情况的具体描述 - 控件是否未绘制或仅显示部分等)以提供更准确的帮助。

Without more information I can't say for sure why you are seeing the difference in behavior (I would suggest you are seeing the same problem since you admit that the debug version doesn't always work either), but you may find that breakpoints will often "fix" paint problems because switching back to Visual Studio ends up invalidating the entire painting surface, as opposed to just a small part. So you bring up the application and its not painting correctly, you hit a breakpoint in visual studio, switch over look at some variables, go back to the application and its painted correctly because OnPaint was called with the proper clipping rectangle to repaint the entire surface (and OnPaintBackground is also usually called, see below).

If this is the case, you should be able to replicate it in the release version by minimizing and restoring your application. If that "fixes" the display of your control, then it is likely caused by a problem with your paint method assuming that it is painting the entire control when it may not be.

You might also look into PaintBackground to make sure that you are erasing your control's surface properly. It is possibly that you are leaving your old display and then repainting on top of it instead of starting from a "fresh" canvas.

Based on your description of what is going on, and the ways that you make it redraw, those are my best suggestions. I would need some more specific details (Paint code, specific description of what happens - is the control not drawn or does it display only parts, etc.) to provide any more accurate help.

青巷忧颜 2024-07-16 19:12:22

我只是尝试了一下,它在发布模式下达到了我的预期。 。 。 它用蓝色和一个大的黄色椭圆填充面板。 请发布重现问题所需的最少量示例代码。 。 。 也许是基于下面的 MyPanel 构建的。

计时器的作用是确保我们不会过于频繁地重绘。 这是一个自动终止计时器,强制重新绘制整个控件。 这是必需的,因为自定义绘制的内容随控件大小变化。

   public class MyPanel : Panel
    {
        Timer _resizeRedrawDelayTimer = new Timer();
        public MyPanel()
        {
            _resizeRedrawDelayTimer.Interval=50;
            _resizeRedrawDelayTimer.Tick += new EventHandler(_resizeRedrawDelayTimer_Tick);
        }

        void _resizeRedrawDelayTimer_Tick(object sender, EventArgs e)
        {
            Invalidate();
            _resizeRedrawDelayTimer.Stop();
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            // don't redraw if still resizing.
            if (!_resizeRedrawDelayTimer.Enabled)
            {
                e.Graphics.FillRectangle(Brushes.Blue, this.ClientRectangle);
                e.Graphics.FillEllipse(Brushes.Yellow, this.ClientRectangle);
            }
            base.OnPaint(e);
        }

        protected override void OnResize(EventArgs eventargs)
        {
            if (_resizeRedrawDelayTimer.Enabled)
                _resizeRedrawDelayTimer.Stop();
            // restart the timer.
            _resizeRedrawDelayTimer.Start();
            base.OnResize(eventargs);
        }
    }

I just gave this a whirl and it did what I expected in release mode. . . it fills the panel with the color Blue and a big yellow ellipse. Please post the minimum amount of example code that is required to reproduce the problem. . . perhaps building off of MyPanel below.

The role of the timer is to ensure we're not redrawing too often. It's a self-terminating timer which forces a repaint of the whole control. This is needed because the custom drawn content sizes with the control.

   public class MyPanel : Panel
    {
        Timer _resizeRedrawDelayTimer = new Timer();
        public MyPanel()
        {
            _resizeRedrawDelayTimer.Interval=50;
            _resizeRedrawDelayTimer.Tick += new EventHandler(_resizeRedrawDelayTimer_Tick);
        }

        void _resizeRedrawDelayTimer_Tick(object sender, EventArgs e)
        {
            Invalidate();
            _resizeRedrawDelayTimer.Stop();
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            // don't redraw if still resizing.
            if (!_resizeRedrawDelayTimer.Enabled)
            {
                e.Graphics.FillRectangle(Brushes.Blue, this.ClientRectangle);
                e.Graphics.FillEllipse(Brushes.Yellow, this.ClientRectangle);
            }
            base.OnPaint(e);
        }

        protected override void OnResize(EventArgs eventargs)
        {
            if (_resizeRedrawDelayTimer.Enabled)
                _resizeRedrawDelayTimer.Stop();
            // restart the timer.
            _resizeRedrawDelayTimer.Start();
            base.OnResize(eventargs);
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文