Get Vault check in window

Get Vault check in window

gert-leonvanlier
Collaborator Collaborator
1,321 Views
4 Replies
Message 1 of 5

Get Vault check in window

gert-leonvanlier
Collaborator
Collaborator

Since the Inventor API nor the Vault API are able to let me get control over the check in window for Vault from within Inventor, I came up with a different approach, but I am not sure how to implement this solution.

My idea is to get connected to the Vault check in window in Inventor as soon as the window appears and then use the sendkeys method to paste a comment into the comment field of the check in window. After that the user can click OK the check in the file.

Although I found out that ApplicationEvents.OnActivateView and UserInputEvents.OnActivateCommand are fired when clicking the check in button, these events happen before the check in window appears. I think this means I can't use these events to help me.

 

Is there a way to look for when the check in window appears?

0 Likes
Accepted solutions (1)
1,322 Views
4 Replies
Replies (4)
Message 2 of 5

matt_jlt
Collaborator
Collaborator
0 Likes
Message 3 of 5

matt_jlt
Collaborator
Collaborator

I went and opened my old project for you, i was testing some stuff out so there might be a bit of unused code / commented out lines. But this is 99% done for you...hopefully 😉

 

This code will get the check in window and click the button when it pops up. Given that you only want to pre-fill out the comments, you will need to use something like Spy++ to get the text area id and define the correct "user32.dll API Function" for the text area object. and remove the section where i have it clicking the button.

 

When / if you get it working. please post the final code here for everyone, as i know it has been asked a bunch of times in the forums. 

 

Notes, this is for an add-in / vb.net code

 

Usage Instructions

The following code needs to be copied into the module StandardAddInServer.vb - assuming you are using the Inventor / visual studio template

 

Imports - add this at the very top of the module

Imports System.Windows.Automation ' this is for the check in window handler
Imports System.Runtime.InteropServices ' Can't remember if this is required
Imports Microsoft.Win32

 

This will be copied into the standardaddinserver class, just below the first line of the class where it says Implements Inventor.applicationaddinserver

' ** GET WINDOW CODE (USE SPY++ DEBUG TOOL WITHIN VISUAL STUDIO TO LOCATE DIALOG INFO)
'This Is the intercepting form windows api code
Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
Private Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" (ByVal hWndParent As Integer, ByVal hWndChildAfter As Integer, ByVal lpszClass As String, ByVal lpszWindow As String) As Integer
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
Private Declare Function GetDlgItem Lib "user32" (ByVal hDlg As IntPtr, nIDDlgItem As Integer) As IntPtr

Private Const BM_CLICK As Integer = &HF5&
Private Const BM_SETCHECK As Integer = &HF1&
Private Const WM_SETFOCUS As Integer = &H7

 

This needs to be added into the "Activate" sub

' ** GET WINDOW CODE
System.Windows.Automation.Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent, AutomationElement.RootElement, TreeScope.Subtree, AddressOf OnWindowOpened)

This sub can be added anywhere in the class, I just added it right below the "activate" sub

        'This Is what captures the name of the check in window And automatically accepts
        'comments are pre-filled from vault check-out menu
        Private Sub OnWindowOpened(sender As Object, oAutomationEventArgs As AutomationEventArgs)
            ' Check if is currently enabled
            'If My.Settings.bAutoCloseCheckInForm = False Then Return

            Try
                Dim element As AutomationElement = sender
                If element Is Nothing Then Return
                ThisApplication.StatusBarText = element.Current.Name
                If element.Current.Name.Count < 11 Then Return ' Needs to have enough characters to check length
                If Left(element.Current.Name, 10) <> "Check In '" Then Return
                ' wait for form to load (closing too early causes problems / skipping)
                sharedFunctions.IsInventorAvailable(ThisApplication, 2)
                Dim h1 = element.Current.NativeWindowHandle
                ThisApplication.StatusBarText = h1
                'Dim H2 = FindWindowEx(h1, IntPtr.Zero, "OK", "")
                Dim h2 = GetDlgItem(h1, "00000001") ' OK button is ID "00000001", Cancel button is "00000002"

                If h2 <> 0 Then
                    'SendMessage(h2, WM_SETFOCUS, IntPtr.Zero, IntPtr.Zero) 'trying without set focus
                    SendMessage(h2, BM_CLICK, IntPtr.Zero, IntPtr.Zero)
                    'SendMessage(H2, BM_SETCHECK, False, 0)
                    ' this removes the event handler if it was a once only operation
                    'System.Windows.Automation.Automation.RemoveAutomationEventHandler(WindowPattern.WindowOpenedEvent, AutomationElement.RootElement, AddressOf OnWindowOpened)
                Else
                    MessageBox.Show("Didnt get it")
                End If
            Catch
            End Try
        End Sub

 

