问题
I have a control with a PictureBox within it. The PictureBox displays an image (in Zoom mode, at least in this particular case). I need to do two kinds of things:
- Click with the mouse and find out which pixel of the image I hit
- Draw a vertical line over the PictureBox at a given column in the image.
Obviously, I need some kind of coordinate transformations between the control coordinates and the (row, column) of the pixel in the image. The first one I may have found (www.codeproject.com/Articles/20923/Mouse-Position-over-Image-in-a-PictureBox), but not the vice versa. Any ideas?
回答1:
I can suggest a "workaround": you do not draw lines etc. on the PictureBox, but, instead, on the bitmap itself, using its Graphics. Then you can only use the image coordinates (row, column) and do not need to convert from control to image. The other way round (from mouse click to row and column), as you mention, is solved and can be used.
回答2:
After a few attempts to draw graphical elements on the bitmap rather than on containing PictureBox I found this approach clumsy: it poses more problems than it solves. I returned to TaW's proposal (This Posting, function SetImageScale(PictureBox pbox, out RectangleF rectImage, out float zoom)
.)
If you know the rectImage
rectangle (ImgArea
in TaW's code), both conversions (to the control's coordinates and to the column and row of the image are then rather simple:
/// <summary>
/// Converts coordinates of a point from the picture box grid into column and row of its image.
/// </summary>
/// <param name="pb">The PictureBox.</param>
/// <param name="ptControl">The point in picture box coordinates (X, Y).</param>
/// <returns>Point in image coordinates (column, row).</returns>
private Point ToImageCoordinates(PictureBox pb, Point ptControl)
{
if (pb.Image == null)
{
return new Point(Int32.MinValue, Int32.MinValue);
}
float deltaX = ptControl.X - rectImage.Left;
float deltaY = ptControl.Y - rectImage.Top;
int column = (int)(deltaX * (pb.Image.Width / rectImage.Width) + 0.5);
int row = (int)(deltaY * (pb.Image.Height / rectImage.Height) + 0.5);
return new Point(column, row);
}
/// <summary>
/// Converts coordinates of a point from the grid (column, row) into the coordinate system of the picture box.
/// </summary>
/// <param name="pb">The PictureBox.</param>
/// <param name="ptImage">The point in image coordinates (column, row).</param>
/// <returns>Point in control coordinates (X, Y).</returns>
private PointF ToControlCoordinates(PictureBox pb, Point ptImage)
{
if (pb.Image == null)
{
return new Point(Int32.MinValue, Int32.MinValue);
}
float deltaX = ptImage.X * (rectImage.Width / pb.Image.Width);
float deltaY = ptImage.Y * (rectImage.Height / pb.Image.Height);
return new PointF(deltaX + rectImage.Left, deltaY + rectImage.Top);
}
The functions were tested and seem to do what they should.
Remember: these conversions are only valid if the PictureBox is in the Zoom
mode.
来源:https://stackoverflow.com/questions/52278722/c-sharp-windowsforms-picturebox-transformation-between-control-coordinates-and