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

Insert .dwg file and adding properties to dynamic block

45 REPLIES 45
Reply
Message 1 of 46
kapes13
1385 Views, 45 Replies

Insert .dwg file and adding properties to dynamic block

I have been working through a dynamic block insertion routine using .NET with ACAD 2006 and it is having trouble getting instructions to stick to AutoCAD to continue.

I have been able to insert a .dwg file and create it's block reference, and at insertion time I wish to modify and add dynamic properties but the block's IsDynamicBlock property remains false just after insertion. I have to leave the routine and re-read the block from model space to note the property as true.

I have seen examples and publications use similar logic as ways to do this but the property remains false using the examples and labs from Autodesk.

Perhaps the references are off a little, or ACAD 2006 doesen't respond to the logic the same, and there is no solidly published model available which explains the methods in enough detail to understand the mishap here. A good reference pointer or hint of why the IsDynamicBlock property remains false after this logic would be greatly appreciated.

Here is the snippet which I use to insert the block:
Dim dwgName As String = HostApplicationServices.Current.FindFile(CurrentFullBlock, acadApp.DocumentManager.MdiActiveDocument.Database, FindFileHint.Default)
Dim db As Database = New Database(False, False)
db.ReadDwgFile(dwgName, IO.FileShare.ReadWrite, True, "")
Dim BlkId As ObjectId
BlkId = doc.Database.Insert(dwgName, db, True)
Dim bt As BlockTable = tr.GetObject(doc.Database.BlockTableId, OpenMode.ForRead, True)
Dim btr As BlockTableRecord = DirectCast(tr.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite), BlockTableRecord)
Dim blockRefIds As ObjectIdCollection = btr.GetBlockReferenceIds(False, False)
'Dim btr As BlockTableRecord = tr.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite)
Dim bref As New BlockReference(New Autodesk.AutoCAD.Geometry.Point3d(insertionPoint), BlkId)
btr.AppendEntity(bref)
tr.AddNewlyCreatedDBObject(bref, True)
'Try to modify dynamic properties:
'Define properties:
Dim insDynamicPropertyCollection As DynamicBlockReferencePropertyCollection
Dim insDynamicProp As DynamicBlockReferenceProperty
'Get a new value for bref - BUT IsDynamicBlock is false here - WHY Please?
If bref.IsDynamicBlock Then
For Each insDynamicProp In insDynamicPropertyCollection
'Get the properties for the block
Select Case insDynamicProp.PropertyName.ToUpper
Case "Put a case here"
insDynamicProp.Value = "Set a value here"
Case Else
MsgBox("Property was not found.")
End Select
Next
End If
'Commit the add:
tr.Commit()
bref.ExplodeToOwnerSpace()

That is all any suggestions on why the property was not true are appreciated.

Have a great day.
45 REPLIES 45
Message 21 of 46
jason.brenton
in reply to: kapes13

basically i do want to just handle a single attribute or prop per a group of several different blocks i am kind of dealing out over a drawing area. actually most of the time most of the blocks will need no or very little modification afterward for my purposes, but that may change.

do you have a new result image to post? i would like to verify that it works for me too and i don't have something else to wrestle with.
Message 22 of 46
cadMeUp
in reply to: kapes13

I am not sure why that one line of code was causing a problem with that. I am not sure what the purpose is for 'RecordGraphicsModified'. You can pass a true/false value to it. When I passed a false value to it, and opened the dwg again, the visibility states remained changed for each block.

I have not had much of a chance to work with Dynamic blocks yet. Your sample that you sent over has given me a great working experience with them. I was not sure how to go about creating visibility states yet. Your block sample is going to help out alot as far as creating dynamic blocks myself in the future!
Message 23 of 46
jason.brenton
in reply to: kapes13

well thansk and your welcome.

From just about 2 months i have gone into this api, and my experience on digging into api's in general, i think i have mangaed to come pretty far.

btw, recreating the xrecords was the trick for them to work, i tried to modify their values instead and the killed autocad without an error.
Message 24 of 46
cadMeUp
in reply to: kapes13

With the xrecords, is it in LISP or VB.NET? Xrecords can be a little tricky sometimes. Like the data that you pass into a result buffer, if you don't pass the correct data it can create nasty exceptions. Do have a sample of your code that you want to show?

