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
I think the following article will be interesting for you:
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
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
Hmm, perhaps you need to convert this code on VB.NET
let me know...
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.
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
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?
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...
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?
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)...
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.
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.
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?
Perhaps, something like
^C^C_netload "C:/Tem/myAutoCADForm.dll" ;
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
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
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...
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...
Can't find what you're looking for? Ask the community or share your knowledge.