【问题标题】:Getting the mouse position on a zoomed picture获取缩放图片上的鼠标位置
【发布时间】:2015-04-23 22:00:50
【问题描述】:

我正在创建一个截图制作器/上传器,一切都很好,但现在我想集成一些东西,比如油漆。所以首先我要创建铅笔功能。但是开始出现我可以绘制的问题:D 但不是我的鼠标位置。他占据了我的光标以外的位置?

所以问题是: 锄头在放大的图片框上获取鼠标位置?

我的代码:

private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
    {
        if (draw && pencil)
        {
            Graphics panel = Graphics.FromImage(ScreenShot);

            Pen pen = new Pen(Color.Black, 14);

            pen.EndCap = LineCap.Round;
            pen.StartCap = LineCap.Round;

            panel.DrawLine(pen, pX, pY, e.X, e.Y);

            pictureBox1.CreateGraphics().DrawImage(ScreenShot, pictureBox1.Width, pictureBox1.Height);

            pictureBox1.Invalidate();
        }
        Point p = pictureBox1.PointToClient(Cursor.Position);

        pX = p.X;
        pY = p.Y;
    }

【问题讨论】:

  • 您需要(至少)做以下两件事之一:a)计算从缩放世界到未缩放世界的点和/或 b)通过缩放图形对象以缩放模式绘制绘制。如果你学习this post,你可以在工作中看到两者。 - 对于 a) 你还需要缩放笔的宽度! (尽可能对所有数字使用浮点数!!)。顺便说一句:无需使用 PointToClient - 使用 e.Location 等参数并将它们除以缩放因子!
  • 并且不要在MouseMove中绘制,在Paint事件中绘制。在 MouseMove 中,您存储在绘制事件中绘制的点的坐标等。并且在您知道自己在做什么之前不要创建 Graphics 对象,使用 Paint e.Graphics 参数中的那个并且不要命名 Graphics 对象面板,您在逗大家,很可能是从您自己开始
  • 收集点然后立即在 scalePoint 函数中转换它们并不是任何额外的工作。进入 GDI+ 中的图形模型确实有一定的学习曲线,但你不需要担心任何事情..
  • 谢谢奇怪的问题,但你可能有Skype。这就是我正在做的:playscripters.nl/topic/46 我正忙于另一个更新
  • 您的问题解决了吗?

标签: c# bitmap position mouse picturebox


【解决方案1】:

在缩放图像上使用鼠标时,报告的像素是缩放坐标。所以我们需要得到真实的像素..

在以某种方式设置之后..

float pbZoom = 3f;  // the factor by which the PictureBox is zoomed in or out

pictureBox.SizeMode = PictureBoxSizeMode.Zoom;
pictureBox.ClientSize = new Size((int)(pictureBox.Image.Width * pbZoom),
         (int)(pictureBox.Image.Height * pbZoom));

pictureBox.Paint     += pictureBox_Paint;
pictureBox.MouseDown += pictureBox_MouseDown;
pictureBox.MouseMove += pictureBox_MouseMove;
pictureBox.MouseUp   += pictureBox_MouseUp;

.. 您可以编写事件以在缩放的图像上绘制或绘制。

首先是一个辅助函数来取消对一个点的缩放:

PointF unZoomed(PointF pt) { return new PointF(pt.X / pbZoom, pt.Y / pbZoom );}

为简单起见,让我们在类级别保留一些内容:

PointF mDown    = PointF.Empty;   // mouse down point
PointF mCurrent = PointF.Empty;   // current mouse location

我们通过计算未缩放的e.Location来启动每个鼠标事件。

我们的测试会在表面上绘制一条直线移动的红线,直到您松开鼠标。然后那条线以绿色绘制到图像中。

MouseDown 只是存储起点,未缩放:

void pictureBox_MouseDown(object sender, MouseEventArgs e)
{
    mDown = unZoomed(e.Location);
}

在MouseMove中我们存储当前点并触发Paint事件:

void pictureBox_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button == System.Windows.Forms.MouseButtons.None) return;

    PointF e_ = unZoomed(e.Location);
    mCurrent = e_;
    pictureBox.Invalidate();
}

在MouseUp中我们画线到PictureBox的Image,改变它的像素;然后我们设置Image 并重置积分:

void pictureBox_MouseUp(object sender, MouseEventArgs e)
{
    Bitmap bmp = (Bitmap) pictureBox.Image;
    using (Graphics G = Graphics.FromImage(bmp))
    {
        G.SmoothingMode = SmoothingMode.HighQuality;
        G.DrawLine(Pens.Green, mDown, mCurrent);
     }
    mDown = PointF.Empty;
    mCurrent = PointF.Empty;
    pictureBox.Image = bmp;

}

我们使用Paint 事件在控制表面上绘图。要按比例绘制,我们使用Matrix..:

void pictureBox_Paint(object sender, PaintEventArgs e)
{
    Matrix scaleMatrix = new Matrix();
    scaleMatrix.Scale(pbZoom, pbZoom);
    e.Graphics.MultiplyTransform(scaleMatrix);
    e.Graphics.DrawLine(Pens.Red, mDown, mCurrent);
}

【讨论】:

    【解决方案2】:

    我也使用缩放图像。我只是使用此代码,它正在工作。因此,您可以在放大/缩小之前与位图(原始图像)进行比较。

    private void pbInput_MouseMove(object sender, MouseEventArgs e) { 
        if (pbInput.Image == null) {
            mouseY.Text = "";
            mouseX.Text = "";
        }
    
        else {
            Bitmap b = new Bitmap(pbInput.Image);
            int x = b.Width * e.X / pbInput.Width;
            int y = b.Height * e.Y / pbInput.Height;
    
            mouseX.Text = x.ToString();
            mouseY.Text = y.ToString();
        }
    }
    

    【讨论】:

      【解决方案3】:
      this.Cursor = new Cursor(Cursor.Current.Handle);
      
                  Size size1 = pictureBox1.Image.Size;
                  Size size2 = pictureBox1.Size;
      
      
                  float x1 = (float)size1.Width / ((float)size2.Width + 1);
                  float y1 = (float)size1.Height / ((float)size2.Height + 1);
      
                  float divisor = x1 >= y1 ? x1 : y1;
      
                  divisor = divisor > 0 ? divisor : 1;
      
                  Size imagesize = new Size((int)(size1.Width / divisor), (int)(size1.Height / divisor));
                  int ex = imagesize.Width - size2.Width >= 0 ? imagesize.Width - size2.Width : size2.Width - imagesize.Width;
                  int ey = imagesize.Height - size2.Height >= 0 ? imagesize.Height - size2.Height : size2.Height - imagesize.Height;
      
      
      
                  float ftx = ((float)size1.Width / (float)imagesize.Width) * ((float)(Cursor.Position.X - this.Location.X - pictureBox1.Location.X - (ex / 2) - 8));
                  float fty = ((float)size1.Height / (float)imagesize.Height) * ((float)(Cursor.Position.Y - this.Location.Y - pictureBox1.Location.Y - (ey / 2) - 31));
      
                  Point LOP = new Point(Convert.ToInt32(ftx), Convert.ToInt32(fty)); //point of cursos on picturebox image pixel ... 
      

      【讨论】:

        猜你喜欢
        • 2020-05-28
        • 2012-05-23
        • 2018-02-01
        • 2014-08-18
        • 2018-10-18
        • 2013-05-12
        • 1970-01-01
        • 2019-11-13
        • 2020-09-07
        相关资源
        最近更新 更多