Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
放大C#Winforms中面板的中间部分_C#_Winforms_Zooming_Panel - Fatal编程技术网

放大C#Winforms中面板的中间部分

放大C#Winforms中面板的中间部分,c#,winforms,zooming,panel,C#,Winforms,Zooming,Panel,我有一个应用程序,我可以放大和缩小,唯一的问题是我想放大和缩小,但集中到面板的当前中间位置,而不是使用鼠标位置 有什么想法吗 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

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

有什么想法吗

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();
    }

谢谢

正如您所说,您的缩放逻辑是错误的。这是错误的,因为变换矩阵是如何工作的

变换矩阵会一个接一个地追加,如果您将图像转换为已缩放的位置,然后对其进行缩放,这将更改缩放原点,并且不会居中

如果有什么不对劲的话,我会在这里假设一些事情

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

因此,滚动条的范围是0到(panel.(with/height)-content.(width/height)),在本例中,滚动条的范围是0到100

让我们首先从一开始就把内容放在中心位置。为了使其居中,我们将TranslateTransform应用于图形对象,使可视区域大小的一半小于虚拟区域大小的一半:

e.Graphics.TranslateTransform(panel.With / 2 - content.Width / 2, panel.Height / 2 - content.Height / 2);
这将使绘图居中,但是,嘿!我们没有使用定位滚动条

好的,让我们应用这些滚动条偏移量。首先,我们以内容为中心,将这些滚动条的值设置为其最大值的一半,在我们的示例中,我们应该将其设置为50

现在,正如我们所说,转换是附加的,因此,没有任何东西会妨碍您添加新的TranslateTransform。您只能在一个调用中执行此操作,但为了简单起见,我们将在两个调用中执行此操作(而且,以后应用zoom会更好)

正如您所看到的,我们正在减去它的最大值的一半,我们的内容已经居中,所以当滚动条位于中心时,我们需要应用0的转换,我们将从-Maximum/2到Maximum/2,在本例中从-50到50

嗯,我们现在有一个虚拟内容区域在我们的屏幕中心,我们可以在上面移动,现在我们需要应用缩放

正如我看到的,您有一个滚动条,所以让我们按照我们的示例使用它

滚动条的范围将是您的选择,我看到您使用的是value/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);
好的,听起来不错,但是等等!它将惨败。为什么?因为当我们缩放虚拟大小时,虚拟大小也会根据视图区域(面板大小)进行缩放,所以我们需要将此缩放应用于内容大小(从而应用于滚动条值):

最后,我们有一个完全工作的虚拟区域,你可以通过它的边界进行缩放和置换

我对图形有点生疏,所以可能一些计算是错误的,我希望不会,无论如何,这将给你关于如何做这件事的一般想法

干杯


p.D.:如果您不想置换虚拟区域,只需缩放面板的中心,请跳过第二次平移变换;如果您想缩放虚拟区域的当前可见中心,请使用置换(不缩放它,变换已经具有此逻辑)而不是滚动条的值。

您说它在鼠标坐标上缩放,但在代码中没有对这些坐标的引用,因此,我想这段代码对于您的提问来说是非常不完整的对不起,我想说的是,有很多关于如何使用鼠标索引实现它的示例,但我只关心面板中间的固定位置。但是我会用我到目前为止写的更新代码写一个回复,请稍候。。。除息的
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);