I work with xrecords quite a bit and I am always cautious with double checking my coding to see if there are any problems.

Have you used the debugger to inspect your code executing with the xrecords?
Message 25 of 46
jason.brenton
in reply to: kapes13

well it is vb.net with sharp develop, and tho my code does have warning it does compile. not all of the warning apply to anything about xrecords.
heres essentiallty what i do now that works.

dim db as database = hostappicaiotionservices.workingdatabase
dim tr as transaction = db.starttransaction
dim NOD as dbdictionary = tr.getobject(namedobjectdictionaryid, openmode.forread)

try
dim odict as dbdictionary
odict = tr.getobject(NOD.getat("TargetName"), openmode.forread)

dim xr as xrecord = tr.getobject(odict.getat("RecName"), openmode.forread)

'code to read xrecords, custom string parsing stuff sorry, because its easier i tend to parse xr.data.tostring

catch ex as system.exception
if ex.message = "eKeyNotFound" then
'use default data
filloutformdefaults'for example
else
msgbox(ex.message)
end if

finally
tr.commit
tr.dispose
end try

thats the read type stuff, for writing

dim db as database = hostappicaiotionservices.workingdatabase
dim tr as transaction = db.starttransaction
dim NOD as dbdictionary = tr.getobject(namedobjectdictionaryid, openmode.forread)

try
dim odict as new dbdictionary
NOD.setat("TargetName"), odict)
tr.addnewlycreateddbobject(odict, true)

dim xr as new xrecord
xr.data = new resultbuffer(new typedvalue(1, sToBeStored))
odict.setat("RecName", xr)
tr.addnewlycreatedbobject(xr, true)

catch ex as system.exception

msgbox(ex.message)

finally
tr.commit
tr.dispose
end try

very basic, but i use this in a lot of code i want to keep to myself.
Message 26 of 46
cadMeUp
in reply to: kapes13

One thing I can see right away, when you are writing the xrecord the NOD should be open for write because you are adding a new dictionary object. I took your code and reworked it to make it more friendly, to me anyway. In the one function block it pretty much shows how to read and write xrecords safely, from my experience.

You will notice that there are more try/catch blocks. I feel it is better to execute a couple of items in a try/catch block than executing a bunch of different things. It is easier to tell where the exception is being thrown.

Also, you will see how to add and read different data types to and from the xrecord. Different data types need different type codes when you are adding them to the result buffer.
Like a Point3d data type has a typecode of 10, a real value has a typecode of 40. You can look at the 'Autodesk.AutoCAD.DatabaseServices.DxfCode' enum for all of the possible values that can be used.

You can see if a dictionary has a key/object define by calling the DBDictionary's 'Contains()' method wich will tell you right away if a key exists instead of trying to open the key with an exception thrown if it can't find the key. Much safer!
Message 27 of 46
cadMeUp
in reply to: kapes13

Sorry! Forgot to attach the sample files that I had. It's been along day!! Almost over though!
Message 28 of 46
jason.brenton
in reply to: kapes13

doh!
i forgot to change the adds to forwrite, your correct.

i wrote it too fast.

now to start work on a croos connect to access/sql to record other project data.
Message 29 of 46
dgorsman
in reply to: kapes13

Slightly off topic - I was under the impression that user-created xrecords in dictionaries could use any group code except 5 and 105 in any way the user sees fit? XData has fixed data type groups.
----------------------------------
If you are going to fly by the seat of your pants, expect friction burns.
"I don't know" is the beginning of knowledge, not the end.


Message 30 of 46
cadMeUp
in reply to: kapes13

I haven't had to use too many group code numbers other than the ones that I used in the posted sample. I probably saw that somewhere where it is not safe to use 5 & 105. To tell you the truth I have never used the 'DxfCode.Handle' group code before until the sample that I posted. For handles I usually store them under 'DxfCode.Text' and convert the string value to a handle on reading the xrecord. This is done in C#. The sample ran without any errors so it looks to me like you can use group 5 at least. I am not sure which 'DxfCode' in the enum will use 105.

