Open Document Settings dialog form at the desired (non-default/first) tab

Open Document Settings dialog form at the desired (non-default/first) tab

Maxim-CADman77
Advisor Advisor
471 Views
8 Replies
Message 1 of 9

Open Document Settings dialog form at the desired (non-default/first) tab

Maxim-CADman77
Advisor
Advisor

I'd like to know whether it possible to open Document Settings dialog form at the desired (non-default/first) tab (let say 'Units')?

 

Code to open Document Settings at the default/first ('Standard') tab is:

 

ThisApplication.CommandManager.ControlDefinitions("AppDocumentSettingsCmd").Execute

 


There is also an advanced relevant sample to open non-default tab (of BOM editor dialog) by @MjDeck.

 

I believe it should be adaptable for the Document Settings form, but I failed to.

 

Here is my attempt (seems like my version of condition used for search window by title, line 66 doesn't work):

 

Option Explicit On
AddReference "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\WPF\UIAutomationClient.dll"
AddReference "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\WPF\UIAutomationTypes.dll"

Imports System.Windows.Forms
Imports System.Runtime.InteropServices
Imports System.Windows.Automation

Sub Main()
' OpenBOMEditor("Structured")
'OpenBOMEditor("Parts Only")

OpenBOMEditor("Units") ' !!
End Sub

Private Delegate Function EnumWindowsProc(ByVal hWnd As IntPtr, ByVal lParam As IntPtr) As Boolean

<DllImport("user32.dll", SetLastError :=True, CharSet :=CharSet.Auto) > _
Private Shared Function SetForegroundWindow(hWnd As IntPtr) As Integer
End Function
<DllImport("user32.dll", SetLastError :=True) > _
Private Shared Function SetActiveWindow(ByVal hWnd As IntPtr) As IntPtr
End Function

<DllImport("user32.dll", SetLastError :=True, CharSet :=CharSet.Auto) > _
Private Shared Function EnumWindows(
	ByVal lpEnumFunc As EnumWindowsProc, _
	ByVal lParam As IntPtr) As Boolean
End Function
<DllImport("user32.dll", CharSet :=CharSet.Auto) > _
Private Shared Function EnumChildWindows(ByVal hWndParent As System.IntPtr, ByVal lpEnumFunc As EnumWindowsProc, ByVal lParam As Integer) As Boolean
End Function
<DllImport("user32.dll", CharSet :=CharSet.Auto) > _
Private Shared Function GetWindowText(ByVal hwnd As Integer, ByVal lpString As System.Text.StringBuilder, ByVal cch As Integer) As Integer
End Function
<DllImport("user32.dll", SetLastError :=True, CharSet :=CharSet.Auto) > _
Private Shared Function GetWindowTextLength(ByVal hwnd As IntPtr) As Integer
End Function

' see https://stackoverflow.com/questions/1363167/how-can-i-get-the-child-windows-of-a-window-given-its-hwnd

Private _tabNameWanted As String

Sub OpenBOMEditor(tabName As String, Optional sleepTime As Integer = 0)
	_tabNameWanted = tabName

	Dim oCommandMgr As CommandManager
	oCommandMgr = ThisApplication.CommandManager
	' Dim oControlDef = oCommandMgr.ControlDefinitions.Item("AssemblyBillOfMaterialsCmd")
	Dim oControlDef = oCommandMgr.ControlDefinitions.Item("AppDocumentSettingsCmd") ' !!
	Call oControlDef.Execute2(False)
	ThisApplication.UserInterfaceManager.DoEvents()
	ThisApplication.UserInterfaceManager.DoEvents()

	System.Threading.Thread.Sleep(sleepTime)
	'EnumChildWindows(ThisApplication.MainFrameHWND, AddressOf FindBOMEditor, 0)
	EnumWindows(AddressOf FindBOMEditor, 0)

	ThisApplication.UserInterfaceManager.DoEvents()
End Sub

Function FindBOMEditor(hWnd As IntPtr, lParam As IntPtr) As Boolean
	Dim title = GetText(hWnd)
	' If title IsNot Nothing AndAlso title.StartsWith("Bill of Materials") Then
logger.info(11)
	If title IsNot Nothing AndAlso title.EndsWith(" Document Settings") Then ' ??
logger.info(22)
		'Logger.Debug("Bill of Materials window: {0}", hWnd)
		EnumChildWindows(hWnd, AddressOf FindPane1, 0)
		Return False ' we're done
	End If

	Return True ' keep enumerating the child windows.
End Function

Function FindPane1(hWnd As IntPtr, lParam As IntPtr) As Boolean
	Dim element = AutomationElement.FromHandle(hWnd)
	If element.Current.AutomationId = "panel1" Then
		'Logger.Debug("found panel1")
		SetActiveWindow(hWnd)
		Dim tabControl = element.FindFirst(TreeScope.Descendants, New PropertyCondition(AutomationElement.AutomationIdProperty, "tabControl1"))
		If tabControl IsNot Nothing Then
			'Logger.Debug("Found tab control")
			tabControl.SetFocus()

			Dim tabPage = tabControl.FindFirst(TreeScope.Descendants, New PropertyCondition(AutomationElement.NameProperty, _tabNameWanted))
			If tabPage IsNot Nothing Then
				'Logger.Debug("Found tab page")
				Dim tabPageSelector As SelectionItemPattern = tabPage.GetCurrentPattern(SelectionItemPattern.Pattern)
				tabPageSelector.Select()
			End If
		End If

		Return False ' we're done
	End If
	Return True ' contine to next window
End Function

' https://www.pinvoke.net/default.aspx/user32.getwindowtext
Public Function GetText(ByVal hWnd As IntPtr) As String
	Dim length As Integer
	If hWnd.ToInt32 = 0 Then
		Return Nothing
	End If
	length = GetWindowTextLength(hWnd)
	If length = 0 Then
		Return Nothing
	End If
	Dim sb As New System.Text.StringBuilder("", length)

	GetWindowText(hWnd, sb, sb.Capacity + 1)
	Return sb.ToString()
End Function

 

 What I'm missing?

Please vote for Inventor-Idea Text Search within Option Names

0 Likes
Accepted solutions (2)
472 Views
8 Replies
Replies (8)
Message 2 of 9

Frederick_Law
Mentor
Mentor

Not sure how to code it.

Open dialog, activate "Unit" tab.

It could be in Windows Form API.

0 Likes
Message 3 of 9

Curtis_Waguespack
Consultant
Consultant
Accepted solution

Hi @Maxim-CADman77 

 

Here's an example of how to do this.

 

I hope this helps.
Best of luck to you in all of your Inventor pursuits,
Curtis
http://inventortrenches.blogspot.com

 

Open to Units tab:

 

 

Imports System.Windows.Forms
ThisApplication.CommandManager.ControlDefinitions("AppDocumentSettingsCmd").Execute2(False)
'opens to Units tab ( send "Tab" key 5 times and "right arrow" key 1 time)
SendKeys.SendWait("{TAB 5} {RIGHT 1}")

 

 

Open to Bill Of Materials tab:

 

 

Imports System.Windows.Forms
ThisApplication.CommandManager.ControlDefinitions("AppDocumentSettingsCmd").Execute2(False)
SendKeys.SendWait("{TAB 5} {RIGHT 4} ")

 

EESignature

Message 4 of 9

Maxim-CADman77
Advisor
Advisor

@Curtis_Waguespack 
This works but if possible I'd like not to rely on Sendkeys.

Please vote for Inventor-Idea Text Search within Option Names

0 Likes
Message 5 of 9

Maxim-CADman77
Advisor
Advisor

Seems that .EndsWith("Settings")  works (unlike .EndsWith(" Document Settings"))
But then what should I use instead of "panel1" ?

Please vote for Inventor-Idea Text Search within Option Names

0 Likes
Message 6 of 9

Curtis_Waguespack
Consultant
Consultant

@Maxim-CADman77 

 

I took a few minutes to look at this. I don't think the title of this dialog is returning what we expect. See the logger outputs of this version for more info. I'm not sure what window/title it is in the list, but maybe this will get you closer.

 

I hope this helps.
Best of luck to you in all of your Inventor pursuits,
Curtis
http://inventortrenches.blogspot.com

 

Option Explicit On
AddReference "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\WPF\UIAutomationClient.dll"
AddReference "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\WPF\UIAutomationTypes.dll"
Imports System.Windows.Forms
Imports System.Runtime.InteropServices
Imports System.Windows.Automation


Sub Main

	OpenTargetDialog("Units")
End Sub

Private Delegate Function EnumWindowsProc(ByVal hWnd As IntPtr, ByVal lParam As IntPtr) As Boolean

<DllImport("user32.dll", SetLastError :=True, CharSet :=CharSet.Auto) > _
Private Shared Function SetForegroundWindow(hWnd As IntPtr) As Integer
End Function
<DllImport("user32.dll", SetLastError :=True) > _
Private Shared Function SetActiveWindow(ByVal hWnd As IntPtr) As IntPtr
End Function

<DllImport("user32.dll", SetLastError :=True, CharSet :=CharSet.Auto) > _
Private Shared Function EnumWindows(
	ByVal lpEnumFunc As EnumWindowsProc, _
	ByVal lParam As IntPtr) As Boolean
End Function
<DllImport("user32.dll", CharSet :=CharSet.Auto) > _
Private Shared Function EnumChildWindows(ByVal hWndParent As System.IntPtr, ByVal lpEnumFunc As EnumWindowsProc, ByVal lParam As Integer) As Boolean
End Function
<DllImport("user32.dll", CharSet :=CharSet.Auto) > _
Private Shared Function GetWindowText(ByVal hwnd As Integer, ByVal lpString As System.Text.StringBuilder, ByVal cch As Integer) As Integer
End Function
<DllImport("user32.dll", SetLastError :=True, CharSet :=CharSet.Auto) > _
Private Shared Function GetWindowTextLength(ByVal hwnd As IntPtr) As Integer
End Function

' see https://stackoverflow.com/questions/1363167/how-can-i-get-the-child-windows-of-a-window-given-its-hwnd

Private _tabNameWanted As String

Sub OpenTargetDialog(tabName As String, Optional sleepTime As Integer = 0)
	_tabNameWanted = tabName

	Dim oCommandMgr As CommandManager
	oCommandMgr = ThisApplication.CommandManager
	Dim oControlDef = oCommandMgr.ControlDefinitions.Item("AppDocumentSettingsCmd")
	Call oControlDef.Execute2(False)
	ThisApplication.UserInterfaceManager.DoEvents()


	System.Threading.Thread.Sleep(sleepTime)
	EnumChildWindows(ThisApplication.MainFrameHWND, AddressOf FindTargetWindow, 0)
	'EnumWindows(AddressOf FindTargetWindow, 0)

	ThisApplication.UserInterfaceManager.DoEvents()
End Sub

Function FindTargetWindow(hWnd As IntPtr, lParam As IntPtr) As Boolean
	Dim title As String = GetText(hWnd)

	If title IsNot Nothing Then
		Logger.Debug( title)
		If title.Contains("Document Settings") Then
			EnumChildWindows(hWnd, AddressOf FindPane1, 0)
			Return False ' we're done
		End If
	End If

	Return True ' keep enumerating the child windows.
End Function

Function FindPane1(hWnd As IntPtr, lParam As IntPtr) As Boolean
	Dim element = AutomationElement.FromHandle(hWnd)
	If element.Current.AutomationId = "panel1" Then
		'Logger.Debug("found panel1")
		SetActiveWindow(hWnd)
		Dim tabControl = element.FindFirst(TreeScope.Descendants, New PropertyCondition(AutomationElement.AutomationIdProperty, "tabControl1"))
		If tabControl IsNot Nothing Then
			'Logger.Debug("Found tab control")
			tabControl.SetFocus()

			Dim tabPage = tabControl.FindFirst(TreeScope.Descendants, New PropertyCondition(AutomationElement.NameProperty, _tabNameWanted))
			If tabPage IsNot Nothing Then
				'Logger.Debug("Found tab page")
				Dim tabPageSelector As SelectionItemPattern = tabPage.GetCurrentPattern(SelectionItemPattern.Pattern)
				tabPageSelector.Select()
			End If
		End If

		Return False ' we're done
	End If
	Return True ' contine to next window
End Function

' https://www.pinvoke.net/default.aspx/user32.getwindowtext
Public Function GetText(ByVal hWnd As IntPtr) As String


	Dim length As Integer
	If hWnd.ToInt32 = 0 Then
		Return Nothing
	End If
	length = GetWindowTextLength(hWnd)

	If length = 0 Then
		Return Nothing
	End If
	Dim sb As New System.Text.StringBuilder("", length)

	GetWindowText(hWnd, sb, sb.Capacity + 1)
	'Logger.Info("sb " & sb.ToString())
	Return sb.ToString()
End Function

 

EESignature

0 Likes
Message 7 of 9

Maxim-CADman77
Advisor
Advisor

I see what you mean.
But then I don't understand why it works for "AssemblyBillOfMaterialsCmd"
For me logger doesn't list any title starting with "Bill of Materials" either...

Please vote for Inventor-Idea Text Search within Option Names

0 Likes
Message 8 of 9

Waguespack_Curtis
Contributor
Contributor

Hi @Maxim-CADman77 

 

I took another look at the BOM version, and I do see it get that window, but what I did just notice is that it gets it while the BOM window is still open. Whereas the Doc Settings version I posted, was only writing those titles out after the Doc Settings dialog is closed. So I suspect they are just being handled differently, but unfortunately, I don't understand it well enough to say much more.

 

Waguespack_Curtis_1-1694194550654.png

 

 

Waguespack_Curtis_0-1694194322838.png

 

0 Likes
Message 9 of 9

Zach.Stauffer
Advocate
Advocate
Accepted solution

The issue might be the difference between the Bill of Materials window and the Document Settings window.

 

The Bill of Materials window is a non-modal window, which means you can still use the rest of the program while it is open. The Document Settings window is modal, which means all code execution stops while that window is open. Therefore the search for the Document Settings window only starts when the window is closed, and then of course it won't find the window because it has been closed.

0 Likes