ControlPaint.DrawBorder3D缩放时的位置和大小错误

时间:2014-10-06 14:56:41

标签: winforms

ControlPaint.DrawBorder3D以100%正确绘制,但如果缩放小于或大于100%则错误。它似乎仍然100%吸引。 ControlPaint.DrawBorder在所有情况下都是正确的。

我发现了一个类似的帖子但问题相同但尚无解决方案:http://www.44342.com/dotnet-framework-f70-t8279-p1.htmhttp://www.pcreview.co.uk/forums/differences-between-drawborder3d-and-drawborder-t1313989.html

这是一个已知问题吗?除了使用DrawBorder而不是DrawBorder3D之外,还有其他解决方法吗?

更新:以下是使用DrawBorder3D和DrawBorder进行比例转换的代码示例(表单有2个放大和缩小的按钮,图像的PictureBox和显示当前缩放的标签) 。观察缩放时两个边框会发生什么:红色边框适应缩放系数,但3D边框不会改变。

public partial class Form1 : Form
{
    private Image image;
    float currentZoom = 100.0f;
    float zoom = 1.0f;
    const int zoomIncrement = 10;

    public Form1()
    {
        InitializeComponent();

        const string fileName = @"C:\30400988_1506.jpg";
        image = Image.FromFile(fileName);
        pictureBox.Paint += pictureBox_Paint;
        lblCurrentZoom.Text = string.Empty;
    }

    private void pictureBox_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.ScaleTransform(zoom, zoom);
        e.Graphics.DrawImage(image, 0, 0, image.Width, image.Height);

        var units = GraphicsUnit.Pixel;
        var rectangle = Rectangle.Round(image.GetBounds(ref units));

        ControlPaint.DrawBorder3D(e.Graphics, rectangle, Border3DStyle.Sunken);
        ControlPaint.DrawBorder(e.Graphics, rectangle, Color.Red, ButtonBorderStyle.Solid);
    }

    private void btnZoomIn_Click(object sender, EventArgs e)
    {
        SetZoom(currentZoom + zoomIncrement);
        pictureBox.Invalidate();
        lblCurrentZoom.Text = "current zoom: " + zoom.ToString("p");
    }

    private void btnZoomOut_Click(object sender, EventArgs e)
    {
        SetZoom(currentZoom - zoomIncrement);
        pictureBox.Invalidate();
        lblCurrentZoom.Text = "current zoom: " + zoom.ToString("p");
    }

    private void SetZoom(float zoomPercentage)
    {
        zoom = zoomPercentage / 100.0f;
        if (zoom < 0.1f)
        {
            zoom = 0.1f;
        }
        currentZoom = zoom * 100.0f;
    }
}

我没有太多时间,我无法发布我们的高效代码,因此这个示例改编自http://tjclifton.com/2012/03/13/zooming-an-image-in-windows-forms/

2 个答案:

答案 0 :(得分:1)

不确定为什么不起作用。无论您使用Graphics实例进行缩放,DrawBorder只是在内部使用Graphics.DrawRectangle方法绘制边框(进行缩放),而不是使用DrawEdge win32的DrawBorder3D api(没有)。

作为一种解决方法,您可以手动缩放矩形并将其传递给DrawBorder3D

protected override void OnPaint(PaintEventArgs e)
{
    base.OnPaint(e);

    int scaleX = 2;
    int scaleY = 2;

    Graphics g = e.Graphics;
    g.ScaleTransform(scaleX, scaleY);//Scale

    Rectangle rectangle = new Rectangle(10, 10, 60, 40);
    g.FillEllipse(Brushes.Gray, rectangle);

    var scaledRectangle = Scale(rectangle, scaleX, scaleY);//Scale the border manually
    ControlPaint.DrawBorder3D(g, scaledRectangle);//Note the use of scaled rectangle instead of actual rectangle.
}

private Rectangle Scale(Rectangle rectangle, int scaleX, int scaleY)
{
    if (rectangle.IsEmpty)
    {
        return rectangle;
    }

    rectangle.X *= scaleX;
    rectangle.Y *= scaleY;
    rectangle.Width *= scaleX;
    rectangle.Height *= scaleY;

    // If the scale in the X dimension is negative, we need to normalize X and Width
    if (scaleX < 0)
    {
        // Make X the left-most edge again
        rectangle.X += rectangle.Width;

        // and make Width positive
        rectangle.Width *= -1;
    }

    // Do the same for the Y dimension
    if (scaleY < 0)
    {
        // Make Y the top-most edge again
        rectangle.Y += rectangle.Height;

        // and make Height positive
        rectangle.Height *= -1;
    }

    return rectangle;
}

缩放方法取自Reference Source

答案 1 :(得分:1)

似乎DrawBorder3D方法忽略了所有图形转换。例如在下面的代码中,第一个矩形没有旋转,第二个矩形是。

private void Form1_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.RotateTransform(30.0f);
        var rect = new Rectangle(10, 10, 100, 200);
        var rect2 = new Rectangle(300,10,100,200);
        // ignores the rotate transformation
        ControlPaint.DrawBorder3D(e.Graphics, rect, Border3DStyle.SunkenOuter, Border3DSide.All);
        // draws with rotate transformation
        ControlPaint.DrawBorder(e.Graphics, rect2, Color.Black, ButtonBorderStyle.Outset);
    }

我猜你可以从当前世界转换矩阵中读取缩放系数(如果你只有缩放)并手动缩放你用来绘制3d边框的矩形...

    private void Form1_Paint(object sender, PaintEventArgs e)
    {
        e.Graphics.ScaleTransform(1.5f,1.5f);
        var rect = new Rectangle(10, 10, 100, 200);
        var rect2 = new Rectangle(300, 10, 100, 200);
        // scale the rectangle
       var scaleFactor = e.Graphics.Transform.Elements[0];

        rect.X = (int)(rect.X * scaleFactor);
        rect.Y = (int)(rect.Y * scaleFactor);
        rect.Width = (int)(rect.Width * scaleFactor);
        rect.Height = (int)(rect.Height * scaleFactor);

        ControlPaint.DrawBorder3D(e.Graphics, rect, Border3DStyle.SunkenOuter, Border3DSide.All);
        ControlPaint.DrawBorder(e.Graphics, rect2, Color.Black, ButtonBorderStyle.Outset);
    }