繁体   English   中英

放大C#Winforms中面板的中间位置

[英]Zoom into the middle of a panel in C# Winforms

我有一个可以放大和缩小的应用程序,只有我想放大和缩小的问题但是聚焦到面板位置的当前中间,而不是使用鼠标位置

有任何想法吗?

private void panel1_Paint(object sender, PaintEventArgs e)
{
    SolidBrush brushs = new SolidBrush(Color.White);
    e.Graphics.Clip = new Region(new Rectangle(0, 0, Viewer.Width, Viewer.Height));
    e.Graphics.FillRegion(brushs, e.Graphics.Clip);

    Graphics g = e.Graphics;
    g.TranslateTransform(_ImgX, _ImgY);
    g.ScaleTransform(_Zoom, _Zoom);
    g.SmoothingMode = SmoothingMode.AntiAlias;
    SolidBrush myBrush = new SolidBrush(Color.Black);
    Pen p = new Pen(Color.Red);
    foreach (CircuitData.ResistorRow resistorRow in ResistorData.Resistor)
    {
        RectangleF rec = new RectangleF((float)(resistorRow.CenterX  - resistorRow.Length/ 2), (float)(resistorRow.CenterY - resistorRow.Width/ 2), (float)resistorRow.Length, (float)resistorRow.Width);
        float orientation = 360 - (float)resistorRow.Orientation;
        PointF center = new PointF((float)resistorRow.CenterX, (float)resistorRow.CenterY);
        PointF[] points = CreatePolygon(rec, center, orientation);
        if (!Double.IsNaN(resistorRow.HiX) && !Double.IsNaN(resistorRow.HiY))
        {
            g.FillEllipse(myBrush, (float)resistorRow.HiX  - 2 , (float)resistorRow.HiY - 2, 4, 4);
            g.DrawLine(p, new PointF((float)resistorRow.HiX , (float)resistorRow.HiY ), center);
    }

    g.FillPolygon(myBrush, points);
}

}

更新缩放功能,我知道这是错误的,但如果有人可以帮助我修复逻辑或更好的想法。

    private void trackBar1_Scroll(object sender, EventArgs e)
    {
        float oldZoom = _Zoom;
        _Zoom = zoomTrackPad.Value / 10f;

        int x = Math.Abs(Viewer.Width / 2 );
        int y = Math.Abs(Viewer.Height / 2 );

        int oldImageX = (int)(x / oldZoom);
        int oldImageY = (int)(y / oldZoom);

        int newImageX = (int)(x / _Zoom);
        int newImageY = (int)(y / _Zoom);

        _ImgX = newImageX - oldImageX + _ImgX;
        _ImgY = newImageY - oldImageY + _ImgY;

        Viewer.Invalidate();
    }

谢谢

正如你所说,你的缩放逻辑是错误的。 由于转换矩阵的工作方式,这是错误的。

转换矩阵是一个接一个地附加的,在这种情况下,您正在翻译图像,就像它已经缩放的那样,然后你缩放它,这将改变缩放原点而不会居中。

我将在这里假设一些事情,如果有任何错误的pelase评论。

假设您的可见区域(面板大小)为100 * 100像素,并且您希望“虚拟”内容大小为200 * 200像素。 我认为你有两个滚动条来取代面板内的内容,如果你只是使用面板尺寸而没有滚动条,那么你应该调整计算位移的方式。

因此,您的滚动条的范围从0到(面板。(带/高度) - 内容。(宽度/高度)),在这种情况下,范围从0到100。

让我们首先将我们的内容集中在一开始。 为了使它居中,我们将TranslateTransform应用于Graphics对象,其可见区域的一半大小减去虚拟区域大小的一半:

e.Graphics.TranslateTransform(panel.With / 2 - content.Width / 2, panel.Height / 2 - content.Height / 2);

这将使绘图集中,但是,嘿! 我们没有使用定位滚动条!

Okokoko,让我们应用那些滚动条偏移量。 首先,当我们将内容集中在一起时,将这些滚动条的值设置为其最大值的一半,在我们的示例中,我们应将它们设置为50。

现在,正如我们所说,转换是附加的,因此,没有什么阻碍您添加新的TranslateTransform。 你只能在一次调用中完成这项工作,但为了简单起见,我们在两次调用中执行此操作(此外,稍后应用缩放会更好)。

e.Graphics.TranslateTransform(panel.With / 2 - content.Width / 2, panel.Height / 2 - content.Height / 2);
e.Graphics.TranslateTransform(hScrollBar1.Value - (hScrollbar1.Maximum / 2), vScrollBar1.Value - (vScrollbar1.Maximum / 2));

如你所见,我们正在减去其最大值的一半,我们已经将内容集中在一起,所以当滚动条位于中心时我们需要应用0的平移,我们的范围从-Maximum / 2到Maximum / 2,在此示例从-50到50。

好吧,我们现在有一个虚拟内容区域位于屏幕中心,我们可以替换它,现在我们需要应用该缩放。

我看到你有一个滚动条,所以让我们按照我们的例子使用它。

滚动条的范围将是您的选择,我看到您正在使用值/ 10f,因此如果您的滚动条范围从1到100,您将有0.1到10的缩放,这是一个很好的选择。

现在,让我们将此滚动条设置为10,以初始进行单一缩放。

现在是有趣的部分,转换按照您设置的顺序应用,因此翻译之前应用缩放比在之后应用缩放不同。

在我们的例子中,我们首先想要将内容居中,转换到我们想要看到的位置(滚动条值),然后缩放。

e.Graphics.TranslateTransform(panel.With / 2 - content.Width / 2, panel.Height / 2 - content.Height / 2);
e.Graphics.TranslateTransform(hScrollBar1.Value - (hScrollbar1.Maximum / 2), vScrollBar1.Value - (vScrollbar1.Maximum / 2));
float scale = zScrollBar.Value / 10f;
e.Graphics.ScaleTransform(scale, scale);

好的,听起来不错,但是等等! 它会悲惨地失败。 为什么? 因为当我们缩放时,我们的虚拟大小也会相对于视图区域(面板大小)进行放大,因此我们需要将此比例应用于内容大小(因此,应用于滚动条值):

float scale = zScrollBar.Value / 10f;
e.Graphics.TranslateTransform(panel.With / 2 - ((content.Width / 2) * scale), panel.Height / 2 - ((content.Height / 2) * scale));
e.Graphics.TranslateTransform((hScrollBar1.Value - (hScrollbar1.Maximum / 2)) * scale, (vScrollBar1.Value - (vScrollbar1.Maximum / 2)) * scale);
e.Graphics.ScaleTransform(scale, scale);

最后,我们有一个完全工作的虚拟区域,您可以通过它来缩放和移动它的边界。

我对图形有点生疏,所以也许有些计算是错误的,我希望不会,无论如何这会给你一般的想法如何做到这一点。

干杯!

PD:如果您不想替换虚拟区域并且只是缩放面板中心,请跳过第二个平移变换,如果您想放大虚拟区域的当前可见中心,也只需使用位移(没有缩放它,变换已经有了这个逻辑)而不是滚动条值。

暂无
暂无

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

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