From d511c3a93c39c95f6f5a22fba32b96075b40b102 Mon Sep 17 00:00:00 2001 From: zqm Date: Fri, 7 Nov 2025 15:12:24 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=85=AB=E4=B8=AA=E5=8F=A5?= =?UTF-8?q?=E6=9F=84=E8=B0=83=E6=95=B4=E5=8C=BA=E5=9F=9F=E5=A4=A7=E5=B0=8F?= =?UTF-8?q?=E7=9A=84=E5=8A=9F=E8=83=BD=EF=BC=8C=E5=8C=85=E6=8B=AC=E5=85=89?= =?UTF-8?q?=E6=A0=87=E5=88=87=E6=8D=A2=E5=92=8C=E5=8C=BA=E5=9F=9F=E8=B0=83?= =?UTF-8?q?=E6=95=B4=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CS/Framework4.0/Toprie/Toprie/Setting.cs | 265 ++++++++++++++++-- 1 file changed, 245 insertions(+), 20 deletions(-) diff --git a/Windows/CS/Framework4.0/Toprie/Toprie/Setting.cs b/Windows/CS/Framework4.0/Toprie/Toprie/Setting.cs index 87cf304..459eb84 100644 --- a/Windows/CS/Framework4.0/Toprie/Toprie/Setting.cs +++ b/Windows/CS/Framework4.0/Toprie/Toprie/Setting.cs @@ -35,6 +35,13 @@ namespace JoyD.Windows.CS // 当前选中的区域索引 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() { InitializeComponent(); @@ -61,7 +68,7 @@ namespace JoyD.Windows.CS } /// - /// 鼠标按下事件 - 处理右击退出绘制状态和左击开始绘制矩形 + /// 鼠标按下事件 - 处理右击退出绘制状态、左击开始绘制矩形和开始调整区域大小 /// private void PicBoxTemp_MouseDown(object sender, MouseEventArgs e) { @@ -88,6 +95,26 @@ namespace JoyD.Windows.CS // 刷新绘制 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) { @@ -189,11 +216,43 @@ namespace JoyD.Windows.CS /// - /// 鼠标移动事件 - 更新矩形大小或检测鼠标悬停区域 + /// 鼠标移动事件 - 更新矩形大小、检测鼠标悬停区域或更新光标 /// 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 height = e.Y - _startPoint.Y; @@ -206,28 +265,56 @@ namespace JoyD.Windows.CS picBoxTemp.Invalidate(); } - else if (!_isDrawingMode && !_isDrawing) // 就绪状态 + // 处理鼠标悬停(更新光标或检测悬停区域) + else if (!_isDrawingMode && !_isDrawing && !_isResizing) // 就绪状态 { - // 将鼠标坐标转换为图像坐标 - Point imagePoint = ControlPointToImagePoint(e.Location); - - // 检查鼠标是否在某个区域内,选择索引号最大的区域 - int newHoveredRegionIndex = -1; - int maxIndex = -1; - foreach (RegionInfo region in _drawnRectangles) + // 如果有选中的区域,检查是否悬停在句柄上 + if (_selectedRegionIndex != -1) { - if (region.ImageRectangle.Contains(imagePoint) && region.Index > maxIndex) + RegionInfo selectedRegion = _drawnRectangles.FirstOrDefault(r => r.Index == _selectedRegionIndex); + if (selectedRegion != null) { - maxIndex = region.Index; - newHoveredRegionIndex = region.Index; + Rectangle controlRectangle = ImageRectangleToControlRectangle(selectedRegion.ImageRectangle); + 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 } /// - /// 鼠标释放事件 - 完成矩形绘制(优化版) + /// 鼠标释放事件 - 完成矩形绘制或调整大小 /// 使用增量绘制,避免每次都重绘所有矩形 /// 确保矩形坐标相对于图像而非控件 /// 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) { _isDrawing = false; @@ -693,6 +790,134 @@ namespace JoyD.Windows.CS /// /// 定时器每秒触发的事件处理方法 /// + /// + /// 获取鼠标当前悬停的句柄 + /// + /// 控件坐标的矩形 + /// 鼠标坐标 + /// 鼠标悬停的句柄类型 + 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; + } + + /// + /// 检查点是否在矩形区域内 + /// + private bool IsPointInRegion(Point point, Rectangle region) + { + return region.Contains(point); + } + + /// + /// 根据句柄类型设置光标 + /// + 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; + } + } + + /// + /// 根据鼠标移动计算新的矩形大小 + /// + 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; + } + /// /// 绘制矩形的八个句柄 /// @@ -754,7 +979,7 @@ namespace JoyD.Windows.CS 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);