I guess the best way to know would be to try and enter as many different possible group codes, with the expected valid values, into a test xrecord(s) and retrieve the values that were entered and see what kind of results you would get. I am assuming that, maybe, some kind of exception would be thrown if a code/value is invalid.

The ObjectARX developer's guide states:
>> The xrecord object is a built-in object class with a DXF name of "XRECORD",
>> which stores and manages arbitrary data streams, represented externally
>> as a result-buffer list composed of DXF groups with "normal object" groups
>> (that is, non-xdata group codes), ranging from 1 through 369.

It also has a table that lists the possible codes for xrecords, and you are right group codes 5 & 105 are not in the table.

Maybe someone will have a more difinitive answer to this note? Why, if 5 & 105 are not valid, will it still store the data under those group codes without throwing an exception?
Message 31 of 46
jason.brenton
in reply to: kapes13

Well back on the dynamic block issues.

I think i have to approach the dynamic block in a two transaction method to get the dynamic values to stick.
Basically, i will create the block ref in transaction 1, keep the ob id of the ref, then on a new transaction changed the properties. I will let you know if this worked, but also be listening if anyone has encounter and fixed this dynamic block problem.
Message 32 of 46
foruma000256
in reply to: kapes13

I have a dynamic block inserted, then properties changed, due to the nature of a user picking to points to outline a box, and the blocks, length and width dyn properties changing after insert. It definitely works with separate transactions. My biggest problem is dynamiic blocks and properties palette. If I change a value with the properties palette, the result from the block is unpredictable.

Have you or anybody listening figured out the mechanism for dynamic blocks? When listening for object modified events, the properties palette throws more that 2 events. On the third, AutoCAD doesn't return the dynamic properties collection, and throws an error (fatal if not catch-ed). In other cases it separates the block geometry from the dynamic handles, where the block reshapes, but the handles stay at original location. I'm just trying to get a clue here...
Message 33 of 46
jason.brenton
in reply to: kapes13

I dont' know much abou the pallette section, but will have a look at a code sample if you got one. also have found block manipulations can take up to 3 transactions, 1 to transfer from the original file to the new files BLockTable. 1 to make a reference in modelspace (or whereever the viewable block is going.) and lastly another to manipulate dynamic properties and similar values.

if the pallette fires mulitple events to change a property, it is probably doing an access/read tranaction, a validation transaction, then finally update transaction. But i do need to see a sample.
Message 34 of 46
foruma000256
in reply to: kapes13

This is my standard block (dynamic) insert from file technique...

Private box1 As Point3d
Private box2 As Point3d
Private brPanel As BlockReference
Private btrPanel As BlockTableRecord

