实现当鼠标在半透明区域内单击时显示八个句柄的选中功能

This commit is contained in:
zqm
2025-11-07 10:29:44 +08:00
parent da03a71c04
commit 97c9db1b25

View File

@@ -32,6 +32,8 @@ namespace JoyD.Windows.CS
// 叠加层图像 - 用于存储已完成绘制的矩形 // 叠加层图像 - 用于存储已完成绘制的矩形
private Image _rectangleOverlayImage = null; private Image _rectangleOverlayImage = null;
private int _hoveredRegionIndex = -1; // 当前悬停的区域索引(-1表示没有悬停在任何区域上 private int _hoveredRegionIndex = -1; // 当前悬停的区域索引(-1表示没有悬停在任何区域上
// 当前选中的区域索引
private int _selectedRegionIndex = -1;
public Setting() public Setting()
{ {
@@ -55,6 +57,9 @@ namespace JoyD.Windows.CS
btnDrawRegion.Click += BtnDrawRegion_Click; btnDrawRegion.Click += BtnDrawRegion_Click;
btnSelectColor.Click += BtnSelectColor_Click; btnSelectColor.Click += BtnSelectColor_Click;
// 注册鼠标事件
picBoxTemp.MouseClick += PicBoxTemp_MouseClick;
// 初始隐藏颜色选择按钮,只有在绘制模式下才显示 // 初始隐藏颜色选择按钮,只有在绘制模式下才显示
btnSelectColor.Visible = false; btnSelectColor.Visible = false;
} }
@@ -381,6 +386,7 @@ namespace JoyD.Windows.CS
/// 绘制事件 - 显示矩形框(实现图像合并机制) /// 绘制事件 - 显示矩形框(实现图像合并机制)
/// 处理叠加层图像的缩放,确保与控件尺寸匹配 /// 处理叠加层图像的缩放,确保与控件尺寸匹配
/// 实现鼠标悬停区域填充半透明色功能 /// 实现鼠标悬停区域填充半透明色功能
/// 实现选中区域显示八个句柄功能
/// </summary> /// </summary>
private void PicBoxTemp_Paint(object sender, PaintEventArgs e) private void PicBoxTemp_Paint(object sender, PaintEventArgs e)
{ {
@@ -397,8 +403,31 @@ namespace JoyD.Windows.CS
e.Graphics.DrawImage(_rectangleOverlayImage, destRect, 0, 0, _rectangleOverlayImage.Width, _rectangleOverlayImage.Height, GraphicsUnit.Pixel); e.Graphics.DrawImage(_rectangleOverlayImage, destRect, 0, 0, _rectangleOverlayImage.Width, _rectangleOverlayImage.Height, GraphicsUnit.Pixel);
} }
// 绘制悬停区域的半透明填充(就绪状态) // 绘制选中区域的半透明填充和八个句柄
if (!_isDrawingMode && _hoveredRegionIndex != -1) if (!_isDrawingMode && _selectedRegionIndex != -1)
{
// 查找当前选中的区域
RegionInfo selectedRegion = _drawnRectangles.FirstOrDefault(r => r.Index == _selectedRegionIndex);
if (selectedRegion != null)
{
// 将图像坐标转换为控件坐标
Rectangle controlRectangle = ImageRectangleToControlRectangle(selectedRegion.ImageRectangle);
// 创建半透明的填充颜色(使用区域的颜色,但设置透明度)
Color semiTransparentColor = Color.FromArgb(100, selectedRegion.Color);
// 填充半透明矩形
using (SolidBrush brush = new SolidBrush(semiTransparentColor))
{
e.Graphics.FillRectangle(brush, controlRectangle);
}
// 绘制八个句柄
DrawHandles(e.Graphics, controlRectangle);
}
}
// 绘制悬停区域的半透明填充(就绪状态且没有选中区域时)
else if (!_isDrawingMode && _hoveredRegionIndex != -1 && _selectedRegionIndex == -1)
{ {
// 查找当前悬停的区域 // 查找当前悬停的区域
RegionInfo hoveredRegion = _drawnRectangles.FirstOrDefault(r => r.Index == _hoveredRegionIndex); RegionInfo hoveredRegion = _drawnRectangles.FirstOrDefault(r => r.Index == _hoveredRegionIndex);
@@ -570,6 +599,96 @@ namespace JoyD.Windows.CS
/// <summary> /// <summary>
/// 定时器每秒触发的事件处理方法 /// 定时器每秒触发的事件处理方法
/// </summary> /// </summary>
/// <summary>
/// 绘制矩形的八个句柄
/// </summary>
/// <param name="g">绘图对象</param>
/// <param name="rectangle">要绘制句柄的矩形(控件坐标)</param>
private void DrawHandles(Graphics g, Rectangle rectangle)
{
// 句柄大小
int handleSize = 6;
// 句柄颜色
Color handleColor = Color.White;
Color handleBorderColor = Color.Black;
// 八个句柄的位置
Point[] handlePoints = new Point[]
{
// 左上角
new Point(rectangle.Left, rectangle.Top),
// 上中
new Point(rectangle.Left + rectangle.Width / 2, rectangle.Top),
// 右上角
new Point(rectangle.Right, rectangle.Top),
// 右中
new Point(rectangle.Right, rectangle.Top + rectangle.Height / 2),
// 右下角
new Point(rectangle.Right, rectangle.Bottom),
// 下中
new Point(rectangle.Left + rectangle.Width / 2, rectangle.Bottom),
// 左下角
new Point(rectangle.Left, rectangle.Bottom),
// 左中
new Point(rectangle.Left, rectangle.Top + rectangle.Height / 2)
};
// 绘制每个句柄
using (SolidBrush handleBrush = new SolidBrush(handleColor))
using (Pen handleBorderPen = new Pen(handleBorderColor, 1))
{
foreach (Point point in handlePoints)
{
// 计算句柄矩形
Rectangle handleRect = new Rectangle(
point.X - handleSize / 2,
point.Y - handleSize / 2,
handleSize,
handleSize);
// 绘制句柄(白色填充,黑色边框)
g.FillRectangle(handleBrush, handleRect);
g.DrawRectangle(handleBorderPen, handleRect);
}
}
}
/// <summary>
/// 鼠标点击事件 - 处理区域选中
/// </summary>
private void PicBoxTemp_MouseClick(object sender, MouseEventArgs e)
{
// 仅在就绪状态(非绘制模式)下处理
if (!_isDrawingMode && e.Button == MouseButtons.Left && picBoxTemp.Image != null)
{
// 将控件坐标转换为图像坐标
Point imagePoint = ControlPointToImagePoint(e.Location);
// 检查是否点击在某个区域内
bool clickedOnRegion = false;
foreach (RegionInfo region in _drawnRectangles)
{
if (region.ImageRectangle.Contains(imagePoint))
{
// 选中或取消选中该区域
_selectedRegionIndex = (_selectedRegionIndex == region.Index) ? -1 : region.Index;
clickedOnRegion = true;
break;
}
}
// 如果没有点击在任何区域上,取消选中
if (!clickedOnRegion)
{
_selectedRegionIndex = -1;
}
// 刷新绘制
picBoxTemp.Invalidate();
}
}
/// <summary> /// <summary>
/// 当图像更新或控件大小变化时,重新创建叠加层图像 /// 当图像更新或控件大小变化时,重新创建叠加层图像
/// 确保矩形框正确显示在新的尺寸下 /// 确保矩形框正确显示在新的尺寸下