一、创建基础的通用通知类和命令类

1.创建带有对象属性通知的抽象类BaseModel继承自INotifyPropertyChanged实现RiseProperty方法

   /// <summary>
   /// 带有对象属性通知的抽象类
   /// </summary>
   public abstract class BaseModel :INotifyPropertyChanged
   {
       public event PropertyChangedEventHandler PropertyChanged;

       protected void RiseProperty(string propertyName)
       {
           if (PropertyChanged != null)
           {
               PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
           }
       }
   }

2.创建命令对象类SimpleCommand继承自ICommand

    /// <summary>
    /// 创建命令对象类
    /// </summary>
    public class SimpleCommand : ICommand
    {
        public event EventHandler CanExecuteChanged;
        public Action<object> DoExecute { get; set; }

        public bool CanExecute(object parameter)
        {
            return true;
        }

        public void Execute(object parameter)
        {
            if (DoExecute != null)
            {
                DoExecute(parameter);
            }
        }
    }

二、使用ViewModel中的命令绘制矩形图像

1.创建矩形模型类RectangleModel继承自BaseModel

/// <summary>
/// 矩形模型类
/// </summary>
public class RectangleModel : BaseModel
{
    private double _rectangleWidth;
    private double _rectangleHeight;
    private double _rectangleLeft;
    private double _rectangleTop;

    public double RectangleWidth
    {
        get { return _rectangleWidth; }
        set { _rectangleWidth = value; RiseProperty(nameof(RectangleWidth)); }
    }

    public double RectangleHeight
    {
        get { return _rectangleHeight; }
        set { _rectangleHeight = value; RiseProperty(nameof(RectangleHeight)); }
    }

    public double RectangleLeft
    {
        get { return _rectangleLeft; }
        set { _rectangleLeft = value; RiseProperty(nameof(RectangleLeft)); }
    }

    public double RectangleTop
    {
        get { return _rectangleTop; }
        set { _rectangleTop = value; RiseProperty(nameof(RectangleTop)); }
    }


    public RectangleModel()
    {
        RectangleWidth = 0;
        RectangleHeight = 0;
        RectangleLeft = 0;
        RectangleTop = 0;
    }

    public void InitRectangle()
    {
        RectangleWidth = 0;
        RectangleHeight = 0;
        RectangleLeft = 0;
        RectangleTop = 0;
    }



}

2.在MainWindowViewModel中定义并初始化矩形类,并定义对应的鼠标按下,移动,弹起的命令

public RectangleModel RectModel { get; set; } = new RectangleModel();

public SimpleCommand MouseDownCommand { get; private set; }
public SimpleCommand MouseMoveCommand { get; private set; }
public SimpleCommand MouseUpCommand { get; private set; }
public SimpleCommand DrawRectComand { get; private set; }
public SimpleCommand DiscernComand { get; private set; }

       public MainWindowViewModel()
       {
   
           MouseDownCommand = new SimpleCommand { DoExecute = new Action<object>(MouseDown) };
           MouseMoveCommand = new SimpleCommand { DoExecute = new Action<object>(MouseMove) };
           MouseUpCommand = new SimpleCommand { DoExecute = new Action<object>(MouseUp) };
           DrawRectComand = new SimpleCommand { DoExecute = new Action<object>(DrawRect) };
           DiscernComand = new SimpleCommand { DoExecute = new Action<object>(DiscernAction) };
       }

 3.在xaml页面上增加canvas和相关的命令

          <Canvas Name="MyCanvas" Background="Transparent">
              <Rectangle Stroke="Red" Width="{Binding RectModel.RectangleWidth}" 
                         Height="{Binding RectModel.RectangleHeight}" 
                         Canvas.Left="{Binding RectModel.RectangleLeft}" 
                         Canvas.Top="{Binding RectModel.RectangleTop}" />
              <i:Interaction.Triggers>
                  <i:EventTrigger EventName="MouseDown">
                      <i:InvokeCommandAction Command="{Binding MouseDownCommand}" CommandParameter="{Binding ElementName=MyCanvas}" />
                  </i:EventTrigger>
                  <i:EventTrigger EventName="MouseMove">
                      <i:InvokeCommandAction Command="{Binding MouseMoveCommand}" />
                  </i:EventTrigger>
                  <i:EventTrigger EventName="MouseUp">
                      <i:InvokeCommandAction Command="{Binding MouseUpCommand}" />
                  </i:EventTrigger>
              </i:Interaction.Triggers>
          </Canvas>

将canvas中的事件转换为命令需使用动态库Microsoft.Xaml.Behaviors.Wpf,并在xaml中添加引用:  xmlns:i="http://schemas.microsoft.com/xaml/behaviors"

