Inventor · iLogic · 1 dzień temu · zaktualizowano dzisiaj
Oznaczenie grubości materiałów arkuszowych na rysunku
'==============================================================================
' iLogic_GruboscWskaznik.vb - Autodesk Inventor iLogic rule (single file)
' Thickness callout (leader note) on a drawing view.
'
' WHAT THIS RULE DOES
' On the active Drawing (.idw / .dwg):
' 1) Click a view that references a Part (.ipt)
' -> arrow tip = click point, text = thickness "x..."
' 2) Move mouse for live preview, click again to place the text
' Sheet-metal Part: reads SheetMetal Thickness (linked FormattedText).
' Regular Part: tries UserParameter named "Thickness".
' If no parameter: plain text "x" + fallback 1.5 mm (not linked to model).
' Esc cancels and removes the preview leader.
'
' HOW TO USE
' 1) Optional: edit CfgThicknessNumberFormat below (display digits).
' 2) Inventor: External Rules -> Add Rule -> select this .vb / .iLogicVb
' (prefer local disk, not W:\ / OneDrive - same tip as Save.iLogicVb).
' 3) Open a Drawing, run the rule, click view then text position (Esc = cancel).
'
' CONFIG (Cfg*) - change Return value only:
' CfgThicknessNumberFormat
'
' NOTES FOR BEGINNERS
' - iLogic = VB.NET (not VBA). Sub Main must come first.
' - Do NOT put Dim / Const / Shared above Main - iLogic will not compile.
' The one setting is a Function that Returns a value (same idea as Save.iLogicVb).
' - ThisApplication is given by iLogic.
' - Inventor database length = cm. Drawing notes / Point2d are in cm.
' Thickness DISPLAY is in mm (cm * 10). Decimal comma for PL drawings.
' - References: System.Windows.Forms (DoEvents loop while picking).
' - Interaction logic lives in Class TwoPointPicker (fields OK inside Class).
' - Class cannot call module-level Cfg* Functions (iLogic: "object reference").
' Main reads Cfg* and assigns NumberFormat on the picker instance.
' - All MsgBox / StatusBar text is English (ASCII-safe).
'==============================================================================
'===== ENTRY ==================================================================
Sub Main()
' ThisApplication = Inventor session provided by iLogic.
Dim invApp As Inventor.Application = ThisApplication
' This tool works only on drawings - cast fails for Part / Assembly.
Dim oDrawDoc As DrawingDocument = TryCast(invApp.ActiveDocument, DrawingDocument)
If oDrawDoc Is Nothing Then
MsgBox("Open a drawing document (.idw/.dwg).", MsgBoxStyle.Exclamation, "Thickness indicator")
Return
End If
' TwoPointPicker: interactive click-1 (view+arrow) / click-2 (text position).
Dim picker As New TwoPointPicker()
picker.DrawDoc = oDrawDoc
' Pass Cfg into Class (Class must not call module Functions directly).
picker.NumberFormat = CfgThicknessNumberFormat()
' False = user cancelled (Esc) or clicks incomplete - leave drawing unchanged.
If Not picker.Run(invApp) Then Return
' Refresh sheet after the final leader note is placed.
oDrawDoc.Update()
End Sub
'----- SETTINGS (edit Return value) -------------------------------------------
' Only number display format is configurable. Everything else is fixed in code.
' Implemented as Function: iLogic forbids module-level Const/fields
' (same pattern as Save.iLogicVb / ObliczeniaBlach.ilogicVb).
Function CfgThicknessNumberFormat() As String
' .NET format for the thickness number (InvariantCulture first, then ",").
' "0.###" = up to 3 decimals, trailing zeros trimmed (e.g. 1.5 -> "1,5").
' Change Return, save the rule, run again.
Return "0.###"
End Function
'===== PICKER CLASS ===========================================================
' Owns InteractionEvents + MouseEvents for the two-click workflow.
' Public fields are filled for Main / callers; Private fields are session state.
Class TwoPointPicker
' Inventor Application used to create TransientGeometry / InteractionEvents.
Private _app As Inventor.Application
' Interaction session (status bar text, Start/Stop, Esc -> OnTerminate).
Private WithEvents _interact As InteractionEvents
' Mouse click + move while interaction is running.
Private WithEvents _mouse As MouseEvents
' 1 = waiting for view/arrow click; 2 = waiting for text position click.
Private _step As Integer
' True when Esc, second click, or terminate ends the DoEvents loop.
Private _done As Boolean
' FormattedText built on click 1 (plain "x..." or linked <Parameter> XML).
Private _noteText As String
' Temporary LeaderNote shown during move; kept as final note on click 2.
Private _previewLeader As LeaderNote
' Last preview text position (cm) - used to ignore tiny mouse moves.
Private _lastPreviewX As Double
Private _lastPreviewY As Double
' False until the first preview leader exists.
Private _hasPreviewPos As Boolean
' Drawing that receives the LeaderNote (set from Main).
Public DrawDoc As DrawingDocument
' View chosen on click 1 (must reference a Part).
Public SelectedView As DrawingView
' Text position (click 2) - sheet Point2d in cm.
Public Point1 As Point2d
' Arrow tip (click 1) - sheet Point2d in cm.
Public Point2 As Point2d
' Set from Main via CfgThicknessNumberFormat() - do not call Cfg* from Class.
Public NumberFormat As String
Public Function Run(app As Inventor.Application) As Boolean
' Start interactive pick. Returns True only if view + both points exist.
_app = app
_step = 1
_done = False
_hasPreviewPos = False
' CreateInteractionEvents: Inventor UI mode for custom mouse handling.
_interact = _app.CommandManager.CreateInteractionEvents()
_interact.StatusBarText = "Click 1/2: view and arrow tip (Esc = cancel)"
_mouse = _interact.MouseEvents
' No snap-to-geometry inference - use raw model/sheet click coordinates.
_mouse.PointInferenceEnabled = False
' Need move events for live leader preview in step 2.
_mouse.MouseMoveEnabled = True
_interact.Start()
' Keep the rule thread pumping Windows messages until _done.
' Without DoEvents the UI would freeze and clicks would not arrive.
Do While Not _done
System.Windows.Forms.Application.DoEvents()
Loop
_interact.Stop()
' Success only when all three results are set (Esc clears preview, leaves nulls).
Return SelectedView IsNot Nothing AndAlso Point1 IsNot Nothing AndAlso Point2 IsNot Nothing
End Function
Private Sub _mouse_OnMouseClick(Button As MouseButtonEnum, ShiftKeys As ShiftStateEnum, ModelPosition As Inventor.Point, ViewPosition As Point2d, ByVal InvView As Inventor.View) Handles _mouse.OnMouseClick
' Only left button advances the workflow.
If Button <> MouseButtonEnum.kLeftMouseButton Then Return
' ModelPosition is sheet space for drawing interaction (X/Y in cm).
Dim pt As Point2d = _app.TransientGeometry.CreatePoint2d(ModelPosition.X, ModelPosition.Y)
If _step = 1 Then
' ----- CLICK 1: pick view + arrow tip, build note text -----
Dim oView As DrawingView = FindViewAtPoint(DrawDoc.ActiveSheet, pt)
If oView Is Nothing Then
MsgBox("Click inside a drawing view.", MsgBoxStyle.Exclamation, "Thickness indicator")
Return
End If
' View must point at a Part document (.ipt), not Assembly / Drawing.
Dim oModel As Inventor.Document = oView.ReferencedDocumentDescriptor.ReferencedDocument
If oModel Is Nothing OrElse oModel.DocumentType <> DocumentTypeEnum.kPartDocumentObject Then
MsgBox("View must reference a part (.ipt).", MsgBoxStyle.Exclamation, "Thickness indicator")
Return
End If
SelectedView = oView
Point2 = pt
_noteText = BuildThicknessFormattedText(CType(oModel, PartDocument), oView)
_step = 2
_interact.StatusBarText = "Click 2/2: text position (Esc = cancel)"
' First preview: text and arrow at the same point until mouse moves.
ShowPreview(pt)
Else
' ----- CLICK 2: lock text position; keep preview as the real note -----
Point1 = pt
ShowPreview(pt)
' Drop our reference without Delete - note stays on the sheet.
_previewLeader = Nothing
_done = True
End If
End Sub
Private Sub _mouse_OnMouseMove(Button As MouseButtonEnum, ShiftKeys As ShiftStateEnum, ModelPosition As Inventor.Point, ViewPosition As Point2d, ByVal InvView As Inventor.View) Handles _mouse.OnMouseMove
' Live preview only after click 1 (arrow tip Point2 already known).
If _step <> 2 OrElse Point2 Is Nothing Then Return
ShowPreview(_app.TransientGeometry.CreatePoint2d(ModelPosition.X, ModelPosition.Y))
End Sub
Private Sub _interact_OnTerminate() Handles _interact.OnTerminate
' Esc / cancel / interaction ended before click 2.
' If we never finished, remove the temporary preview leader.
If Not _done Then ClearPreview()
_done = True
End Sub
Private Sub ShowPreview(textPt As Point2d)
' Rebuild LeaderNote at textPt -> Point2 (arrow).
' Skip moves smaller than 0.05 cm to avoid delete/add every pixel.
If _hasPreviewPos AndAlso _
Math.Abs(_lastPreviewX - textPt.X) < 0.05 AndAlso _
Math.Abs(_lastPreviewY - textPt.Y) < 0.05 Then Return
ClearPreview()
' LeaderNotes.Add expects: first point = text, last point = arrow tip.
Dim oLeaderPts As ObjectCollection = _app.TransientObjects.CreateObjectCollection
oLeaderPts.Add(textPt)
oLeaderPts.Add(Point2)
_previewLeader = DrawDoc.ActiveSheet.DrawingNotes.LeaderNotes.Add(oLeaderPts, "")
' FormattedText can be plain string or Inventor XML with <Parameter>.
_previewLeader.FormattedText = _noteText
' Small dot arrowhead (less visual clutter than a filled arrow).
_previewLeader.Leader.ArrowheadType = ArrowheadTypeEnum.kSmallDotArrowheadType
_lastPreviewX = textPt.X
_lastPreviewY = textPt.Y
_hasPreviewPos = True
DrawDoc.Update()
End Sub
Private Sub ClearPreview()
' Delete temporary leader if it still exists on the sheet.
If _previewLeader Is Nothing Then Return
Try
_previewLeader.Delete()
Catch
' Ignore if already deleted by the user / Inventor.
End Try
_previewLeader = Nothing
_hasPreviewPos = False
End Sub
Private Function FindViewAtPoint(oSheet As Sheet, pt As Point2d) As DrawingView
' Hit-test: which DrawingView rectangle contains the sheet point (cm).
' Walk from last to first so the top-most (later) view wins when stacked.
For i As Integer = oSheet.DrawingViews.Count To 1 Step -1
Dim oView As DrawingView = oSheet.DrawingViews.Item(i)
Dim pos As Point2d = oView.Position
Dim halfW As Double = oView.Width / 2.0
Dim halfH As Double = oView.Height / 2.0
If pt.X >= pos.X - halfW AndAlso pt.X <= pos.X + halfW AndAlso _
pt.Y >= pos.Y - halfH AndAlso pt.Y <= pos.Y + halfH Then
Return oView
End If
Next
Return Nothing
End Function
Private Function BuildThicknessFormattedText(oPart As PartDocument, oView As DrawingView) As String
' Build the LeaderNote string: "x" + value, optionally linked to Thickness.
Dim thicknessParam As Parameter = Nothing
' Inventor Parameter.Value for length is cm. Fallback 1.5 mm = 0.15 cm.
Dim thicknessInventorCm As Double = 0.15
Dim cd As ComponentDefinition = oPart.ComponentDefinition
If TypeOf cd Is SheetMetalComponentDefinition Then
' Sheet metal: Thickness is a first-class property (always present).
thicknessParam = CType(cd, SheetMetalComponentDefinition).Thickness
thicknessInventorCm = thicknessParam.Value
Else
' Regular part: only if a UserParameter named "Thickness" exists.
Try
thicknessParam = oPart.ComponentDefinition.Parameters.UserParameters.Item("Thickness")
thicknessInventorCm = thicknessParam.Value
Catch
' Keep fallback 0.15 cm; thicknessParam stays Nothing -> plain text.
End Try
End If
' Display mm = cm * 10; format uses NumberFormat + decimal comma.
Dim displayValue As String = FormatThicknessForDrawing(thicknessInventorCm * 10.0)
If thicknessParam Is Nothing Then
' No model link - static text only (will not update if thickness changes).
Return "x" & displayValue
End If
' ComponentIdentifier: path Inventor uses to resolve the parameter later.
Dim componentId As String = oPart.FullFileName
If String.IsNullOrEmpty(componentId) Then
' Unsaved part - fall back to the view descriptor document name.
componentId = oView.ReferencedDocumentDescriptor.FullDocumentName
End If
' Linked FormattedText XML: Inventor refreshes the number when Thickness changes.
' Precision='3' = up to 3 digits after decimal in the linked display.
Return "x<Parameter Resolved='True' ComponentIdentifier='" & EscapeXmlAttribute(componentId) & _
"' Name='" & EscapeXmlAttribute(thicknessParam.Name) & _
"' Precision='3'>" & displayValue & "</Parameter>"
End Function
Private Function EscapeXmlAttribute(value As String) As String
' FormattedText attributes use single quotes - escape ' inside paths/names.
If String.IsNullOrEmpty(value) Then Return ""
Return value.Replace("'"c, "'")
End Function
Private Function FormatThicknessForDrawing(valueMm As Double) As String
' 1) Format with .NET pattern from Main (CfgThicknessNumberFormat).
' 2) Replace "." with "," for Polish drawing convention.
Dim fmt As String = NumberFormat
If String.IsNullOrEmpty(fmt) Then fmt = "0.###"
Return valueMm.ToString(fmt, Globalization.CultureInfo.InvariantCulture).Replace("."c, ","c)
End Function
End Class
'==============================================================================
' iLogic_GruboscWskaznik.vb - Autodesk Inventor iLogic rule (single file)
' Thickness callout (leader note) on a drawing view.
'
' WHAT THIS RULE DOES
' On the active Drawing (.idw / .dwg):
' 1) Click a view that references a Part (.ipt)
' -> arrow tip = click point, text = thickness "x..."
' 2) Move mouse for live preview, click again to place the text
' Sheet-metal Part: reads SheetMetal Thickness (linked FormattedText).
' Regular Part: tries UserParameter named "Thickness".
' If no parameter: plain text "x" + fallback 1.5 mm (not linked to model).
' Esc cancels and removes the preview leader.
'
' HOW TO USE
' 1) Optional: edit CfgThicknessNumberFormat below (display digits).
' 2) Inventor: External Rules -> Add Rule -> select this .vb / .iLogicVb
' (prefer local disk, not W:\ / OneDrive - same tip as Save.iLogicVb).
' 3) Open a Drawing, run the rule, click view then text position (Esc = cancel).
'
' CONFIG (Cfg*) - change Return value only:
' CfgThicknessNumberFormat
'
' NOTES FOR BEGINNERS
' - iLogic = VB.NET (not VBA). Sub Main must come first.
' - Do NOT put Dim / Const / Shared above Main - iLogic will not compile.
' The one setting is a Function that Returns a value (same idea as Save.iLogicVb).
' - ThisApplication is given by iLogic.
' - Inventor database length = cm. Drawing notes / Point2d are in cm.
' Thickness DISPLAY is in mm (cm * 10). Decimal comma for PL drawings.
' - References: System.Windows.Forms (DoEvents loop while picking).
' - Interaction logic lives in Class TwoPointPicker (fields OK inside Class).
' - Class cannot call module-level Cfg* Functions (iLogic: "object reference").
' Main reads Cfg* and assigns NumberFormat on the picker instance.
' - All MsgBox / StatusBar text is English (ASCII-safe).
'==============================================================================
'===== ENTRY ==================================================================
Sub Main()
' ThisApplication = Inventor session provided by iLogic.
Dim invApp As Inventor.Application = ThisApplication
' This tool works only on drawings - cast fails for Part / Assembly.
Dim oDrawDoc As DrawingDocument = TryCast(invApp.ActiveDocument, DrawingDocument)
If oDrawDoc Is Nothing Then
MsgBox("Open a drawing document (.idw/.dwg).", MsgBoxStyle.Exclamation, "Thickness indicator")
Return
End If
' TwoPointPicker: interactive click-1 (view+arrow) / click-2 (text position).
Dim picker As New TwoPointPicker()
picker.DrawDoc = oDrawDoc
' Pass Cfg into Class (Class must not call module Functions directly).
picker.NumberFormat = CfgThicknessNumberFormat()
' False = user cancelled (Esc) or clicks incomplete - leave drawing unchanged.
If Not picker.Run(invApp) Then Return
' Refresh sheet after the final leader note is placed.
oDrawDoc.Update()
End Sub
'----- SETTINGS (edit Return value) -------------------------------------------
' Only number display format is configurable. Everything else is fixed in code.
' Implemented as Function: iLogic forbids module-level Const/fields
' (same pattern as Save.iLogicVb / ObliczeniaBlach.ilogicVb).
Function CfgThicknessNumberFormat() As String
' .NET format for the thickness number (InvariantCulture first, then ",").
' "0.###" = up to 3 decimals, trailing zeros trimmed (e.g. 1.5 -> "1,5").
' Change Return, save the rule, run again.
Return "0.###"
End Function
'===== PICKER CLASS ===========================================================
' Owns InteractionEvents + MouseEvents for the two-click workflow.
' Public fields are filled for Main / callers; Private fields are session state.
Class TwoPointPicker
' Inventor Application used to create TransientGeometry / InteractionEvents.
Private _app As Inventor.Application
' Interaction session (status bar text, Start/Stop, Esc -> OnTerminate).
Private WithEvents _interact As InteractionEvents
' Mouse click + move while interaction is running.
Private WithEvents _mouse As MouseEvents
' 1 = waiting for view/arrow click; 2 = waiting for text position click.
Private _step As Integer
' True when Esc, second click, or terminate ends the DoEvents loop.
Private _done As Boolean
' FormattedText built on click 1 (plain "x..." or linked <Parameter> XML).
Private _noteText As String
' Temporary LeaderNote shown during move; kept as final note on click 2.
Private _previewLeader As LeaderNote
' Last preview text position (cm) - used to ignore tiny mouse moves.
Private _lastPreviewX As Double
Private _lastPreviewY As Double
' False until the first preview leader exists.
Private _hasPreviewPos As Boolean
' Drawing that receives the LeaderNote (set from Main).
Public DrawDoc As DrawingDocument
' View chosen on click 1 (must reference a Part).
Public SelectedView As DrawingView
' Text position (click 2) - sheet Point2d in cm.
Public Point1 As Point2d
' Arrow tip (click 1) - sheet Point2d in cm.
Public Point2 As Point2d
' Set from Main via CfgThicknessNumberFormat() - do not call Cfg* from Class.
Public NumberFormat As String
Public Function Run(app As Inventor.Application) As Boolean
' Start interactive pick. Returns True only if view + both points exist.
_app = app
_step = 1
_done = False
_hasPreviewPos = False
' CreateInteractionEvents: Inventor UI mode for custom mouse handling.
_interact = _app.CommandManager.CreateInteractionEvents()
_interact.StatusBarText = "Click 1/2: view and arrow tip (Esc = cancel)"
_mouse = _interact.MouseEvents
' No snap-to-geometry inference - use raw model/sheet click coordinates.
_mouse.PointInferenceEnabled = False
' Need move events for live leader preview in step 2.
_mouse.MouseMoveEnabled = True
_interact.Start()
' Keep the rule thread pumping Windows messages until _done.
' Without DoEvents the UI would freeze and clicks would not arrive.
Do While Not _done
System.Windows.Forms.Application.DoEvents()
Loop
_interact.Stop()
' Success only when all three results are set (Esc clears preview, leaves nulls).
Return SelectedView IsNot Nothing AndAlso Point1 IsNot Nothing AndAlso Point2 IsNot Nothing
End Function
Private Sub _mouse_OnMouseClick(Button As MouseButtonEnum, ShiftKeys As ShiftStateEnum, ModelPosition As Inventor.Point, ViewPosition As Point2d, ByVal InvView As Inventor.View) Handles _mouse.OnMouseClick
' Only left button advances the workflow.
If Button <> MouseButtonEnum.kLeftMouseButton Then Return
' ModelPosition is sheet space for drawing interaction (X/Y in cm).
Dim pt As Point2d = _app.TransientGeometry.CreatePoint2d(ModelPosition.X, ModelPosition.Y)
If _step = 1 Then
' ----- CLICK 1: pick view + arrow tip, build note text -----
Dim oView As DrawingView = FindViewAtPoint(DrawDoc.ActiveSheet, pt)
If oView Is Nothing Then
MsgBox("Click inside a drawing view.", MsgBoxStyle.Exclamation, "Thickness indicator")
Return
End If
' View must point at a Part document (.ipt), not Assembly / Drawing.
Dim oModel As Inventor.Document = oView.ReferencedDocumentDescriptor.ReferencedDocument
If oModel Is Nothing OrElse oModel.DocumentType <> DocumentTypeEnum.kPartDocumentObject Then
MsgBox("View must reference a part (.ipt).", MsgBoxStyle.Exclamation, "Thickness indicator")
Return
End If
SelectedView = oView
Point2 = pt
_noteText = BuildThicknessFormattedText(CType(oModel, PartDocument), oView)
_step = 2
_interact.StatusBarText = "Click 2/2: text position (Esc = cancel)"
' First preview: text and arrow at the same point until mouse moves.
ShowPreview(pt)
Else
' ----- CLICK 2: lock text position; keep preview as the real note -----
Point1 = pt
ShowPreview(pt)
' Drop our reference without Delete - note stays on the sheet.
_previewLeader = Nothing
_done = True
End If
End Sub
Private Sub _mouse_OnMouseMove(Button As MouseButtonEnum, ShiftKeys As ShiftStateEnum, ModelPosition As Inventor.Point, ViewPosition As Point2d, ByVal InvView As Inventor.View) Handles _mouse.OnMouseMove
' Live preview only after click 1 (arrow tip Point2 already known).
If _step <> 2 OrElse Point2 Is Nothing Then Return
ShowPreview(_app.TransientGeometry.CreatePoint2d(ModelPosition.X, ModelPosition.Y))
End Sub
Private Sub _interact_OnTerminate() Handles _interact.OnTerminate
' Esc / cancel / interaction ended before click 2.
' If we never finished, remove the temporary preview leader.
If Not _done Then ClearPreview()
_done = True
End Sub
Private Sub ShowPreview(textPt As Point2d)
' Rebuild LeaderNote at textPt -> Point2 (arrow).
' Skip moves smaller than 0.05 cm to avoid delete/add every pixel.
If _hasPreviewPos AndAlso _
Math.Abs(_lastPreviewX - textPt.X) < 0.05 AndAlso _
Math.Abs(_lastPreviewY - textPt.Y) < 0.05 Then Return
ClearPreview()
' LeaderNotes.Add expects: first point = text, last point = arrow tip.
Dim oLeaderPts As ObjectCollection = _app.TransientObjects.CreateObjectCollection
oLeaderPts.Add(textPt)
oLeaderPts.Add(Point2)
_previewLeader = DrawDoc.ActiveSheet.DrawingNotes.LeaderNotes.Add(oLeaderPts, "")
' FormattedText can be plain string or Inventor XML with <Parameter>.
_previewLeader.FormattedText = _noteText
' Small dot arrowhead (less visual clutter than a filled arrow).
_previewLeader.Leader.ArrowheadType = ArrowheadTypeEnum.kSmallDotArrowheadType
_lastPreviewX = textPt.X
_lastPreviewY = textPt.Y
_hasPreviewPos = True
DrawDoc.Update()
End Sub
Private Sub ClearPreview()
' Delete temporary leader if it still exists on the sheet.
If _previewLeader Is Nothing Then Return
Try
_previewLeader.Delete()
Catch
' Ignore if already deleted by the user / Inventor.
End Try
_previewLeader = Nothing
_hasPreviewPos = False
End Sub
Private Function FindViewAtPoint(oSheet As Sheet, pt As Point2d) As DrawingView
' Hit-test: which DrawingView rectangle contains the sheet point (cm).
' Walk from last to first so the top-most (later) view wins when stacked.
For i As Integer = oSheet.DrawingViews.Count To 1 Step -1
Dim oView As DrawingView = oSheet.DrawingViews.Item(i)
Dim pos As Point2d = oView.Position
Dim halfW As Double = oView.Width / 2.0
Dim halfH As Double = oView.Height / 2.0
If pt.X >= pos.X - halfW AndAlso pt.X <= pos.X + halfW AndAlso _
pt.Y >= pos.Y - halfH AndAlso pt.Y <= pos.Y + halfH Then
Return oView
End If
Next
Return Nothing
End Function
Private Function BuildThicknessFormattedText(oPart As PartDocument, oView As DrawingView) As String
' Build the LeaderNote string: "x" + value, optionally linked to Thickness.
Dim thicknessParam As Parameter = Nothing
' Inventor Parameter.Value for length is cm. Fallback 1.5 mm = 0.15 cm.
Dim thicknessInventorCm As Double = 0.15
Dim cd As ComponentDefinition = oPart.ComponentDefinition
If TypeOf cd Is SheetMetalComponentDefinition Then
' Sheet metal: Thickness is a first-class property (always present).
thicknessParam = CType(cd, SheetMetalComponentDefinition).Thickness
thicknessInventorCm = thicknessParam.Value
Else
' Regular part: only if a UserParameter named "Thickness" exists.
Try
thicknessParam = oPart.ComponentDefinition.Parameters.UserParameters.Item("Thickness")
thicknessInventorCm = thicknessParam.Value
Catch
' Keep fallback 0.15 cm; thicknessParam stays Nothing -> plain text.
End Try
End If
' Display mm = cm * 10; format uses NumberFormat + decimal comma.
Dim displayValue As String = FormatThicknessForDrawing(thicknessInventorCm * 10.0)
If thicknessParam Is Nothing Then
' No model link - static text only (will not update if thickness changes).
Return "x" & displayValue
End If
' ComponentIdentifier: path Inventor uses to resolve the parameter later.
Dim componentId As String = oPart.FullFileName
If String.IsNullOrEmpty(componentId) Then
' Unsaved part - fall back to the view descriptor document name.
componentId = oView.ReferencedDocumentDescriptor.FullDocumentName
End If
' Linked FormattedText XML: Inventor refreshes the number when Thickness changes.
' Precision='3' = up to 3 digits after decimal in the linked display.
Return "x<Parameter Resolved='True' ComponentIdentifier='" & EscapeXmlAttribute(componentId) & _
"' Name='" & EscapeXmlAttribute(thicknessParam.Name) & _
"' Precision='3'>" & displayValue & "</Parameter>"
End Function
Private Function EscapeXmlAttribute(value As String) As String
' FormattedText attributes use single quotes - escape ' inside paths/names.
If String.IsNullOrEmpty(value) Then Return ""
Return value.Replace("'"c, "'")
End Function
Private Function FormatThicknessForDrawing(valueMm As Double) As String
' 1) Format with .NET pattern from Main (CfgThicknessNumberFormat).
' 2) Replace "." with "," for Polish drawing convention.
Dim fmt As String = NumberFormat
If String.IsNullOrEmpty(fmt) Then fmt = "0.###"
Return valueMm.ToString(fmt, Globalization.CultureInfo.InvariantCulture).Replace("."c, ","c)
End Function
End Class