IDW:(PL) Add-In-Funktin von Drittanbieter ausfĂĽhren und auf Place-Funktion reagieren? / Inventor VBA
mb-ing 01. Apr. 2020, 07:33

Hallo zusammen,

wir arbeiten zukünftig mit Inventor 2020 in Verbindung mit einem PDM-System.
Dieses PDM-System hat im Inventor einen eigenen Reiter sowie einen Knopf (Funktion) zum Platzieren der Stückliste aus dem PDM.
Diese Stückliste sieht 1:1 aus wie eine Inventor-Stückliste, aber bekommt alles aus dem PDM und nichts von der dargestellten BG vererbt.
Leider "endet" die Funktion "Stückliste aus PDM einfügen" damit, dass man mit dem Mauszeiger die X-Y-Position der Stückliste klicken muss, so dass diese auf der Zeichnung platziert werden kann.

Ich kann die geschilderte Funktion mittels Command-Manager ausführen lassen. (Siehe Code-Ausschnitt unten)
Jedoch habe ich das Problem, dass ich dann nicht automatisch eine X-Y-Position in VBA angeben kann, sondern immer eine Benutzer-Interaktion stattfinden muss.

Wie kann ich diese "Platzier-Funktion" mittels Maus abfangen oder ähnliches, so dass keine Benutzer-Interaktion nötig ist?

Public Sub insertBOMonIDW ()

    . . . . .
    Dim oCommandMgr As CommandManager
    Set oCommandMgr = ThisApplication.CommandManager
    Dim oControlDef As ControlDefinition
    Set oControlDef = oCommandMgr.ControlDefinitions.Item("Stückliste aus PDM einfügen")
    Call oControlDef.Execute
    . . . . .

End Sub

Vielen Dank im Voraus für Eure Antworten.

Danke und Grüße
MB-Ing.

mb-ing 02. Apr. 2020, 07:42

Hallo zusammen,

kann man im Inventor einen Klick mit der linken Maustaste simulieren?

Das sieht gut aus:
Public Declare PtrSafe Function SetCursorPos Lib "user32" (ByVal x As Long, ByVal y As Long) As LongPtr
Public Declare PtrSafe Sub mouse_event Lib "user32" (ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As Long)
Public Const MOUSEEVENTF_LEFTDOWN = &H2
Public Const MOUSEEVENTF_LEFTUP = &H4
Public Const MOUSEEVENTF_RIGHTDOWN As Long = &H8
Public Const MOUSEEVENTF_RIGHTUP As Long = &H10
Private Sub SingleClick()
    SetCursorPos 800, 600 'x and y position
    mouse_event MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
    mouse_event MOUSEEVENTF_LEFTUP, 0, 0, 0, 0
End Sub

Oder ist das richtiger Murks? 

Wie kann man in VBA warten bis eine andere Funktion fertig ist?
Kann man mit ThisApplication.ApplicationAddIns….. abfragen, ob das Add-In schon fertig ist? 

Danke und Grüße
MB-Ing.

mb-ing 02. Apr. 2020, 07:42

Hallo zusammen,

kann man im Inventor einen Klick mit der linken Maustaste simulieren?

Das sieht gut aus:
Public Declare PtrSafe Function SetCursorPos Lib "user32" (ByVal x As Long, ByVal y As Long) As LongPtr
Public Declare PtrSafe Sub mouse_event Lib "user32" (ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As Long)
Public Const MOUSEEVENTF_LEFTDOWN = &H2
Public Const MOUSEEVENTF_LEFTUP = &H4
Public Const MOUSEEVENTF_RIGHTDOWN As Long = &H8
Public Const MOUSEEVENTF_RIGHTUP As Long = &H10
Private Sub SingleClick()
    SetCursorPos 800, 600 'x and y position
    mouse_event MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
    mouse_event MOUSEEVENTF_LEFTUP, 0, 0, 0, 0
End Sub

Oder ist das richtiger Murks? 

Wie kann man in VBA warten bis eine andere Funktion fertig ist?
Kann man mit ThisApplication.ApplicationAddIns….. abfragen, ob das Add-In schon fertig ist? 