使用 <i:Interaction.Triggers>触发器添加<i:EventTrigger EventName="MouseDown">触发事件并绑定命令

 <i:InvokeCommandAction Command="{Binding MouseDownCommand}" CommandParameter="{Binding ElementName=MyCanvas}" />

通过命令参数将canvs的名称传给命令

4.鼠标按下的命令执行逻辑

  /// <summary>
  /// 鼠标按下的命令执行逻辑
  /// </summary>
  /// <param name="obj"></param>
  /// <exception cref="NotImplementedException"></exception>
  private void MouseDown(object obj)
  {
     //按下鼠标左键时
      if (Mouse.LeftButton == MouseButtonState.Pressed) 
      {
          _hv_Hanlde = _controlWPF.HalconWindow;
          _myCanvas = obj as Canvas;  //obj作为命令参数可转换为canvas类型
          _startPoint = Mouse.GetPosition(_myCanvas); //获取鼠标在canvas中按下的位置坐标
          // 获取窗口加载的图片部分对象
          var imagePart = _controlWPF.HImagePart;
          // 获取图片与窗口的高度比
          _k = imagePart.Height / _controlWPF.ActualHeight;
          // 获取图片部分在窗口的坐标
          _tx = imagePart.X;
          _ty = imagePart.Y;
          // 如果缩放窗口,那么比例值肯定要变化
          var hdp = DependencyPropertyDescriptor
              .FromProperty(HSmartWindowControlWPF.HImagePartProperty, typeof(HSmartWindowControlWPF));
          hdp.AddValueChanged(_controlWPF, (o, e) => 
          {
              imagePart = _controlWPF.HImagePart;
              // 获取图片与窗口的高度比
              _k = imagePart.Height / _controlWPF.ActualHeight;
              // 获取图片部分在窗口的坐标
              _tx = imagePart.X;
              _ty = imagePart.Y;
          });
      }
  }

5.鼠标移动的命令逻辑

private void MouseMove(object obj)
{
    if (Mouse.LeftButton == MouseButtonState.Pressed)
    {
        _endPoint = Mouse.GetPosition(_myCanvas);
        // 计算画矩形的长和高
        var width = Math.Abs(_endPoint.X - _startPoint.X);
        var height = Math.Abs(_endPoint.Y - _startPoint.Y);
        // 设置矩形在Canvas上面的定位
        var top = _startPoint.Y;
        var left = _startPoint.X;

        switch (_shapeType)
        {
            case ShapeType.Cricle:
                break;
            case ShapeType.Rectangle:
                // 设置属性的值
                RectModel.RectangleWidth = width;
                RectModel.RectangleHeight = height;
                RectModel.RectangleLeft = left;
                RectModel.RectangleTop = top;
                // 把图像坐标转换为Halcon坐标
                ConvertToHalconPoint(_startPoint.X, _startPoint.Y, _k, _tx, _ty, out double column, out double row);
                ConvertToHalconPoint(_endPoint.X, _endPoint.Y, _k, _tx, _ty, out double column1, out double row1);
                _row = row;
                _column = column;
                _row1 = row1;
                _column1 = column1;
                break;
            default:
                break;
        }
        
        
    }
}

6. 鼠标松开的方法

        /// <summary>
        /// 鼠标松开的方法
        /// </summary>
        /// <param name="obj"></param>
        private void MouseUp(object obj)
        {
            if (DispImage != null && _myCanvas != null)
            {
                // 应该根据选择ROI类型绘制对应图像放到Halcon窗口上面
                switch (_shapeType)
                {
                    case ShapeType.Cricle:
                        break;
                    case ShapeType.Rectangle:
                        var rectTuple = new HTuple[] { _row, _column, _row1, _column1 };
                        // 绘制矩形对象
                        var rect = HDrawingObject.CreateDrawingObject(HDrawingObject.HDrawingObjectType.RECTANGLE1, rectTuple);
                        _roi = new NewDrawingObject { DrawingObject = rect, HTuples = rectTuple };
                        // 把矩形放到Halcon窗口
                        _hv_Hanlde.AttachDrawingObjectToWindow(rect);
                        break;
                    default:
                        break;
                }

                // 设置ROI区域的拖拽及缩放事件
                if (_roi!= null)
                {
                    _roi.DrawingObject.OnDrag(DragCallbackClass);
                    _roi.DrawingObject.OnResize(ResizeCallbackClass);
                }

                _myCanvas.Visibility = Visibility.Collapsed;
                RectModel.InitRectangle();
            }
           
        }

 7.把图像坐标转换为Halcon坐标系

      private void ConvertToHalconPoint(double x, double y, double k, double tx, double ty, out double row, out double column)
      {
          row = k * x + tx;
          column = k * y + ty;
      }

 

posted on 2025-06-11 17:32  江渔湖  阅读(106)  评论(0)    收藏  举报