.NET
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Display VB.Net form when block reference is double-clicked

19 REPLIES 19
Reply
Message 1 of 20
mindofcat
2173 Views, 19 Replies

Display VB.Net form when block reference is double-clicked

Hi all,

 

I'm in the process of converting existing VBA code to VB.NET using AutoCAD 2010 and MS Visual Studio Professional, and I just hit a major snag.

 

In AutoCAD 2010, double-clicking a block will display its attributes in the attributes editor; I would like instead to be able to display my own custom vb.net form showing some of the block's attributes, IF AND ONLY IF the block was created by my dot net form (the block would have certain identifiable characters in its name).

 

So far, I have not been able to find anything to help, but I have discovered that this may have something to do with the cuix customization file, as well as setting the system variable DBLCLICKEDIT.

 

At this point I am so confused as to how this problem can be resolved. Does anyone have any helpful hints or concise code blocks that might help? Or at the most point me in the right direction?

 

Thanks in advance,

 

Cat

19 REPLIES 19
Message 2 of 20
Hallex
in reply to: mindofcat

I think the following article will be interesting for you:

http://through-the-interface.typepad.com/through_the_interface/2009/07/providing-information-on-auto...

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Message 3 of 20
mindofcat
in reply to: mindofcat

Thanks for the article... It's quite interesting, and will definitely come in handy for later use. For the issue at hand, however, the article describes the use of selection set to identify entities, but I'm looking for information on how to replace the CAD double-click event for blocks with my custom VB.Net form. And this is only for blocks created by said form...

 

Any ideas? Guidelines? Similar articles?

 

Thanks in advance

Message 4 of 20
Hallex
in reply to: mindofcat

Try this code written some time for double click event on polyline objects,

just change object type to double click on blockreference within the code

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//acad
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.ComponentModel;
//acad application
using AcadApp = Autodesk.AutoCAD.ApplicationServices.Application;
//acad interop
using Autodesk.AutoCAD.Interop;
using Autodesk.AutoCAD.Interop.Common;

// tested on A2010
// This line is not mandatory, but improves loading performances
[assembly: CommandClass(typeof(AutoCAD_CSharp_plug_in1.ClickEventMgd))]
namespace AutoCAD_CSharp_plug_in1
{
   public class ClickEventMgd
    {
        Autodesk.AutoCAD.Interop.AcadDocument m_doc;


        [CommandMethod("DBL")]
        public void TestDoubleClick()
        {
            if (m_doc == null)
            {
                m_doc = (Autodesk.AutoCAD.Interop.AcadDocument)AcadApp.DocumentManager.MdiActiveDocument.AcadDocument;

                m_doc.BeginDoubleClick += new _DAcadDocumentEvents_BeginDoubleClickEventHandler(m_doc_BeginDoubleClick);

            }
            else
            {
                AcadApp.SetSystemVariable("DBLCLKEDIT", 1);
                m_doc.BeginDoubleClick -= new _DAcadDocumentEvents_BeginDoubleClickEventHandler(m_doc_BeginDoubleClick);
                m_doc = null;

            }

        }

        #region "Events"
        private void m_doc_BeginDoubleClick(object adoc)
        {
            Document activeDoc = AcadApp.DocumentManager.MdiActiveDocument;
            Editor ed = activeDoc.Editor;
            AcadApp.DocumentManager.MdiActiveDocument.Editor.WriteMessage("Double click event is now hooked.");

            //get the object that the user has selected
            PromptSelectionResult res = activeDoc.Editor.SelectImplied();
            if (res.Status != PromptStatus.OK)
                return;
            if (res.Value.Count != 1)
            {
                //if more then 1 selected before double click dispaly message
                AcadApp.ShowAlertDialog("Must be selected just one object only\nHit Esc button to refresh");
                // might be Sendcommand instead but I don't like it
                return; //we don't handle multiple selected objects
            }
            ObjectId idSel = res.Value[0].ObjectId;
            
            using (Transaction trans = activeDoc.TransactionManager.StartTransaction())
            {
                Entity obj = (Entity)trans.GetObject(idSel, OpenMode.ForRead);
                if (idSel.ObjectClass != RXClass.GetClass(typeof(Polyline)))
                {
                    // for all other objects add usual way
                    AcadApp.SetSystemVariable("DBLCLKEDIT", 1);
                    return;
                }
                m_doc.SendCommand("\x03\x03");
                AcadApp.SetSystemVariable("DBLCLKEDIT", 0);
                Polyline pline = (Polyline)obj as Polyline;


                TestPlineCommand(pline);
             

                trans.Commit();
            }
         
        }
        #endregion

        #region "Commands"
       // change calling  command here
        public void TestPlineCommand(Polyline pline)
        {
            AcadApp.ShowAlertDialog(string.Format("Polyline:\nHandle: {0}\nArea: {1}\nLength: {2}\nLayer: {3}", pline.Handle.Value, pline.Area, pline.Length, pline.Layer));
        }
        #endregion
    }
}

