ControlPaint.DrawBorder3D以100%正确绘制,但如果缩放小于或大于100%则错误。它似乎仍然100%吸引。 ControlPaint.DrawBorder在所有情况下都是正确的。
我发现了一个类似的帖子但问题相同但尚无解决方案:http://www.44342.com/dotnet-framework-f70-t8279-p1.htm和http://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/。
答案 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);
}