简体   繁体   English

调整表单大小时,为什么线条没有穿过图像的同一部分?

[英]Why do the lines not cross the same part of the image when the form is resized?

I'm creating a program that uses the flycapture camera. 我正在创建一个使用抓拍相机的程序。 I've created a class that extends the pictureBox class in order to draw a crosshair, consisting of two lines, onto the screen. 我创建了一个扩展pictureBox类的类,以便在屏幕上绘制由两行组成的十字准线。 I want to be able to move the crosshair from the center to any other location on the screen. 我希望能够将十字准线从中心移动到屏幕上的任何其他位置。

The problem is when the form is resized, the crosshair moves to a different location as shown here . 问题是,当所述形式的大小时,如所示的十字准线移动到一个不同的位置在这里 I want the crosshair to be pointing at the same part of the image as before it was resized (in the example it is no longer pointing at the grey mesh). 我希望十字准线指向与调整大小之前图像相同的部分 (在示例中,它不再指向灰色网格)。 I'm drawing the crosshair in relation to the height and width of the pictureBox . 我正在根据pictureBox的高度和宽度绘制十字准线。 I want to be able to draw the lines on the image but the image height and width are always the same regardless of the image's size. 我希望能够在图像上绘制线条,但是无论图像的大小如何,图像的高度和宽度总是相同的。

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;


namespace FlyCapture2SimpleGUI_CSharp
{
    class IMSPictureBox : PictureBox
    {

        private Color colorSetting = Color.Black;
        private float width = 1.0f;

        public IMSPictureBox()
        {
            this.Paint += IMSPictureBox_Paint;
        }

        private void IMSPictureBox_Paint(object sender, PaintEventArgs e)
        {
            //Draw if image has loaded
            if (this.Image != null)
            {
                //Draw horizontal line
                e.Graphics.DrawLine(
                  new Pen(this.colorSetting, this.width),
                  new Point(0, this.Size.Height / 2 + 100),
                  new Point(this.Size.Width, this.Size.Height / 2 + 100));

                //Draw vertical line
                e.Graphics.DrawLine(
                  new Pen(this.colorSetting, this.width),
                  new Point(this.Size.Width / 2 + 100, 0),
                  new Point(this.Size.Width / 2 + 100, this.Size.Height));
            }
        }
    }
}

Edit: As DiskJunky suggested, I'm now drawing on the image itself and not using the Paint function above. 编辑:如DiskJunky所建议,我现在在图像本身上绘图,而不使用上面的Paint函数。

Here is the image getting set: 这是要设置的图像:

private void UpdateUI(object sender, ProgressChangedEventArgs e)
{
    UpdateStatusBar();

    pictureBox1.SetImage = m_processedImage.bitmap;
    pictureBox1.Invalidate();
}

Here are the lines drawing on the image: 这是图像上绘制的线条:

public System.Drawing.Image SetImage
{
    set
    {
        using (Graphics g = Graphics.FromImage(value))
        {
            g.DrawLine(new Pen(Color.Red, 3.0f), new Point(0, 0), new Point(value.Width, value.Height));
            g.Dispose();
        }
        this.Image = value;
    }
    get
    {
        return this.Image;
    }
}

I now have a line that scales with the image, but now it's constantly flickering. 我现在有一条与图像成比例的线,但是现在它一直在闪烁。

This isn't exact but modifying to something like the following will keep the position static as the picture box resizes; 虽然不完全正确,但是修改为如下所示的内容将在图片框调整大小时保持位置不变;

class IMSPictureBox : PictureBox
{

    private Color colorSetting = Color.Black;
    private float width = 1.0f;
    private Tuple<Point, Point> _verticalLine;
    private Tuple<Point, Point> _horizontalLine;

    public IMSPictureBox()
    {
        this.Paint += IMSPictureBox_Paint;
    }

    private void IMSPictureBox_Paint(object sender, PaintEventArgs e)
    {
        //Draw if image has loaded
        if (this.Image != null)
        {
            //Draw vertical line
            if (_verticalLine == null)
            {
                _verticalLine = new Tuple<Point, Point>(new Point(100, 0), new Point(100, this.Size.Height);
            }
            e.Graphics.DrawLine(
              new Pen(this.colorSetting, this.width),
              _verticalLine.Item1,
              _verticalLine.Item2);

            //Draw horizontal line
            if (_horizontalLine == null)
            {
                _horizontalLine = new Tuple<Point, Point>(new Point(0, 100), new Point(this.Size.Width, 100);
            }
            e.Graphics.DrawLine(
              new Pen(this.colorSetting, this.width),
              _horizontalLine.Item1,
              _horizontalLine.Item2);
        }
    }
}

Edit The above solution outlines the concept of preserving the line position. 编辑上面的解决方案概述了保留行位置的概念。 As per discussion in comments below, this developed into a more involved solution for the OP as additional requirements came out of investigating and testing the solution above for the original intent - to cleanly draw aa coordinate marker on an image. 根据下面的评论中的讨论,随着对上述解决方案进行调查和测试的最初意图(出于在图像上清晰地绘制坐标标记)的额外要求,该解决方案发展成为针对OP的更复杂解决方案。

To that end a manual double buffering mechanism is recommended in that scenario as the PictureBox control supports limited drawing capability itself. 为此,在这种情况下,建议使用手动双缓冲机制,因为PictureBox控件本身支持有限的绘图功能。 An example of manually implementing a double buffering solution can be found here; 可以在此处找到手动实现双缓冲解决方案的示例。 https://docs.microsoft.com/en-us/dotnet/framework/winforms/advanced/how-to-manually-render-buffered-graphics https://docs.microsoft.com/zh-cn/dotnet/framework/winforms/advanced/how-to-manually-render-buffered-graphics

Rather than calling DrawEllipse() there'll be calls to DrawLine() to display the coordinate marker. 与其调用DrawEllipse() ,不如调用DrawLine()来显示坐标标记。 One caveat is that if the image is still being displayed in the PictureBox then the PictureBoxSizeMode.Zoom value may still have to be accounted for. 一个警告是,如果图像仍在PictureBox中显示,则可能仍需要考虑PictureBoxSizeMode.Zoom值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM