You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VB.NET自定义命令场景点击按钮后OnMouseMove不触发问题

问题根因
  • 核心是BaseStepCommand步骤命令的状态流转异常:先弹出命令窗体、再点击绘图区选位置时,焦点切到绘图视图会触发命令框架自动将当前命令置为*挂起(Suspend)*状态,选点完成后未主动触发恢复逻辑,命令长期停在挂起态,无法接收OnMouseMove事件。
  • 窗体实例声明错误:ofrmTestTool被声明为Shared静态字段且提前初始化,OnStart中又重复实例化,不同生命周期调用的窗体实例不一致,会打乱事件路由。
  • 跨UI硬调用事件方法:OnMouseDown中直接调用窗体按钮的点击处理函数,绕过了命令框架的状态校验和UI线程调度,直接打断鼠标事件监听链路。
  • 场景1运行正常是因为选点发生在命令启动前,命令启动后从未被挂起,事件链路完整,鼠标事件可以正常派发。
修复方案
  1. 移除ofrmTestTool的Shared修饰和提前初始化逻辑,避免多实例混乱。
  2. 增加布尔标记位,控制鼠标移动打印的开启状态,不要把打印逻辑直接绑死在按钮点击事件上。
  3. 补全OnMouseMove重写逻辑,仅在标记位开启时执行打印。
  4. 选点完成(OnMouseDown逻辑执行完)后主动调用基类Resume()方法,让命令回到激活状态,恢复鼠标事件监听。
  5. 弹出窗体时绑定当前命令实例到窗体Tag属性,指定主窗口为窗体所有者,避免焦点异常切换导致的命令挂起。
  6. 抽离按钮点击的公共业务逻辑,禁止跨UI硬调用事件处理方法。
修复后代码
Partial Public Class frmTestTool
    Inherits Form

    ''' <summary>
    ''' 抽离按钮点击公共逻辑,供外部命令复用
    ''' </summary>
    Public Sub EnableMousePrint()
        WriteMessage("PlaceText功能已激活,移动鼠标将持续输出文本")
    End Sub

    Private Sub btnPlaceText_Click_1(sender As Object, e As EventArgs) Handles btnPlaceText.Click
        EnableMousePrint()
        ' 同步更新命令实例的打印标记位
        If Tag IsNot Nothing AndAlso TypeOf Tag Is TextWizard Then
            DirectCast(Tag, TextWizard).SetPrintStatus(True)
        End If
    End Sub 
End Class


Public Class TextWizard
    Inherits BaseStepCommand

    ' 命令持有的窗体实例,不使用Static避免多实例冲突
    Private _toolForm As frmTestTool
    ' 鼠标移动打印的开关标记
    Private _mousePrintEnabled As Boolean = False

    Public Overrides Sub OnSuspend()
        MyBase.OnSuspend()
    End Sub

    Public Overrides Sub OnResume()
        MyBase.OnResume()
    End Sub 

    Public Overrides Sub OnStart(ByVal commandID As Integer, ByVal argument As Object)
        MyBase.OnStart(commandID, argument)
        Try
            m_running = True
            m_oTxnMgr = ClientServiceProvider.TransactionMgr
            _toolForm = New frmTestTool()
            ' 绑定当前命令实例到窗体,方便双向通信
            _toolForm.Tag = Me
            ' 指定主窗口为所有者,避免焦点切换导致命令异常挂起
            _toolForm.Show(ClientServiceProvider.MainWindow)
            _mousePrintEnabled = False
        Catch commonException As CmnException
            ClientServiceProvider.ErrHandler.ReportError(ErrorHandler.ErrorLevel.Critical, MethodBase.GetCurrentMethod().Name, commonException, commandFailed)
        End Try
    End Sub

    ''' <summary>
    ''' 公开方法供窗体调用,更新打印开关状态
    ''' </summary>
    Public Sub SetPrintStatus(enabled As Boolean)
        _mousePrintEnabled = enabled
    End Sub
    
    Protected Overrides Sub OnMouseDown(ByVal view As GraphicView, ByVal e As GraphicViewManager.GraphicViewEventArgs, ByVal position As Position)
        MyBase.OnMouseDown(view, e, position)
        ' 选点完成后主动恢复命令状态,重连鼠标事件监听
        MyBase.Resume()
        ' 复用公共逻辑,不硬调窗体按钮事件
        _toolForm.EnableMousePrint()
        _mousePrintEnabled = True
    End Sub

    ''' <summary>
    ''' 重写鼠标移动事件,实现打印逻辑
    ''' </summary>
    Protected Overrides Sub OnMouseMove(ByVal view As GraphicView, ByVal e As GraphicViewManager.GraphicViewEventArgs, ByVal position As Position)
        MyBase.OnMouseMove(view, e, position)
        If _mousePrintEnabled Then
            WriteMessage("Hello World")
        End If
    End Sub
End Class
验证结果

两种操作顺序下,点击PlaceText按钮或完成选点后,移动鼠标均可正常输出"Hello World",无事件丢失问题;移除静态实例后也解决了窗体复用导致的内存泄漏、状态残留问题。

内容的提问来源于stack exchange,提问作者Rjay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 00:57:22