Public Sub InsertNewPanel()
Dim dblInsert As Point3d
Dim dblP2 As Point3d
Dim objResult As PromptPointResult
Dim bt As BlockTable
Dim btr As BlockTableRecord = Nothing
Dim btrMSpace As BlockTableRecord
Dim id As ObjectId
Dim db As Autodesk.AutoCAD.DatabaseServices.Database = HostApplicationServices.WorkingDatabase
Using trans As Transaction = db.TransactionManager.StartTransaction
Dim ed As Autodesk.AutoCAD.EditorInput.Editor = Application.DocumentManager.MdiActiveDocument.Editor
'insert block and rename it
Try
'pick single insert point method
'add support for pick box method
Dim op As PromptPointOptions = New PromptPointOptions("Pick the location for the new shear wall panel")
op.AllowArbitraryInput = False
op.AllowNone = False
objResult = ed.GetPoint(op)
If objResult.Status = PromptStatus.Error Then MsgBox("Pick error" & objResult.Status.ToString)
If objResult.Status = PromptStatus.OK Then
dblInsert = objResult.Value
'insert by box section
If Building.InsertByBox = True Then
Dim pco As New PromptCornerOptions("Pick second point for Panel: ", dblInsert)
pco.AllowArbitraryInput = False
pco.AllowNone = False
pco.UseDashedLine = True
Dim ppr As PromptPointResult = ed.GetCorner(pco)
If ppr.Status = PromptStatus.OK Then
dblP2 = ppr.Value
End If
End If
'add getCorner and insert block to fit in box
bt = trans.GetObject(db.BlockTableId, OpenMode.ForWrite)
If bt.Has(srwlBuilding.strSourcePanelBlockName) Then
'block found, get instance for copying
btrPanel = trans.GetObject(bt.Item(srwlBuilding.strSourcePanelBlockName), OpenMode.ForRead)
Else
'block not found, insert into drawing
Using sourcedb As Database = New Database(False, False)
Try
sourcedb.ReadDwgFile(srwlBuilding.strSourcePanelBlockPath, IO.FileShare.Read, True, "")
id = db.Insert(srwlBuilding.strSourcePanelBlockPath, sourcedb, True)
btrPanel = trans.GetObject(id, OpenMode.ForWrite)
btrPanel.Name = "Panel-" & Name & "-" & PanelID.ToString
Catch ex As System.Exception
Dim aex As New System.Exception("Block file not found" & srwlBuilding.strSourcePanelBlockPath & "-", ex)
Throw aex
Exit Sub
End Try
sourcedb.Dispose()
End Using
End If
btrMSpace = trans.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite)
brPanel = New BlockReference(dblInsert, btrPanel.ObjectId)
btrMSpace.AppendEntity(brPanel)
trans.AddNewlyCreatedDBObject(brPanel, True)
Me.BlockRefHandle = brPanel.Handle
Me.BlockHandle = btrPanel.Handle
End If
trans.Commit()
Catch ex As System.Exception
Dim aex2 As New System.Exception("Error in inserting new Panel block. ", ex)
Throw aex2
Finally
ed.WriteMessage(vbLf & "Command: ")
If Not trans Is Nothing Then trans.Dispose()
End Try
If Building.InsertByBox = True Then
Try
SetShape(dblInsert, dblP2)
Catch ex As System.Exception
Dim aex3 As New System.Exception("Error while setting Panel shape: ", ex)
Throw aex3
End Try
End If
SetDefaults()
End Using
End Sub

this chunk is responsible for putting the dynamic block into the drawing into modelspace.

This next chunk is my event handler that listens to AutoCAD. It is fired off 3 time when modifying a (dynamic only) property using AutoCAD's built in properties palette. If the object is 'found' to be one of the objects I am tracking in my object tree, then I react by re-reading the objects properties. When the code reads the dynamic properties, third time (event triggered) crashes, because no dynamic properties can be found (kind of...)


Private Sub callback_ObjectModified(ByVal sender As Object, ByVal e As ObjectEventArgs)
If IgnoreEvents Then Exit Sub
Dim ibe As Boolean = Me.IgnoreEvents
Try
IgnoreEvents = True
If Not e.DBObject.IsWriteEnabled Then
IgnoreEvents = ibe
WorkEvent(e.DBObject, "Modified")
End If
Catch ex As System.Exception
Dim aex As New System.Exception("Error at Modify Object AutoCAD Event: ", ex)
Me.HandleError(aex)
Finally
IgnoreEvents = ibe
End Try
End Sub

Public Sub WorkEvent(ByRef dbObject As DBObject, ByVal strTask As String)
Try
Select Case dbObject.GetType.ToString
Case "Autodesk.AutoCAD.DatabaseServices.BlockReference"
'If e.DBObject.IsModified = False Then
'Debug.Print("BlockReference " & strTask)
Try
Dim objCheck As Object = Me.Levels.ContainsHandle(dbObject.Handle)
If objCheck(0) Then
'Debug.Print(objCheck(1).ToString & objCheck(2).ToString)
Select Case strTask
Case "Added"
Case "Modified"
Me.ReactToChange(objCheck)
Case "Erased"
Me.ReactToErased(objCheck)
Case "UnErased"
Me.ReactToUnErase(objCheck)
End Select
End If
Catch ex As System.Exception
Dim aex As New System.Exception("Error working BlockReference event: ", ex)
Throw aex
End Try
'End If
Case "Autodesk.AutoCAD.DatabaseServices.Polyline"
'Debug.Print("Polyline " & strTask)
Try
Dim objCheck As Object = Me.Levels.ContainsHandle(dbObject.Handle)
If objCheck(0) Then
'Debug.Print(objCheck(1).ToString & objCheck(2).ToString)
Select Case strTask
Case "Added"
Case "Modified"
Me.ReactToChange(objCheck)
Case "Erased"
Me.ReactToErased(objCheck)
Case "UnErased"
Me.ReactToUnErase(objCheck)
End Select
End If
Catch ex As System.Exception
Dim aex As New System.Exception("Error working Polyline event: ", ex)
Throw aex
End Try
End Select
Catch ex As System.Exception
Dim aex As New System.Exception("Error Working Event: ", ex)
Throw aex
End Try
End Sub