Danke und Grüße
MB-Ing.

mb-ing 02. Apr. 2020, 07:42

Hallo zusammen,

kann man im Inventor einen Klick mit der linken Maustaste simulieren?

Das sieht gut aus:
Public Declare PtrSafe Function SetCursorPos Lib "user32" (ByVal x As Long, ByVal y As Long) As LongPtr
Public Declare PtrSafe Sub mouse_event Lib "user32" (ByVal dwFlags As Long, ByVal dx As Long, ByVal dy As Long, ByVal cButtons As Long, ByVal dwExtraInfo As Long)
Public Const MOUSEEVENTF_LEFTDOWN = &H2
Public Const MOUSEEVENTF_LEFTUP = &H4
Public Const MOUSEEVENTF_RIGHTDOWN As Long = &H8
Public Const MOUSEEVENTF_RIGHTUP As Long = &H10
Private Sub SingleClick()
    SetCursorPos 800, 600 'x and y position
    mouse_event MOUSEEVENTF_LEFTDOWN, 0, 0, 0, 0
    mouse_event MOUSEEVENTF_LEFTUP, 0, 0, 0, 0
End Sub

Oder ist das richtiger Murks? 

Wie kann man in VBA warten bis eine andere Funktion fertig ist?
Kann man mit ThisApplication.ApplicationAddIns….. abfragen, ob das Add-In schon fertig ist? 

Danke und Grüße
MB-Ing.

mb-ing 02. Apr. 2020, 08:57

Hallo zusammen,

sorry für den "Doppel-Post" 

Ist der folgende Code-Ausschnitt legitim, um zu prüfen, ob eine Stückliste existiert? 

    Dim partListExists As Boolean
    partListExists = True
    Dim i As Integer
    i = 1
    Do While doc.activeSheet.PartsLists.Count = 0
        If i >= 50 Then
            partListExists = False
            Set oControlDef = oCommandMgr.ControlDefinitions.Item("AppContextual_CancelCmd")
            Call oControlDef.Execute
            Exit Do
        End If
        DoEvents
        i = i + 1
    Loop
    If partListExists Then

Danke und Grüße
MB-Ing.

KraBBy 02. Apr. 2020, 09:00

Zitat:
Original erstellt von mb-ing:
Wie kann man in VBA warten bis eine andere Funktion fertig ist?

Du kannst die ControlDefinition.Execute2 Method ausprobieren. Auszug aus der Hilfe:

Zitat:

Syntax
ControlDefinition.Execute2( Synchronous As Boolean )
Parameters
Synchronous Input Boolean that specifies whether to execute the control definition synchronously ('Send Message') or asynchronously ('Post Message').

KraBBy 02. Apr. 2020, 09:20

Zu dem Thema mit der (Klick)Position könnte man mit der CommandManager.PostPrivateEvent Method etwas rumspielen. Ich benutze das, um den Eingabedialog eines Speicherpfades o.ä. abzufangen. In der Hilfe liest es sich nicht unbedingt so, als ob das auch für einen Mauklick gedacht ist/funktioniert, aber versuchen kann man es ja trotzdem.

Das mit dem Mausklick per WinAPI finde ich nicht ganz falsch. Ich meine Klick ist Klick. Ich stelle es mir nur nicht ganz einfach vor, die richtigen Koordinaten zu finden  (ich gehe davon aus, dass die API Koordinaten bzgl. der "Darstellungsfläche" sprich Monitor(e) nimmt).
Eine mögliche Brotkrume: Camera.ModelToViewSpace Method

edit: kurz mit Camera.ModelToViewSpace rum probiert (im 3d-Modell, nicht in einer idw). -> liefert Koordinaten innerhalb des 'aktive View'.
Zu Koordinaten im 'Screen Space' kommt man dann über .GetWindowExtents.

Code:
Dim oView As View
    Set oView = ThisApplication.ActiveView
    Dim Top As Long, Left As Long, Height As Long, Width As Long
    Call oView.GetWindowExtents(Top, Left, Height, Width)