Message 4 of 5

matt_jlt
Collaborator
Collaborator

This is the function, it was just on another module

 

    Function IsInventorAvailable(ByRef oInvApp As Inventor.Application, Optional ByVal dTimeOutInSeconds As Double = 0) As Boolean
        ' Don't use this one, can get stuck in endless loop
        If dTimeOutInSeconds = 0 Then   'Wait forever
            While Not oInvApp.Ready
                System.Threading.Thread.Sleep(100)
                System.Windows.Forms.Application.DoEvents()
            End While
        Else
            Dim dStart As Double = Microsoft.VisualBasic.DateAndTime.Timer
            While Not oInvApp.Ready And
                (Microsoft.VisualBasic.DateAndTime.Timer - dStart) < dTimeOutInSeconds

                System.Threading.Thread.Sleep(100)
                ThisApplication.UserInterfaceManager.DoEvents() 'Use this for inventor
                'System.Windows.Forms.Application.DoEvents()
            End While
        End If

        IsInventorAvailable = oInvApp.Ready
    End Function
Message 5 of 5

gert-leonvanlier
Collaborator
Collaborator
Accepted solution

Thank you very much! You gave me the solution I was looking for with the lack of an API.

 

This is my code. I hope someone else can benefit from it.

 

The following has to reside in StandardAddInServer.cs under the Activate method:

//WindowEvents
  System.Windows.Automation.Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent, AutomationElement.RootElement, TreeScope.Subtree, OnWindowOpened);

 

Outside the Activate method:

private void OnWindowOpened(object Sender, AutomationEventArgs automationEventArgs)
{
	try
	{
		AutomationElement element = (AutomationElement)Sender;
		
		if (element == null)
		{
			return;
		}

		Globals.invApp.StatusBarText = element.Current.Name;

		if (element.Current.Name.Length < 10) //needs enough character to check length
		{
			return;
		}

		string checkinWindowName = element.Current.Name;

		if (checkinWindowName.Substring(0, 9) == "Check In ")
		{
			//wait for form to load (closing too early causes problems / skipping)
			VaultCheckin vaultCheckin = new VaultCheckin();
			vaultCheckin.SetComment(checkinWindowName);
		}
	}
	catch
	{
		//something to do when try fails
	}
}

 

I created a separate class to set the comment field named VaultCheckin.cs:

using System;
using Inventor;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace InventorAddIn
{
    public class VaultCheckin
    {
        // Get a handle to an application window.
        [DllImport("USER32.DLL", CharSet = CharSet.Unicode)]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        // Activate an application window.
        [DllImport("USER32.DLL")]
        public static extern bool SetForegroundWindow(IntPtr hWnd);

        public void SetComment(string CheckinWindowName)
        {
            IntPtr checkinWindowHandle = FindWindow(null, CheckinWindowName);

            if (checkinWindowHandle == IntPtr.Zero)
            {
                return;
            }

            SetForegroundWindow(checkinWindowHandle);

            var comment = "Some comment";

            SendKeys.SendWait(comment);
        }
    }
}

 

 

0 Likes