This is the snippet that accesses the dynamic property as a separate process from a custom built palette.

Public Overridable Function GetDynProperty(ByVal bref As BlockReference, ByVal PropertyName As String) As Object
Dim db As Autodesk.AutoCAD.DatabaseServices.Database = HostApplicationServices.WorkingDatabase
Dim ThisDrawing As Autodesk.AutoCAD.ApplicationServices.Document = Application.DocumentManager.MdiActiveDocument
Dim objProp As Object = Nothing
Using trans As Transaction = db.TransactionManager.StartTransaction
Dim dlock As DocumentLock = Nothing
Try
Try
dlock = ThisDrawing.LockDocument
Catch ex As Exception
Dim aex As New System.Exception("Error locking document for to get Dynamic Property: ", ex)
Throw aex
End Try
Dim brObj As BlockReference = trans.GetObject(bref.Id, OpenMode.ForRead)
If Not brObj Is Nothing Then
Dim dpcPanel As DynamicBlockReferencePropertyCollection
Dim dpPanel As DynamicBlockReferenceProperty
If brObj.IsDynamicBlock = True Then
Try
dpcPanel = brObj.DynamicBlockReferencePropertyCollection
For Each dpPanel In dpcPanel
Select Case dpPanel.PropertyName.ToUpper
Case PropertyName
objProp = dpPanel.Value 'this is the point of crash
Exit For
End Select
Next
Catch ex As System.Exception
Dim aex As New System.Exception("Error getting dynamic property for " & PropertyName, ex)
Throw aex
End Try
End If
End If
'trans.Commit()
Catch ex As System.Exception
Dim aex As New System.Exception("Error getting dynamic property for " & PropertyName, ex)
Throw aex
Finally
If Not trans Is Nothing Then trans.Dispose()
If Not dlock Is Nothing Then dlock.Dispose()
End Try
End Using
Return objProp
End Function
Message 35 of 46
jason.brenton
in reply to: kapes13

alright, i see a line you mark as the issue line:
objProp = dpPanel.Value 'this is the point of crash

Since you set this to a object of no instance and containing nothing, its not gonna work. you might try something like this

dim baseType as string = dpPanel.value.gettype

then using that, establish a type transition case or similar

select case baseType
case "Long"
'retrieve long
dim lValue as long =DirectCast( dpPanel.value, Long)

now lValue could have the property value.
This pattern seems to work with string types (visibility), but i am not sure which number types to expect. probably doubles.
Message 36 of 46
Anonymous
in reply to: kapes13

Accessing Dynamic block properties requires that the BlockReference that owns the properties be open in a transaction.

The problem is that when you access the dynamic block insertion via the DBObject property of the ObjectEventArgs from the handler of an event that passes that type (like ObjectModified), you cannot assume the notifying DBObject is open in a transaction.

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2008
Supporting AutoCAD 2000 through 2008
http://www.acadxtabs.com

wrote in message news:5864334@discussion.autodesk.com...
This is my standard block (dynamic) insert from file technique...

Private box1 As Point3d
Private box2 As Point3d
Private brPanel As BlockReference
Private btrPanel As BlockTableRecord

