Reputation: 1253
ControlPaint.DrawBorder3D draws correctly at 100% but it is wrong if the zooming is less or more than 100%. It seems like it still draws with 100%. ControlPaint.DrawBorder is correct in all cases.
I found a similar post with the same problem but no solution yet: http://www.44342.com/dotnet-framework-f70-t8279-p1.htm and http://www.pcreview.co.uk/forums/differences-between-drawborder3d-and-drawborder-t1313989.html
Is this a known issue? Is there any workaround, other than using DrawBorder instead of DrawBorder3D?
Update: Here's a code sample for the scale transformation with DrawBorder3D and DrawBorder (the form has 2 buttons to zoom in and out, a PictureBox for the image and a label to display the current zoom). Watch what happens to the two borders when zooming: the red border adapts to the zoom factor but the 3D border won't change.
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;
}
}
I didn't have much time and I can't post our productive code so this example is adapted from http://tjclifton.com/2012/03/13/zooming-an-image-in-windows-forms/.
Upvotes: 0
Views: 400
Reputation: 96
It seems that the DrawBorder3D method ignores all graphics transformations. e.g. in the following code, the first rectangle is not rotated but the second one is.
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);
}
I guess you could read the zoom factor from the current world Transformation Matrix (if you only have zooming) and scale manually the rectangle which you are using to draw the 3d border...something along the lines of
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);
}
Upvotes: 1
Reputation: 73502
Not sure why that doesn't work. Whatever you do with Graphics
instance gets scaled, DrawBorder
just draws border with Graphics.DrawRectangle
method internally(which gets scaled) as opposed to DrawBorder3D
which uses DrawEdge win32 api (which doesn't).
As a workaround you could manually scale the rectangle and pass it to 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;
}
Scale method is taken from Reference Source
Upvotes: 1