Du musst also den gewünschten Punkt im KS der Zeichnung kennen. ModelToViewSpace sollte dazu die Koordinaten im View liefern. Wenn man dann dazu noch Top bzw. Left von GetWindowExtents dazu addiert, sollten das die 'Screen'Koordinaten für den Mausklick sein.

mb-ing 02. Apr. 2020, 11:11

@KraBBy:

Vielen Dank für Deine Antwort.

Eigentlich muss ich nur irgendwo in der IDW auf die Zeichnungsfläche klicken. 
Die Stückliste schiebe ich dann mittels VBA an die richtige Stelle...

Die anderen Anregungen von Dir muss ich mal ausprobieren.

Danke und Grüße
MB-Ing.

Frank_Schalla 02. Apr. 2020, 16:12

finde einen Punkt der dir gefällt 
Dim oTG As TransientGeometry
        oTG = ThisApplication.TransientGeometry
       
     
        oSketchedSymbol =  oTG.CreatePoint2d(15, 5), 0, 1)

mb-ing 15. Apr. 2020, 08:10

@KraBBy & Frank_Schalla:

Vielen Dank für Eure Antworten, das hat mir geholfen.

Danke und Grüße
MB-Ing.

mb-ing 15. Apr. 2020, 08:21

Zitat:
Original erstellt von KraBBy:
Zu dem Thema mit der (Klick)Position könnte man mit der CommandManager.PostPrivateEvent Method etwas rumspielen. Ich benutze das, um den Eingabedialog eines Speicherpfades o.ä. abzufangen. In der Hilfe liest es sich nicht unbedingt so, als ob das auch für einen Mauklick gedacht ist/funktioniert, aber versuchen kann man es ja trotzdem.


@Krabby:
Habe mir dazu die Hilfe durchgelesen und die Funktion greift nur aufs Clipboard zu, oder?
Wie kann ich da die Brücke zum Mausklick schlagen? ^^

Danke und Grüße
MB-Ing.

KraBBy 15. Apr. 2020, 13:25

Der Gedanke war, vor dem execute des "Stücklisten einfügen", die Position in das interne clipboard zu legen (über das post private event). Damit die Hoffnung, dass der Klick erst gar nicht nötig ist.

Wie schon geschrieben, verspreche ich mir davon nicht viel. Aber wer weiß... 🙄

mb-ing 15. Apr. 2020, 16:50

Zitat:
Original erstellt von KraBBy :
Der Gedanke war, vor dem execute des "Stücklisten einfügen", die Position in das interne clipboard zu legen (über das post private event). Damit die Hoffnung, dass der Klick erst gar nicht nötig ist.

Wie schon geschrieben, verspreche ich mir davon nicht viel. Aber wer weiß... 🙄


@KraBBy:
Die Idee ist echt genial.

Wie bekomme ich einen Point2D in den Befehl?

http://help.autodesk.com/view/INVNTOR/2020/ENU/?guid=GUID-E255F1E5-BF3F-4F8E-AF32-70BEA677E11C
https://adndevblog.typepad.com/manufacturing/2013/01/provide-command-parameters-using-postprivateevent.html

Die beiden Quellen führen nicht zum Erfolg.

Aber der Befehl ist trotzdem interessant, deswegen muss ich mich mal weiter damit beschäftigen.

Danke und Grüße
MB-Ing.

RolandD 15. Apr. 2020, 17:57

Zitat:
Original erstellt von mb-ing:
..Wie bekomme ich einen Point2D in den Befehl?

Du könntest den Punkt rechts oben vom Schriftfeld nehmen:

Code:
Dim oSheet As Sheet
        oSheet = oDoc.ActiveSheet

        Dim oTitleBlockPoint As Point2d
        If Not oSheet.TitleBlock Is Nothing Then 'TitleBlock existiert. SL rechts oben ausrichten
            oTitleBlockPoint = oSheet.TitleBlock.RangeBox.MaxPoint
        Else                'kein TitleBlock vorhanden.
            MsgBox("kein Schriftfeld zum Ausrichten der SL vorhanden")
            Exit Sub
        End If 'oSheet.TitleBlock Is Nothing