Public Sub InsertNewPanel()
Dim dblInsert As Point3d
Dim dblP2 As Point3d
Dim objResult As PromptPointResult
Dim bt As BlockTable
Dim btr As BlockTableRecord = Nothing
Dim btrMSpace As BlockTableRecord
Dim id As ObjectId
Dim db As Autodesk.AutoCAD.DatabaseServices.Database = HostApplicationServices.WorkingDatabase
Using trans As Transaction = db.TransactionManager.StartTransaction
Dim ed As Autodesk.AutoCAD.EditorInput.Editor = Application.DocumentManager.MdiActiveDocument.Editor
'insert block and rename it
Try
'pick single insert point method
'add support for pick box method
Dim op As PromptPointOptions = New PromptPointOptions("Pick the location for the new shear wall panel")
op.AllowArbitraryInput = False
op.AllowNone = False
objResult = ed.GetPoint(op)
If objResult.Status = PromptStatus.Error Then MsgBox("Pick error" & objResult.Status.ToString)
If objResult.Status = PromptStatus.OK Then
dblInsert = objResult.Value
'insert by box section
If Building.InsertByBox = True Then
Dim pco As New PromptCornerOptions("Pick second point for Panel: ", dblInsert)
pco.AllowArbitraryInput = False
pco.AllowNone = False
pco.UseDashedLine = True
Dim ppr As PromptPointResult = ed.GetCorner(pco)
If ppr.Status = PromptStatus.OK Then
dblP2 = ppr.Value
End If
End If
'add getCorner and insert block to fit in box
bt = trans.GetObject(db.BlockTableId, OpenMode.ForWrite)
If bt.Has(srwlBuilding.strSourcePanelBlockName) Then
'block found, get instance for copying
btrPanel = trans.GetObject(bt.Item(srwlBuilding.strSourcePanelBlockName), OpenMode.ForRead)
Else
'block not found, insert into drawing
Using sourcedb As Database = New Database(False, False)
Try
sourcedb.ReadDwgFile(srwlBuilding.strSourcePanelBlockPath, IO.FileShare.Read, True, "")
id = db.Insert(srwlBuilding.strSourcePanelBlockPath, sourcedb, True)
btrPanel = trans.GetObject(id, OpenMode.ForWrite)
btrPanel.Name = "Panel-" & Name & "-" & PanelID.ToString
Catch ex As System.Exception
Dim aex As New System.Exception("Block file not found" & srwlBuilding.strSourcePanelBlockPath & "-", ex)
Throw aex
Exit Sub
End Try
sourcedb.Dispose()
End Using
End If
btrMSpace = trans.GetObject(bt(BlockTableRecord.ModelSpace), OpenMode.ForWrite)
brPanel = New BlockReference(dblInsert, btrPanel.ObjectId)
btrMSpace.AppendEntity(brPanel)
trans.AddNewlyCreatedDBObject(brPanel, True)
Me.BlockRefHandle = brPanel.Handle
Me.BlockHandle = btrPanel.Handle
End If
trans.Commit()
Catch ex As System.Exception
Dim aex2 As New System.Exception("Error in inserting new Panel block. ", ex)
Throw aex2
Finally
ed.WriteMessage(vbLf & "Command: ")
If Not trans Is Nothing Then trans.Dispose()
End Try
If Building.InsertByBox = True Then
Try
SetShape(dblInsert, dblP2)
Catch ex As System.Exception
Dim aex3 As New System.Exception("Error while setting Panel shape: ", ex)
Throw aex3
End Try
End If
SetDefaults()
End Using
End Sub

this chunk is responsible for putting the dynamic block into the drawing into modelspace.

This next chunk is my event handler that listens to AutoCAD. It is fired off 3 time when modifying a (dynamic only) property using AutoCAD's built in properties palette. If the object is 'found' to be one of the objects I am tracking in my object tree, then I react by re-reading the objects properties. When the code reads the dynamic properties, third time (event triggered) crashes, because no dynamic properties can be found (kind of...)


Private Sub callback_ObjectModified(ByVal sender As Object, ByVal e As ObjectEventArgs)
If IgnoreEvents Then Exit Sub
Dim ibe As Boolean = Me.IgnoreEvents
Try
IgnoreEvents = True
If Not e.DBObject.IsWriteEnabled Then
IgnoreEvents = ibe
WorkEvent(e.DBObject, "Modified")
End If
Catch ex As System.Exception
Dim aex As New System.Exception("Error at Modify Object AutoCAD Event: ", ex)
Me.HandleError(aex)
Finally
IgnoreEvents = ibe
End Try
End Sub

