实现八个句柄调整区域大小的功能,包括光标切换和区域调整逻辑
This commit is contained in:
@@ -35,6 +35,13 @@ namespace JoyD.Windows.CS
|
|||||||
// 当前选中的区域索引
|
// 当前选中的区域索引
|
||||||
private int _selectedRegionIndex = -1;
|
private int _selectedRegionIndex = -1;
|
||||||
|
|
||||||
|
// 句柄调整相关变量
|
||||||
|
private enum ResizeHandle { None, TopLeft, Top, TopRight, Right, BottomRight, Bottom, BottomLeft, Left }
|
||||||
|
private ResizeHandle _currentHandle = ResizeHandle.None;
|
||||||
|
private bool _isResizing = false;
|
||||||
|
private Point _resizeStartPoint;
|
||||||
|
private Rectangle _originalRectangle;
|
||||||
|
|
||||||
public Setting()
|
public Setting()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
@@ -61,7 +68,7 @@ namespace JoyD.Windows.CS
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 鼠标按下事件 - 处理右击退出绘制状态和左击开始绘制矩形
|
/// 鼠标按下事件 - 处理右击退出绘制状态、左击开始绘制矩形和开始调整区域大小
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void PicBoxTemp_MouseDown(object sender, MouseEventArgs e)
|
private void PicBoxTemp_MouseDown(object sender, MouseEventArgs e)
|
||||||
{
|
{
|
||||||
@@ -88,6 +95,26 @@ namespace JoyD.Windows.CS
|
|||||||
// 刷新绘制
|
// 刷新绘制
|
||||||
picBoxTemp.Invalidate();
|
picBoxTemp.Invalidate();
|
||||||
}
|
}
|
||||||
|
// 处理选中区域的调整大小
|
||||||
|
else if (e.Button == MouseButtons.Left && !_isDrawingMode && _selectedRegionIndex != -1)
|
||||||
|
{
|
||||||
|
RegionInfo selectedRegion = _drawnRectangles.FirstOrDefault(r => r.Index == _selectedRegionIndex);
|
||||||
|
if (selectedRegion != null)
|
||||||
|
{
|
||||||
|
Rectangle controlRectangle = ImageRectangleToControlRectangle(selectedRegion.ImageRectangle);
|
||||||
|
|
||||||
|
// 检查是否点击在句柄上
|
||||||
|
_currentHandle = GetHoveredHandle(controlRectangle, e.Location);
|
||||||
|
|
||||||
|
if (_currentHandle != ResizeHandle.None)
|
||||||
|
{
|
||||||
|
// 开始调整大小
|
||||||
|
_isResizing = true;
|
||||||
|
_resizeStartPoint = e.Location;
|
||||||
|
_originalRectangle = controlRectangle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// 处理左击开始绘制矩形
|
// 处理左击开始绘制矩形
|
||||||
else if (e.Button == MouseButtons.Left && _isDrawingMode)
|
else if (e.Button == MouseButtons.Left && _isDrawingMode)
|
||||||
{
|
{
|
||||||
@@ -189,11 +216,43 @@ namespace JoyD.Windows.CS
|
|||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 鼠标移动事件 - 更新矩形大小或检测鼠标悬停区域
|
/// 鼠标移动事件 - 更新矩形大小、检测鼠标悬停区域或更新光标
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void PicBoxTemp_MouseMove(object sender, MouseEventArgs e)
|
private void PicBoxTemp_MouseMove(object sender, MouseEventArgs e)
|
||||||
{
|
{
|
||||||
if (_isDrawing && _isDrawingMode)
|
// 处理调整大小
|
||||||
|
if (_isResizing && !_isDrawingMode && _selectedRegionIndex != -1)
|
||||||
|
{
|
||||||
|
RegionInfo selectedRegion = _drawnRectangles.FirstOrDefault(r => r.Index == _selectedRegionIndex);
|
||||||
|
if (selectedRegion != null)
|
||||||
|
{
|
||||||
|
// 计算新的矩形大小
|
||||||
|
Rectangle newRect = CalculateNewRectangle(_originalRectangle, _resizeStartPoint, e.Location, _currentHandle);
|
||||||
|
|
||||||
|
// 确保矩形有最小尺寸
|
||||||
|
if (newRect.Width > 10 && newRect.Height > 10)
|
||||||
|
{
|
||||||
|
// 转换为图像坐标并更新区域
|
||||||
|
Point imageTopLeft = ControlPointToImagePoint(new Point(newRect.Left, newRect.Top));
|
||||||
|
Point imageBottomRight = ControlPointToImagePoint(new Point(newRect.Right, newRect.Bottom));
|
||||||
|
|
||||||
|
selectedRegion.ImageRectangle = new Rectangle(
|
||||||
|
imageTopLeft.X,
|
||||||
|
imageTopLeft.Y,
|
||||||
|
imageBottomRight.X - imageTopLeft.X,
|
||||||
|
imageBottomRight.Y - imageTopLeft.Y
|
||||||
|
);
|
||||||
|
|
||||||
|
// 重新创建叠加层以反映变化
|
||||||
|
CreateRectangleOverlayImage();
|
||||||
|
|
||||||
|
// 触发重绘
|
||||||
|
picBoxTemp.Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 处理绘制新矩形
|
||||||
|
else if (_isDrawing && _isDrawingMode)
|
||||||
{
|
{
|
||||||
int width = e.X - _startPoint.X;
|
int width = e.X - _startPoint.X;
|
||||||
int height = e.Y - _startPoint.Y;
|
int height = e.Y - _startPoint.Y;
|
||||||
@@ -206,28 +265,56 @@ namespace JoyD.Windows.CS
|
|||||||
|
|
||||||
picBoxTemp.Invalidate();
|
picBoxTemp.Invalidate();
|
||||||
}
|
}
|
||||||
else if (!_isDrawingMode && !_isDrawing) // 就绪状态
|
// 处理鼠标悬停(更新光标或检测悬停区域)
|
||||||
|
else if (!_isDrawingMode && !_isDrawing && !_isResizing) // 就绪状态
|
||||||
{
|
{
|
||||||
// 将鼠标坐标转换为图像坐标
|
// 如果有选中的区域,检查是否悬停在句柄上
|
||||||
Point imagePoint = ControlPointToImagePoint(e.Location);
|
if (_selectedRegionIndex != -1)
|
||||||
|
|
||||||
// 检查鼠标是否在某个区域内,选择索引号最大的区域
|
|
||||||
int newHoveredRegionIndex = -1;
|
|
||||||
int maxIndex = -1;
|
|
||||||
foreach (RegionInfo region in _drawnRectangles)
|
|
||||||
{
|
{
|
||||||
if (region.ImageRectangle.Contains(imagePoint) && region.Index > maxIndex)
|
RegionInfo selectedRegion = _drawnRectangles.FirstOrDefault(r => r.Index == _selectedRegionIndex);
|
||||||
|
if (selectedRegion != null)
|
||||||
{
|
{
|
||||||
maxIndex = region.Index;
|
Rectangle controlRectangle = ImageRectangleToControlRectangle(selectedRegion.ImageRectangle);
|
||||||
newHoveredRegionIndex = region.Index;
|
ResizeHandle hoveredHandle = GetHoveredHandle(controlRectangle, e.Location);
|
||||||
|
|
||||||
|
if (hoveredHandle != ResizeHandle.None)
|
||||||
|
{
|
||||||
|
// 设置相应的光标
|
||||||
|
SetCursorByHandle(hoveredHandle);
|
||||||
|
return; // 不需要检查悬停区域
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 重置光标
|
||||||
|
picBoxTemp.Cursor = Cursors.Default;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果悬停的区域发生变化,更新并触发重绘
|
// 如果没有悬停在句柄上,检查是否悬停在区域上
|
||||||
if (newHoveredRegionIndex != _hoveredRegionIndex)
|
if (_currentHandle == ResizeHandle.None)
|
||||||
{
|
{
|
||||||
_hoveredRegionIndex = newHoveredRegionIndex;
|
// 将鼠标坐标转换为图像坐标
|
||||||
picBoxTemp.Invalidate();
|
Point imagePoint = ControlPointToImagePoint(e.Location);
|
||||||
|
|
||||||
|
// 检查鼠标是否在某个区域内,选择索引号最大的区域
|
||||||
|
int newHoveredRegionIndex = -1;
|
||||||
|
int maxIndex = -1;
|
||||||
|
foreach (RegionInfo region in _drawnRectangles)
|
||||||
|
{
|
||||||
|
if (region.ImageRectangle.Contains(imagePoint) && region.Index > maxIndex)
|
||||||
|
{
|
||||||
|
maxIndex = region.Index;
|
||||||
|
newHoveredRegionIndex = region.Index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果悬停的区域发生变化,更新并触发重绘
|
||||||
|
if (newHoveredRegionIndex != _hoveredRegionIndex)
|
||||||
|
{
|
||||||
|
_hoveredRegionIndex = newHoveredRegionIndex;
|
||||||
|
picBoxTemp.Invalidate();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -333,12 +420,22 @@ namespace JoyD.Windows.CS
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 鼠标释放事件 - 完成矩形绘制(优化版)
|
/// 鼠标释放事件 - 完成矩形绘制或调整大小
|
||||||
/// 使用增量绘制,避免每次都重绘所有矩形
|
/// 使用增量绘制,避免每次都重绘所有矩形
|
||||||
/// 确保矩形坐标相对于图像而非控件
|
/// 确保矩形坐标相对于图像而非控件
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void PicBoxTemp_MouseUp(object sender, MouseEventArgs e)
|
private void PicBoxTemp_MouseUp(object sender, MouseEventArgs e)
|
||||||
{
|
{
|
||||||
|
// 结束调整大小
|
||||||
|
if (_isResizing && e.Button == MouseButtons.Left)
|
||||||
|
{
|
||||||
|
_isResizing = false;
|
||||||
|
_currentHandle = ResizeHandle.None;
|
||||||
|
picBoxTemp.Cursor = Cursors.Default;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 结束绘制新矩形
|
||||||
if (_isDrawing && _isDrawingMode && e.Button == MouseButtons.Left && picBoxTemp.Image != null)
|
if (_isDrawing && _isDrawingMode && e.Button == MouseButtons.Left && picBoxTemp.Image != null)
|
||||||
{
|
{
|
||||||
_isDrawing = false;
|
_isDrawing = false;
|
||||||
@@ -693,6 +790,134 @@ namespace JoyD.Windows.CS
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 定时器每秒触发的事件处理方法
|
/// 定时器每秒触发的事件处理方法
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <summary>
|
||||||
|
/// 获取鼠标当前悬停的句柄
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rectangle">控件坐标的矩形</param>
|
||||||
|
/// <param name="mousePoint">鼠标坐标</param>
|
||||||
|
/// <returns>鼠标悬停的句柄类型</returns>
|
||||||
|
private ResizeHandle GetHoveredHandle(Rectangle rectangle, Point mousePoint)
|
||||||
|
{
|
||||||
|
int handleSize = 8; // 句柄检测范围稍大,提高用户体验
|
||||||
|
|
||||||
|
// 检查各个句柄
|
||||||
|
if (IsPointInRegion(mousePoint, new Rectangle(rectangle.Left - handleSize/2, rectangle.Top - handleSize/2, handleSize, handleSize)))
|
||||||
|
return ResizeHandle.TopLeft;
|
||||||
|
if (IsPointInRegion(mousePoint, new Rectangle(rectangle.Left + rectangle.Width/2 - handleSize/2, rectangle.Top - handleSize/2, handleSize, handleSize)))
|
||||||
|
return ResizeHandle.Top;
|
||||||
|
if (IsPointInRegion(mousePoint, new Rectangle(rectangle.Right - handleSize/2, rectangle.Top - handleSize/2, handleSize, handleSize)))
|
||||||
|
return ResizeHandle.TopRight;
|
||||||
|
if (IsPointInRegion(mousePoint, new Rectangle(rectangle.Right - handleSize/2, rectangle.Top + rectangle.Height/2 - handleSize/2, handleSize, handleSize)))
|
||||||
|
return ResizeHandle.Right;
|
||||||
|
if (IsPointInRegion(mousePoint, new Rectangle(rectangle.Right - handleSize/2, rectangle.Bottom - handleSize/2, handleSize, handleSize)))
|
||||||
|
return ResizeHandle.BottomRight;
|
||||||
|
if (IsPointInRegion(mousePoint, new Rectangle(rectangle.Left + rectangle.Width/2 - handleSize/2, rectangle.Bottom - handleSize/2, handleSize, handleSize)))
|
||||||
|
return ResizeHandle.Bottom;
|
||||||
|
if (IsPointInRegion(mousePoint, new Rectangle(rectangle.Left - handleSize/2, rectangle.Bottom - handleSize/2, handleSize, handleSize)))
|
||||||
|
return ResizeHandle.BottomLeft;
|
||||||
|
if (IsPointInRegion(mousePoint, new Rectangle(rectangle.Left - handleSize/2, rectangle.Top + rectangle.Height/2 - handleSize/2, handleSize, handleSize)))
|
||||||
|
return ResizeHandle.Left;
|
||||||
|
|
||||||
|
return ResizeHandle.None;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 检查点是否在矩形区域内
|
||||||
|
/// </summary>
|
||||||
|
private bool IsPointInRegion(Point point, Rectangle region)
|
||||||
|
{
|
||||||
|
return region.Contains(point);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据句柄类型设置光标
|
||||||
|
/// </summary>
|
||||||
|
private void SetCursorByHandle(ResizeHandle handle)
|
||||||
|
{
|
||||||
|
switch (handle)
|
||||||
|
{
|
||||||
|
case ResizeHandle.TopLeft:
|
||||||
|
case ResizeHandle.BottomRight:
|
||||||
|
picBoxTemp.Cursor = Cursors.SizeNWSE;
|
||||||
|
break;
|
||||||
|
case ResizeHandle.TopRight:
|
||||||
|
case ResizeHandle.BottomLeft:
|
||||||
|
picBoxTemp.Cursor = Cursors.SizeNESW;
|
||||||
|
break;
|
||||||
|
case ResizeHandle.Top:
|
||||||
|
case ResizeHandle.Bottom:
|
||||||
|
picBoxTemp.Cursor = Cursors.SizeNS;
|
||||||
|
break;
|
||||||
|
case ResizeHandle.Left:
|
||||||
|
case ResizeHandle.Right:
|
||||||
|
picBoxTemp.Cursor = Cursors.SizeWE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
picBoxTemp.Cursor = Cursors.Default;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据鼠标移动计算新的矩形大小
|
||||||
|
/// </summary>
|
||||||
|
private Rectangle CalculateNewRectangle(Rectangle original, Point startPoint, Point currentPoint, ResizeHandle handle)
|
||||||
|
{
|
||||||
|
Rectangle newRect = original;
|
||||||
|
|
||||||
|
switch (handle)
|
||||||
|
{
|
||||||
|
case ResizeHandle.TopLeft:
|
||||||
|
newRect.X = currentPoint.X;
|
||||||
|
newRect.Y = currentPoint.Y;
|
||||||
|
newRect.Width = original.Right - currentPoint.X;
|
||||||
|
newRect.Height = original.Bottom - currentPoint.Y;
|
||||||
|
break;
|
||||||
|
case ResizeHandle.Top:
|
||||||
|
newRect.Y = currentPoint.Y;
|
||||||
|
newRect.Height = original.Bottom - currentPoint.Y;
|
||||||
|
break;
|
||||||
|
case ResizeHandle.TopRight:
|
||||||
|
newRect.Y = currentPoint.Y;
|
||||||
|
newRect.Width = currentPoint.X - original.Left;
|
||||||
|
newRect.Height = original.Bottom - currentPoint.Y;
|
||||||
|
break;
|
||||||
|
case ResizeHandle.Right:
|
||||||
|
newRect.Width = currentPoint.X - original.Left;
|
||||||
|
break;
|
||||||
|
case ResizeHandle.BottomRight:
|
||||||
|
newRect.Width = currentPoint.X - original.Left;
|
||||||
|
newRect.Height = currentPoint.Y - original.Top;
|
||||||
|
break;
|
||||||
|
case ResizeHandle.Bottom:
|
||||||
|
newRect.Height = currentPoint.Y - original.Top;
|
||||||
|
break;
|
||||||
|
case ResizeHandle.BottomLeft:
|
||||||
|
newRect.X = currentPoint.X;
|
||||||
|
newRect.Width = original.Right - currentPoint.X;
|
||||||
|
newRect.Height = currentPoint.Y - original.Top;
|
||||||
|
break;
|
||||||
|
case ResizeHandle.Left:
|
||||||
|
newRect.X = currentPoint.X;
|
||||||
|
newRect.Width = original.Right - currentPoint.X;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确保矩形不会变成负尺寸
|
||||||
|
if (newRect.Width < 0)
|
||||||
|
{
|
||||||
|
newRect.X += newRect.Width;
|
||||||
|
newRect.Width = Math.Abs(newRect.Width);
|
||||||
|
}
|
||||||
|
if (newRect.Height < 0)
|
||||||
|
{
|
||||||
|
newRect.Y += newRect.Height;
|
||||||
|
newRect.Height = Math.Abs(newRect.Height);
|
||||||
|
}
|
||||||
|
|
||||||
|
return newRect;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 绘制矩形的八个句柄
|
/// 绘制矩形的八个句柄
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -754,7 +979,7 @@ namespace JoyD.Windows.CS
|
|||||||
private void PicBoxTemp_MouseClick(object sender, MouseEventArgs e)
|
private void PicBoxTemp_MouseClick(object sender, MouseEventArgs e)
|
||||||
{
|
{
|
||||||
// 仅在就绪状态(非绘制模式)下处理
|
// 仅在就绪状态(非绘制模式)下处理
|
||||||
if (!_isDrawingMode && e.Button == MouseButtons.Left && picBoxTemp.Image != null)
|
if (!_isDrawingMode && e.Button == MouseButtons.Left && picBoxTemp.Image != null && !_isResizing)
|
||||||
{
|
{
|
||||||
// 将控件坐标转换为图像坐标
|
// 将控件坐标转换为图像坐标
|
||||||
Point imagePoint = ControlPointToImagePoint(e.Location);
|
Point imagePoint = ControlPointToImagePoint(e.Location);
|
||||||
|
|||||||
Reference in New Issue
Block a user