Oder eben feste Koordinaten nutzen:

Code:
Dim Pkt As Point2d = invApp.TransientGeometry.CreatePoint2d(0, 0)

mb-ing 16. Apr. 2020, 07:10

Zitat:
Original erstellt von RolandD:

Du könntest den Punkt rechts oben vom Schriftfeld nehmen:

Code:
Dim oSheet As Sheet
        oSheet = oDoc.ActiveSheet

        Dim oTitleBlockPoint As Point2d
        If Not oSheet.TitleBlock Is Nothing Then 'TitleBlock existiert. SL rechts oben ausrichten
            oTitleBlockPoint = oSheet.TitleBlock.RangeBox.MaxPoint
        Else                'kein TitleBlock vorhanden.
            MsgBox("kein Schriftfeld zum Ausrichten der SL vorhanden")
            Exit Sub
        End If 'oSheet.TitleBlock Is Nothing


Oder eben feste Koordinaten nutzen:

Code:
Dim Pkt As Point2d = invApp.TransientGeometry.CreatePoint2d(0, 0)



@Roland:
Danke für Deine Antwort.

Wie kann ich den oSheet.TitleBlock.RangeBox.MaxPoint in Pixel umrechnen, so dass ich meine Klick-Position erhalte?

Hierzu habe ich folgendes gefunden, aber das berücksichtigt nicht zwei Bildschirme...
https://forums.autodesk.com/t5/inventor-customization/how-to-get-the-pixel-coordinates-of-the-sketch-point-on-the/td-p/8119360

Der post private event klappt leider nicht, da ich hier keine Koordinaten einlesen kann 

Ich will es nun so machen, dass ich die ZN einpasse dann vom Schriftkopf eine Position auslesen möchte und diese "anklicke".
Anschließend wird die Stüli einfach dort positioniert und dann wieder zu der alten Position verschoben.
Aber leider brauche ich hierzu immer die "Pixel-Koordinaten.
Ich muss berücksichtigen, dass das Makro ausgeführt wird, wenn zwei Bildschirme vorhanden sind, Inventor nicht maximiert ist, etc.
Deswegen ist es vermutlich sinnvoll die ZN vorab einzupassen und eine Position am Schriftkopf auszulesen.

Danke und Grüße
MB-Ing.

KraBBy 16. Apr. 2020, 09:24

Das mit den Pixel Koordinaten habe ich oben schon angesprochen.

Vorher so zu zoomen, dass alles sichtbar ist, ist ein guter Plan. Dann sollte es auch keinen Unterschied machen, ob das IV Fenster maximiert ist oder nicht. Mehrere Monitore sollte sich auch ergeben, da es für den klick 'eine Fläche' ist (1 KS das sich über beide Monitore erstreckt)

mb-ing 16. Apr. 2020, 10:10

Hallo zusammen,

perfekt, jetzt passt es. 
Top und Left addieren dann klappt es auch mit dem Nachbarn 

Vielen herzlichen Dank an alle!

Danke und Grüße
MB-Ing.

RolandD 16. Apr. 2020, 10:10

Wie wäre das:
1. an beliebige Stelle (z.B. 0,0) platzieren lassen
2. mit VBA auf die gewünschte Position verschieben

mb-ing 16. Apr. 2020, 10:13

Zitat:
Original erstellt von RolandD:
Wie wäre das:
1. an beliebige Stelle (z.B. 0,0) platzieren lassen
2. mit VBA auf die gewünschte Position verschieben


Hallo Roland,

danke für Deine Antwort.
Leider geht das nicht, da das Add-In des Drittanbieters explizit einen Klick mit der linken Maustaste auf eine Position in der Zeichnung erwartet.
Bevor das nicht erfolgt ist, wird keine Stückliste aus dem PLM auf der ZN platziert...

Danke und Grüße
MB-Ing.