I think you need to store block names you've created from form

in list of string as member of your form,

then compare if this list contains a block name

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Message 5 of 20
mindofcat
in reply to: mindofcat

Thanks, Hallex... Imma try it out right away and see how it goes.

Message 6 of 20
Hallex
in reply to: mindofcat

Hmm, perhaps you need to convert this code on VB.NET

let me know...

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Message 7 of 20
mindofcat
in reply to: Hallex

You're right there... I'm already covnerting to VB.Net. I'm curious to see what would happen when I change the polyline ent to blockref.

 

I shall let you know once I finish converting and testing.

 

I deeply appreciate your help.

Message 8 of 20
Hallex
in reply to: mindofcat

Here is quick convertion very limited tested

 

Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
'acad
Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.ApplicationServices
Imports Autodesk.AutoCAD.Runtime
Imports Autodesk.AutoCAD.EditorInput
Imports Autodesk.AutoCAD.ComponentModel
'acad application
Imports AcApp = Autodesk.AutoCAD.ApplicationServices.Application
'acad interop
Imports Autodesk.AutoCAD.Interop
Imports Autodesk.AutoCAD.Interop.Common

' tested on A2010
' This line is not mandatory, but improves loading performances
<Assembly: CommandClass(GetType(AutoCAD_CSharp_plug_in1.ClickEventMgd))> 
Namespace AutoCAD_CSharp_plug_in1
    Public Class ClickEventMgd
        Private m_doc As Autodesk.AutoCAD.Interop.AcadDocument


        <CommandMethod("DBLK")> _
        Public Sub TestDoubleClick()
            If m_doc Is Nothing Then
                m_doc = DirectCast(AcApp.DocumentManager.MdiActiveDocument.AcadDocument, Autodesk.AutoCAD.Interop.AcadDocument)

                AddHandler m_doc.BeginDoubleClick, AddressOf m_doc_BeginDoubleClick
            Else
                AcApp.SetSystemVariable("DBLCLKEDIT", 1)
                RemoveHandler m_doc.BeginDoubleClick, AddressOf m_doc_BeginDoubleClick

                m_doc = Nothing

            End If

        End Sub

#Region "Events"
        Private Sub m_doc_BeginDoubleClick(adoc As Object)
            Dim activeDoc As Document = AcApp.DocumentManager.MdiActiveDocument
            Dim ed As Editor = activeDoc.Editor
            AcApp.DocumentManager.MdiActiveDocument.Editor.WriteMessage("Double click event is now hooked.")

            'get the object that the user has selected
            Dim res As PromptSelectionResult = activeDoc.Editor.SelectImplied()
            If res.Status <> PromptStatus.OK Then
                Return
            End If
            If res.Value.Count <> 1 Then
                'if more then 1 selected before double click dispaly message
                AcApp.ShowAlertDialog("Must be selected just one object only" & vbLf & "Hit Esc button to refresh")
                ' might be Sendcommand instead but I don't like it
                'we don't handle multiple selected objects
                Return
            End If
            Dim idSel As ObjectId = res.Value(0).ObjectId

            Using trans As Transaction = activeDoc.TransactionManager.StartTransaction()
                Dim obj As Entity = DirectCast(trans.GetObject(idSel, OpenMode.ForRead), Entity)
                If idSel.ObjectClass <> RXClass.GetClass(GetType(BlockReference)) Then
                    ' for all other objects add usual way
                    AcApp.SetSystemVariable("DBLCLKEDIT", 1)
                    Return
                End If
                m_doc.SendCommand(ChrW(3) & ChrW(3))
                AcApp.SetSystemVariable("DBLCLKEDIT", 0)
                Dim bref As BlockReference = TryCast(DirectCast(obj, BlockReference), BlockReference)


                TestBlockCommand(bref)


                trans.Commit()
            End Using

        End Sub
#End Region

#Region "Commands"
        ' change calling  command here
        Public Sub TestBlockCommand(bref As BlockReference)
            AcApp.ShowAlertDialog(String.Format("BlockReference:" & vbLf & "Name: {0}" & vbLf & "Handle: {1}" & vbLf & "Layer: {2}" & vbLf & "Position: {3:f3}", bref.Name, bref.Handle.Value, bref.Layer, bref.Position))
        End Sub
#End Region
    End Class
End Namespace

 

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Message 9 of 20
mindofcat
in reply to: Hallex

Sir,

 

Thanks for the dot net conversion... The code seems to be flawless and makes perfect sense. However, after I implemented it into my existing namespace and executed the code by typing the command; but it doesn't seem to have the desired effect, 'cos I doubleclick on a block created by my form, and the EATTEDIT command still runs, popping up the block's attributes.

 

Isn't the code supposed to overwrite this behavior by now?

Message 10 of 20
Hallex
in reply to: mindofcat