Public Sub WorkEvent(ByRef dbObject As DBObject, ByVal strTask As String)
Try
Select Case dbObject.GetType.ToString
Case "Autodesk.AutoCAD.DatabaseServices.BlockReference"
'If e.DBObject.IsModified = False Then
'Debug.Print("BlockReference " & strTask)
Try
Dim objCheck As Object = Me.Levels.ContainsHandle(dbObject.Handle)
If objCheck(0) Then
'Debug.Print(objCheck(1).ToString & objCheck(2).ToString)
Select Case strTask
Case "Added"
Case "Modified"
Me.ReactToChange(objCheck)
Case "Erased"
Me.ReactToErased(objCheck)
Case "UnErased"
Me.ReactToUnErase(objCheck)
End Select
End If
Catch ex As System.Exception
Dim aex As New System.Exception("Error working BlockReference event: ", ex)
Throw aex
End Try
'End If
Case "Autodesk.AutoCAD.DatabaseServices.Polyline"
'Debug.Print("Polyline " & strTask)
Try
Dim objCheck As Object = Me.Levels.ContainsHandle(dbObject.Handle)
If objCheck(0) Then
'Debug.Print(objCheck(1).ToString & objCheck(2).ToString)
Select Case strTask
Case "Added"
Case "Modified"
Me.ReactToChange(objCheck)
Case "Erased"
Me.ReactToErased(objCheck)
Case "UnErased"
Me.ReactToUnErase(objCheck)
End Select
End If
Catch ex As System.Exception
Dim aex As New System.Exception("Error working Polyline event: ", ex)
Throw aex
End Try
End Select
Catch ex As System.Exception
Dim aex As New System.Exception("Error Working Event: ", ex)
Throw aex
End Try
End Sub

This is the snippet that accesses the dynamic property as a separate process from a custom built palette.

Public Overridable Function GetDynProperty(ByVal bref As BlockReference, ByVal PropertyName As String) As Object
Dim db As Autodesk.AutoCAD.DatabaseServices.Database = HostApplicationServices.WorkingDatabase
Dim ThisDrawing As Autodesk.AutoCAD.ApplicationServices.Document = Application.DocumentManager.MdiActiveDocument
Dim objProp As Object = Nothing
Using trans As Transaction = db.TransactionManager.StartTransaction
Dim dlock As DocumentLock = Nothing
Try
Try
dlock = ThisDrawing.LockDocument
Catch ex As Exception
Dim aex As New System.Exception("Error locking document for to get Dynamic Property: ", ex)
Throw aex
End Try
Dim brObj As BlockReference = trans.GetObject(bref.Id, OpenMode.ForRead)
If Not brObj Is Nothing Then
Dim dpcPanel As DynamicBlockReferencePropertyCollection
Dim dpPanel As DynamicBlockReferenceProperty
If brObj.IsDynamicBlock = True Then
Try
dpcPanel = brObj.DynamicBlockReferencePropertyCollection
For Each dpPanel In dpcPanel
Select Case dpPanel.PropertyName.ToUpper
Case PropertyName
objProp = dpPanel.Value 'this is the point of crash
Exit For
End Select
Next
Catch ex As System.Exception
Dim aex As New System.Exception("Error getting dynamic property for " & PropertyName, ex)
Throw aex
End Try
End If
End If
'trans.Commit()
Catch ex As System.Exception
Dim aex As New System.Exception("Error getting dynamic property for " & PropertyName, ex)
Throw aex
Finally
If Not trans Is Nothing Then trans.Dispose()
If Not dlock Is Nothing Then dlock.Dispose()
End Try
End Using
Return objProp
End Function
Message 37 of 46
Anonymous
in reply to: kapes13

>> Since you set this to a object of no instance and containing nothing, its not gonna work. you might try something like this...<<

Why is it 'not gonna work' ?

There's nothing wrong with that statement.

The variable is typed as 'Object', and the Value property of the dblock property is 'Object', so you are completely off base here.

The problem is that accessing dynamic block properties requires the dynamic block insertion that owns the properties to be open in a transaction, which is not always the case when the instance it is obtained through the DBObject property of the event handler arguments.

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2008
Supporting AutoCAD 2000 through 2008
http://www.acadxtabs.com

wrote in message news:5864360@discussion.autodesk.com...
alright, i see a line you mark as the issue line:
objProp = dpPanel.Value 'this is the point of crash

