• Industries
  • Products
  • Buy
  • Services & Support
  • Communities
  • Discussion Groups

    .NET

    Reply
    Active Contributor
    Posts: 41
    Registered: ‎05-14-2012
    Accepted Solution

    How to capture double click event in AutoCAD using VB.NET

    709 Views, 28 Replies
    11-26-2012 06:16 PM

    Hi all,

     

    I`m still trying to find a solution to my previous post, displaying a vb.net form when an autocad block reference is double-clicked. Unfortunately, I still don`t know how to capture the double-click event for a block reference from code. I have gone down the IMessageFilter path, still no success.

     

    I have tried the addHandler for application using code supplied to me in my previous post, still no luck. I really need to be able to capture the doubleclick event for a block reference in autocad, without overwriting the default autocad double-click behavior.

     

    I wish to be able to double-click a block reference, capture its name, and, if the name is same as blocks created by my form, then I`d simply have my dot net form pop up, displaying a few of the block`s properties.

     

    Does anyone have any ideas on how this might be accomplishedÉ

     

    Below is the code module I am using, which isn`t working ofr me:

     

    ' System
    Imports Microsoft.Win32
    Imports System.Reflection

     

    ' AutoCAD
    Imports Autodesk.AutoCAD.ApplicationServices
    Imports Autodesk.AutoCAD.Runtime
    Imports acApp = Autodesk.AutoCAD.ApplicationServices.Application
    Imports Autodesk.AutoCAD.DatabaseServices
    Imports Autodesk.AutoCAD.EditorInput

     

    ' AutoCAD Interop
    Imports acOp = Autodesk.AutoCAD.Interop
    Imports acOpCom = Autodesk.AutoCAD.Interop.Common

     

    Module ModDoubleClick


    Private acDoc As acOp.AcadDocument
    Private handlerAdded As Boolean = False

     

    Public Sub eventDoubleClick()
        Try
            If handlerAdded = False Then
                acApp.SetSystemVariable("DBLCLKEDIT", 0)
                If acDoc Is Nothing Then
                    acDoc = CType(acApp.DocumentManager.MdiActiveDocument.AcadDocument, _
                    Autodesk.AutoCAD.Interop.AcadDocument)
                    AddHandler acDoc.BeginDoubleClick, AddressOf callback_DoubleClick
                End If
                handlerAdded = True
            End If

        Catch ex As Autodesk.AutoCAD.Runtime.Exception
            MsgBox(ex.Message, MsgBoxStyle.Critical)

        Finally
            acApp.SetSystemVariable("DBLCLKEDIT", 1)
        End Try
    End Sub

     

    Private Sub callback_DoubleClick(ByVal PickPoint As Object)
        Dim activeDoc As Document = acApp.DocumentManager.MdiActiveDocument
        Dim prmtSel As PromptSelectionResult = activeDoc.Editor.GetSelection()

     

        Using docLock As DocumentLock = activeDoc.LockDocument()
            If prmtSel.Status <> PromptStatus.OK Then Return
            If prmtSel.Value.Count <> 1 Then Return

     

            Dim id As Autodesk.AutoCAD.DatabaseServices.ObjectId = _
            prmtSel.Value(0).ObjectId

     

            Using acTrans As Autodesk.AutoCAD.DatabaseServices.Transaction = _
            activeDoc.TransactionManager.StartTransaction()

                Dim dbObj As Autodesk.AutoCAD.DatabaseServices.DBObject = _
                acTrans.GetObject(id, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForWrite)

     

                Dim ent As Autodesk.AutoCAD.DatabaseServices.Entity = _
                TryCast(dbObj, Autodesk.AutoCAD.DatabaseServices.Entity)

                If ent Is Nothing Then
                    Return
                Else
                    Dim blockRef As Autodesk.AutoCAD.DatabaseServices.BlockReference = _
                    TryCast(ent, Autodesk.AutoCAD.DatabaseServices.BlockReference)

                    If blockRef Is Nothing Then
                        Return
                    Else
                        activeDoc.Editor.WriteMessage(blockRef.Name)
                    End If
                End If
                acTrans.Commit()

            End Using

        End Using

    End Sub

     

    End Module

     

     

    And the Commands class, from which my vb.net form is generated, as well as where the ModDoubleClick.eventDoubleClick() method is called:

     

     

    Public Class Commands


        ' Component for displaying the Mass Straight Conveyor form

        <CommandMethod("mst")> _
        Public Shared Sub massStraight()

            Try
                ' Call this to override default block dblclk event handler
                ModDoubleClick.eventDoubleClick()

     

                ' Display the mass straight form
                Dim cForm As New frmMassStraight
                acApp.ShowModalDialog(cForm)

     

            Catch ex As Autodesk.AutoCAD.Runtime.Exception
                MsgBox(ex.Message, MsgBoxStyle.Critical)
            End Try

        End Sub

     

    End Class

     

     

    Any help is greatly appreciated!

     

    Many thanks...

     

    Cat

    Please use plain text.
    Distinguished Contributor
    ACADuser
    Posts: 1,183
    Registered: ‎12-22-2003

    Re: How to capture double click event in AutoCAD using VB.NET

    11-27-2012 06:58 AM in reply to: mindofcat

    See if this might help;

     

    http://www.theswamp.org/index.php?topic=40021.0

    ACADuser
    Dell Precision T5500 Workstation
    Windows XP Professional SP3
    Dual Quad Core Intel Xeon Processors E5540 2.53GHz,8M L3,5.8GT/s,turbo
    4GB, DDR3 Memory, 1066MHz, ECC (4 DIMMS)
    1.5GB NVIDIA Quadro FX 4800, DUAL MON, 2DP & 1DVI
    160GB, 3.0Gb/s, 16MB Data Burst Cache,SATA2,10K RPM Hard Drive
    16XDVD AND 16XDVD+/-RW
    Please use plain text.
    Active Contributor
    Posts: 42
    Registered: ‎09-05-2012

    Re: How to capture double click event in AutoCAD using VB.NET

    11-27-2012 07:30 AM in reply to: mindofcat

    This code seems to be working OK for me as far as capturing the event.  You are creating and displaying the form at the wrong place however.  I think these 2 lines of code shouldn't be part of your command that's setting up the handler:

     

                Dim cForm As New frmMassStraight
                acApp.ShowModalDialog(cForm)

     

    but instead have to be called before your callback returns.  If you try to run this but you double click on something other than a block reference you might Return prematurely.  I would suggest you print out the Type of your entity just to be sure you are double clicking on the right entity before you return:

     

    ed.WriteMessage(vbLf & "Type:        " + ent.GetType().ToString())

     

    You should see:

     

    Type:        Autodesk.AutoCAD.DatabaseServices.BlockReference

     

    as opposed to something like this:

     

    Type:        Autodesk.AutoCAD.DatabaseServices.Solid3d

     

    or something else.  Hope this helps

    Please use plain text.
    Mentor
    Posts: 247
    Registered: ‎05-12-2009

    Re: How to capture double click event in AutoCAD using VB.NET

    11-27-2012 08:31 AM in reply to: sszabo
    Please use plain text.
    Active Contributor
    Posts: 41
    Registered: ‎05-14-2012

    Re: How to capture double click event in AutoCAD using VB.NET

    11-27-2012 12:14 PM in reply to: ACADuser

    Thanks... the article shows me a code structure that is quite similar to the one I already have. My code should work, but it isn't, I am not seeing the desired result, and I'm guessing this is probably as a result of HOW I'm calling its command.

     

    This whole thing is so confusing. I even seperated the doubleclick module into its own calling command (complete with usepickset), so that I could draw a block, then execute the doubleclick command, and then double-click on the block to see if anything happens... nothing. Just the same ol' AutoCAD attributes editor.


    Really frustrating!

    Please use plain text.
    Active Contributor
    Posts: 41
    Registered: ‎05-14-2012

    Re: How to capture double click event in AutoCAD using VB.NET

    11-27-2012 12:20 PM in reply to: jeff

    And as well, I have also been to http://adndevblog.typepad.com/autocad/2012/09/displaying-entity-details-on-double-click.html many days ago; I translated the code to dot net, and executed it. When I go to AutoCAD and type cui in the command to pull up the cui editor, I see that my new double click action has been created alright, but I still don't know how to attach it to block references, or how to modify the macro string to open my vb.net form.

     

    The macro string in the article runs thus:

     

    C^C^myForm

     

    How does this get modified to pop up a vb.net form named frmMassStraight which I would normally open using application.showModalDialog(formInstance)

     

    Thanks all, for your help, but I'm still floundering in the dark, trying so hard to see the light which I know exists at the end of this dark tunnel...

    Please use plain text.
    Active Contributor
    Posts: 41
    Registered: ‎05-14-2012

    Re: How to capture double click event in AutoCAD using VB.NET

    11-27-2012 12:27 PM in reply to: mindofcat

    Does anyone know of any professional AutoCAD VB.NET Customization Consultants whom I can pay for their time in order to discuss this doubleclick action problem on the phone or via email, in the hope of finding a feasible solution?

     

    Many thanks in advance...

     

    Cat

    Please use plain text.
    Active Contributor
    Posts: 42
    Registered: ‎09-05-2012

    Re: How to capture double click event in AutoCAD using VB.NET

    11-27-2012 12:35 PM in reply to: mindofcat

    I am not sure I understand what is the problem.. Your code works perfectly with minor changes. 

     

    I replaced your cForm with one that has a textbox1 that displays all the properties of the objects you double click.  It should help you identify/discover any issues.  Alll you should have to do is add a winform to your project and drag a textbox1 on it:

     

     Keep me posted where is your code failing exactly, because this works for me.  Also, I am using AutoCAD 2013, it should be easy to replace document code relevant to 2012 or earlier.

     

     

    Imports acOp = Autodesk.AutoCAD.Interop

     

            Public db As Database = HostApplicationServices.WorkingDatabase

            Public ed As Editor = activeDoc.Editor

            Public ReadOnly Property ThisDrawing() As AcadDocument

                Get

                    Return DocumentExtension.GetAcadDocument(Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument)

                End Get

            End Property

            Private acDoc As acOp.AcadDocument

            Private handlerAdded As Boolean = False

            Private cForm As New frmMassStraight

     

            Public Sub eventDoubleClick()

                Try

                    If handlerAdded = False Then

                        MgdAcApplication.SetSystemVariable("DBLCLKEDIT", 0)

                        If acDoc Is Nothing Then

                            acDoc = CType(ThisDrawing, Autodesk.AutoCAD.Interop.AcadDocument)

                            AddHandler acDoc.BeginDoubleClick, AddressOf callback_DoubleClick

                        End If

                        handlerAdded = True

                    End If

                Catch ex As Autodesk.AutoCAD.Runtime.Exception

                    MsgBox(ex.Message, MsgBoxStyle.Critical)

                Finally

                    MgdAcApplication.SetSystemVariable("DBLCLKEDIT", 1)

                End Try

            End Sub

     

            Private Sub DisplayError(ByVal msg As String)

                ed.WriteMessage(vbLf + msg)

                cForm.TextBox1.Text += msg + vbCrLf

                MgdAcApplication.ShowModalDialog(cForm)

            End Sub

            Private Sub callback_DoubleClick(ByVal PickPoint As Object)

                Dim prmtSel As PromptSelectionResult = activeDoc.Editor.GetSelection()

                Dim msg As String = ""

                Using docLock As DocumentLock = activeDoc.LockDocument()

                    If prmtSel.Status <> PromptStatus.OK Then

                        DisplayError(String.Format("ERROR: prmtSel.Status= {0}", prmtSel.Status))

                        Return

                    End If

                    If prmtSel.Value.Count <> 1 Then

                        DisplayError(String.Format("ERROR: prmtSel.Value.Count={0}", prmtSel.Value.Count))

                        Return

                    End If

     

                    Dim id As Autodesk.AutoCAD.DatabaseServices.ObjectId = prmtSel.Value(0).ObjectId

                    Try

                        Using acTrans As Autodesk.AutoCAD.DatabaseServices.Transaction = _

                        activeDoc.TransactionManager.StartTransaction()

                            Dim dbObj As Autodesk.AutoCAD.DatabaseServices.DBObject = _

                            acTrans.GetObject(id, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForWrite)

     

                            Dim ent As Autodesk.AutoCAD.DatabaseServices.Entity = _

                            TryCast(dbObj, Autodesk.AutoCAD.DatabaseServices.Entity)

     

                            cForm.Text = ent.GetType().ToString()

     

                            For Each p As System.Reflection.PropertyInfo In ent.GetType().GetProperties()

                                Try

                                    Dim displStr As String = String.Format("  {0}:     '{1}'", p.Name, p.GetValue(ent, Nothing))

                                    cForm.TextBox1.Text += displStr + vbCrLf

                                Catch

                                    Dim msgStr As String = String.Format("ERR: '{0}' p='{1}'", Err.Description, p.ToString)

                                    ed.WriteMessage(vbLf + msgStr)

                                    cForm.TextBox1.Text += msgStr + vbCrLf

                                End Try

                            Next

     

                            If ent Is Nothing Then

                                DisplayError(String.Format("ERROR: ent={0}", ent))

                                Return

                            Else

                                Dim blockRef As Autodesk.AutoCAD.DatabaseServices.BlockReference = _

                                TryCast(ent, Autodesk.AutoCAD.DatabaseServices.BlockReference)

                                If blockRef Is Nothing Then

                                    DisplayError(String.Format("ERROR: blockRef={0}", blockRef))

                                    Return

                                Else

                                    activeDoc.Editor.WriteMessage(blockRef.BlockName)

                                End If

                            End If

                            acTrans.Commit()

                        End Using

                    Catch ex As Autodesk.AutoCAD.Runtime.Exception

                        Dim msgStr As String = String.Format("EX: '{0}'", ex.ToString)

                        ed.WriteMessage(vbLf + msgStr)

                        cForm.TextBox1.Text += msgStr + vbCrLf

                    Catch

                        Dim msgStr As String = String.Format("ERR: '{0}'", Err.Description)

                        ed.WriteMessage(vbLf + msgStr)

                        cForm.TextBox1.Text += msgStr + vbCrLf

                    End Try

                End Using

                MgdAcApplication.ShowModalDialog(cForm)

            End Sub

            ' Component for displaying the Mass Straight Conveyor form

            <CommandMethod("mst")> _

            Public Sub massStraight()

                Try

                    ' Call this to override default block dblclk event handler

                    eventDoubleClick()

                Catch ex As Autodesk.AutoCAD.Runtime.Exception

                    MsgBox(ex.Message, MsgBoxStyle.Critical)

                End Try

     

            End Sub

     

     

    Please use plain text.
    Active Contributor
    Posts: 41
    Registered: ‎05-14-2012

    Re: How to capture double click event in AutoCAD using VB.NET

    11-27-2012 01:41 PM in reply to: sszabo

    Thanks a bunch. Let me try out your suggestion, and see if I can pinpoint where I am making my mistake.

     

    I shall keep you posted on the development.

     

    Many thanks...

    Please use plain text.
    Active Contributor
    Posts: 41
    Registered: ‎05-14-2012

    Re: How to capture double click event in AutoCAD using VB.NET

    11-27-2012 07:21 PM in reply to: sszabo

    Hi sszabo,

     

    I`ve implemented the code revision you so kindly provided. However, when I run the `mst` command, nothing happens. I doubleclick on a block after running the command, and the attributes editor is what I see still.

     

    Here is the code I have:

     

    ' System
    Imports System
    Imports System.Collections.Generic
    Imports System.Linq
    Imports System.Text
    Imports System.Linq.Expressions
    
    ' AutoCAD
    Imports Autodesk.AutoCAD.DatabaseServices
    Imports Autodesk.AutoCAD.ApplicationServices
    Imports Autodesk.AutoCAD.Runtime
    Imports acApp = Autodesk.AutoCAD.ApplicationServices.Application
    Imports Autodesk.AutoCAD.EditorInput
    
    ' AutoCAD Interop
    Imports acOp = Autodesk.AutoCAD.Interop
    Imports acOpCom = Autodesk.AutoCAD.Interop.Common
    
    <Assembly: CommandClass(GetType(Test.Commands))> 
    
    
    Namespace Test
    
        Public Class Commands
            Public db As Database = HostApplicationServices.WorkingDatabase
            Public activeDoc As Document = acApp.DocumentManager.MdiActiveDocument
            Public ed As Editor = activeDoc.Editor
    
            Private acDoc As acOp.AcadDocument
            Private handlerAdded As Boolean = False
            Private cForm As New frmMassStraight ' I already have a form called frmMassStraight, so I simply added a Textbox1 to it
            
            ' I tried using the property call, but was getting an error on type mismatch from document to acadDocument
            Public Function ThisDrawing()
                Return acApp.DocumentManager.MdiActiveDocument.AcadDocument
            End Function
    
            Public Sub eventDoubleClick()
    
                Try
                    If handlerAdded = False Then
                        acApp.SetSystemVariable("DBLCLKEDIT", 0)
                        If acDoc Is Nothing Then
                            acDoc = CType(ThisDrawing, Autodesk.AutoCAD.Interop.AcadDocument)
                            AddHandler acDoc.BeginDoubleClick, AddressOf callback_DoubleClick
                        End If
                        handlerAdded = True
                    End If
    
                Catch ex As Autodesk.AutoCAD.Runtime.Exception
                    MsgBox(ex.Message, MsgBoxStyle.Critical)
    
                Finally
                    acApp.SetSystemVariable("DBLCLKEDIT", 1)
                End Try
    
            End Sub
    
            Private Sub displayError(ByVal msg As String)
                ed.WriteMessage(vbLf + msg)
                cForm.TextBox1.Text += msg + vbCrLf
                acApp.ShowModalDialog(cForm)
            End Sub
    
            Private Sub callback_DoubleClick(ByVal pickPoint As Object)
                Dim prmtSel As PromptSelectionResult = activeDoc.Editor.GetSelection()
                Dim msg As String = ""
    
                Using docLock As DocumentLock = activeDoc.LockDocument()
                    If prmtSel.Status <> PromptStatus.OK Then
                        displayError(String.Format("Error: prmtSel.Status= {0}", prmtSel.Status))
                        Return
                    End If
    
                    If prmtSel.Value.Count <> 1 Then
                        displayError(String.Format("Error: prmtSel.Value.Count={0}", _
                                                   prmtSel.Value.Count))
                    End If
    
                    Dim id As Autodesk.AutoCAD.DatabaseServices.ObjectId = prmtSel.Value(0).ObjectId
                    Try
                        Using acTrans As Autodesk.AutoCAD.DatabaseServices.Transaction = _
                            activeDoc.TransactionManager.StartTransaction()
    
                            Dim dbObj As Autodesk.AutoCAD.DatabaseServices.DBObject = _
                            acTrans.GetObject(id, Autodesk.AutoCAD.DatabaseServices.OpenMode.ForWrite)
    
                            Dim ent As Autodesk.AutoCAD.DatabaseServices.Entity = _
                                TryCast(dbObj, Autodesk.AutoCAD.DatabaseServices.Entity)
    
                            cForm.Text = ent.GetType().ToString()
    
                            For Each p As System.Reflection.PropertyInfo In _
                                ent.GetType().GetProperties()
                                Try
                                    Dim displStr As String = String.Format(" {0}:      '{1}'", _
                                                            p.Name, p.GetValue(ent, Nothing))
                                    cForm.TextBox1.Text += displStr + vbCrLf
    
                                Catch
                                    Dim msgStr As String = String.Format("Error: '{0}' p='{1}'", _
                                                    Err.Description, p.ToString)
                                    ed.WriteMessage(vbLf + msgStr)
                                    cForm.TextBox1.Text += msgStr + vbCrLf
                                End Try
                            Next
    
                            If ent Is Nothing Then
                                displayError(String.Format("Error: ent={0}", ent))
                                Return
                            Else
                                Dim blockRef As Autodesk.AutoCAD.DatabaseServices.BlockReference = _
                                    TryCast(ent, Autodesk.AutoCAD.DatabaseServices.BlockReference)
    
                                If blockRef Is Nothing Then
                                    displayError(String.Format("Error: blockRef={0}", blockRef))
                                    Return
                                Else
                                    activeDoc.Editor.WriteMessage(blockRef.BlockName)
                                End If
                            End If
                            acTrans.Commit()
    
                        End Using
                    Catch ex As Autodesk.AutoCAD.Runtime.Exception
                        Dim msgStr As String = String.Format("EX: '{0}'", ex.ToString)
                        ed.WriteMessage(vbLf + msgStr)
    
                    Catch
                        Dim msgStr As String = String.Format("ERR: '{0}", Err.Description)
                        ed.WriteMessage(vbLf + msgStr)
                        cForm.TextBox1.Text += msgStr + vbCrLf
                    End Try
    
                End Using
                acApp.ShowModalDialog(cForm)
    
            End Sub
    
            ' Component for displaying the Mass Straight Conveyor form
            <CommandMethod("mst")> _
            Public Sub massStraight()
                Try
                    ' Call this to override the default block dblclk event handler
                    eventDoubleClick()
    
                Catch ex As Autodesk.AutoCAD.Runtime.Exception
                    MsgBox(ex.Message, MsgBoxStyle.Critical)
    
                End Try
            End Sub
    
        End Class
    
    
    End Namespace

     

    I wonder if the problem is because I used the wrong document translations here. I am developing in an AutoCAD 2010 environment, and probably used the wrong instances for your equivalent of DocumentExtension.GetAcadDocument() as well as MgdAcApplication.

     

    As it is, this code should work, but I am not seeing the desired effect. The form doesn`t pop up at all, so I can`t even tell what`s wrong. However, in an attempt to debug, I am guessing that the showModalDialog code at the end of the doubleclick callback probably isn`t being reached at all, which is why the form does not pop up at all to show me anything.

     

    Not even the commandline shows me any of the messages I am supposed to see in the event of an error, or successful call.

     

    Any ideas,

     

    Thanks in advance...

    Please use plain text.