Oops, sorry I didn't test this code from form

if your form is modeless maybe you could use

Editor.StartUserInteraction(Me), I haven't have a time

on this work...

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Message 11 of 20
mindofcat
in reply to: Hallex

That's OK... I am truly appreciative of the time you have put into this. So the thing is, my form is modal. I would netload, then type in the command to run my form, which generates a block. Then I would type in the command to run the doubleclick event you so kindly provided.

 

At this point, I would expect to double-click on the block I just created, and have the default doubleclick event overridden, but no, that still doesn't happen.

 

What I'm trying to understand is this: When exactly is the default doubleclick event for block reference supposed to be overridden? 'Cos like I mentioned in my last post, the logic of the code you provided seems flawless, but I simply can't understand why I stil don't have the desired effect...

 

I trash around online quite a bit searching for more solutions, and many a time I keep getting the referral to do something with the CAD cuix file. Do you think this is feasible? And if so, can this be done from code, as opposed to typing cuix in the command line and pulling up the AutoCAD cui customization interface?

Message 12 of 20
mindofcat
in reply to: mindofcat

Here is the module I am using to accomplish doubleclick event handling:

 

 

' 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

 

 

To execute, I start AutoCAD 2010, and type 'mst' into the command bar to run the command which both launches my form and as well 'supposedly' applies doubleclick handler.

 

After form execution has drawn a block, I doubleclick on the block and the AutoCAD block Attributes Editor still appears.


Really frustrating, isn't it? No end in sight, still hoping for some insight as to why the module isn't doing what it's supposed to do, override the default AutoCAD doubleclick event for blocks (with attributes)...

Message 13 of 20
Balaji_Ram
in reply to: mindofcat

Hello,

 

I have attached two screenshots showing the double click actions responsible for block and attribute editing.

 

You may try editing the macro for the attribute edit double click action to include your command that displays the form.

 

I havent tried the sample code yet. Please let me know if modifying the double click action in cuix does not help. I will debug through the code that you already provided.

 



Balaji
Developer Technical Services
Autodesk Developer Network

Message 14 of 20
mindofcat
in reply to: Balaji_Ram

Thank you very much, let me check out your screenshots and see how it helps...

 

Quick word though, I would be slightly skeptical about making adjustments directly in the cuix, since this would affect ALL DOUBLE-CLICKED BLOCK REFERENCES, right?

 

But I am only interested in affecting double-clicked block references which were created by my form (the block name has certain identifiable substrings), while therest of the block references in the drawing would continue to exhibit the default AutoCAD double-click behavior...

 

Still, let me take a look at your screenshots and investigate my cuix.

 

Thanks for your help, much appreciated!

 

Further suggestions/pointers/advice still welcome.

 

 

Message 15 of 20
mindofcat
in reply to: Balaji_Ram

Any idea how to write the macro string for opening a vb.net form in the cuix double-click macro field?

 

In regular vb.net code, this would be acApp.ShowModalDialog(cForm), but in macro?

Message 16 of 20
Hallex
in reply to: mindofcat

Perhaps, something like

^C^C_netload "C:/Tem/myAutoCADForm.dll" ;

 

_____________________________________
C6309D9E0751D165D0934D0621DFF27919
Message 17 of 20
mindofcat
in reply to: mindofcat

Thanks...

 

I checked out the cuix screenshots; unfortunately, I need to be able to accomplish this double-click action programmatically, as I feel that's the only way I shall be able to apply my custom double-click action to only specific block references, instead of ALL block references.

 

All the research I have done online enabled me to compile the module I posted here, and the code's logic seems sensible, but unfortunately, after I run the command, double-clicking blocks still pulls up the default autocad double-click action (attredit)

 

DO you have any idea how this can be made to work?

 

Many thanks in advance...

 

Cat

Message 18 of 20

Hi,

 

 You can try using IMessageFilter to avoid double click message going to AutoCAD. Refer DevBlog http://adndevblog.typepad.com/autocad/2012/05/how-to-combine-a-net-jig-and-messagefilter-to-catch-us... which shows the use of IMessageFilter and blocking of right click reaching AutoCAD

 

 



Virupaksha Aithal KM
Developer Technical Services
Autodesk Developer Network

Message 19 of 20

Hi,

 

Thanks for the posted link... I'm still trying to figure out how to customize that JigMsgFilter class to suit my needs. I am still relatively new to AutoCAD VB.Net customization, and so many things out there are still confusing for me, but I am finding my way thru gradually.

 

I am currently attempting to fingure out how the class in your post can be customized for doubleclick action... 

Message 20 of 20

Hi ,

 

also take look at the new post on similar issue http://forums.autodesk.com/t5/NET/How-to-capture-double-click-event-in-AutoCAD-using-VB-NET/td-p/371...



Virupaksha Aithal KM
Developer Technical Services
Autodesk Developer Network

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report

”Boost