Since you set this to a object of no instance and containing nothing, its not gonna work. you might try something like this

dim baseType as string = dpPanel.value.gettype

then using that, establish a type transition case or similar

select case baseType
case "Long"
'retrieve long
dim lValue as long =DirectCast( dpPanel.value, Long)

now lValue could have the property value.
This pattern seems to work with string types (visibility), but i am not sure which number types to expect. probably doubles.
Message 38 of 46
foruma000256
in reply to: kapes13

My event handler works great when the user makes a modification on screen, or changes any other non-dynamic property, because like Tony said, I am accessing the object using a transaction that is outside of the DBObject's scope.

I only use db object to find the block reference's handle. I use the handle to find if It is one of my live data objects. Then I use a separate process to open the object based on its stored live object ID.

When working with the properties palette I get more than 1 object modified event. It is during this process that something is screwy. While handling the events I am able to prevent the system from crashing autoCAD, but the end result is a set of blocks separated from their dynamic properties. (the handels move, but not the line work.) Can anybody else verify this result?
Message 39 of 46
Anonymous
in reply to: kapes13

>> Me.ReactToChange(objCheck)

Sorry, I don't see any sub with that name.

You're not show what your code is doing in the ObjectModified event handler context.

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2008
Supporting AutoCAD 2000 through 2008
http://www.acadxtabs.com

wrote in message news:5864498@discussion.autodesk.com...
My event handler works great when the user makes a modification on screen, or changes any other non-dynamic property, because like Tony said, I am accessing the object using a transaction that is outside of the DBObject's scope.

I only use db object to find the block reference's handle. I use the handle to find if It is one of my live data objects. Then I use a separate process to open the object based on its stored live object ID.

When working with the properties palette I get more than 1 object modified event. It is during this process that something is screwy. While handling the events I am able to prevent the system from crashing autoCAD, but the end result is a set of blocks separated from their dynamic properties. (the handels move, but not the line work.) Can anybody else verify this result?
Message 40 of 46
foruma000256
in reply to: kapes13

It is there. Just above the work event routine. They work together. The handler verifies the event (i try to filter out the object's IsWriteEnabled first to no avail), the work event verifies the object, and sends a custom event to the custom form with this line:

Public Sub PublishEvent(ByVal objType As String, ByVal eventType As String, ByVal id As Object)
RaiseEvent ObjectChanged(objType, eventType, id)
End Sub

(palette set based). Which then responds by running these lines of code:
...
Case "Modified"
Dim int As Integer = FindRow(Me.dgridPanelList, id)
If int = -1 Then Exit Sub
Dim objPanelRow As DataGridViewRow = dgridPanelList.Rows(int)
Dim objPanel As srwlPanel = Building.Levels.ContainsPanel(id)
objPanelRow.Cells("PanelID").Value = objPanel.PanelID
objPanelRow.Cells("Panel").Value = objPanel.Name
objPanelRow.Cells("PlateHeight").Value = objPanel.PlateHeight
objPanelRow.Cells("Length").Value = objPanel.Length
objPanelRow.Cells("Shear").Value = objPanel.Shear
objPanelRow.Cells("Tension").Value = objPanel.Tension
objPanelRow.Cells("UnitMaxShear").Value = objPanel.UnitMaxShear
objPanelRow.Cells("PanelDirection").Value = (objPanel.Direction * 180 / Math.PI) 'from radians to degrees
objPanelRow.Cells("Level").Value = objPanel.Level.Name
objPanelRow.Cells("Material").Value = objPanel.Material
objPanelRow.Cells("FullHeight").Value = objPanel.FullHeight
objPanelRow.Cells("Co").Value = objPanel.Co
objPanelRow.Cells("Reaction1").Value = objPanel.Reaction1
objPanelRow.Cells("Reaction2").Value = objPanel.Reaction2
objPanelRow.Cells("StackedWalls").Value = objPanel.StackedWalls
Me.objBuilding_ObjectChanged("Level", "Modified", objPanel.Level.LevelID)

These lines start from the custom form's point of view and go to GET the properties from scratch, not from the DBObject.
Which then runs the get dynamic property function to return the 'Length' value to the form.

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