Update ThisApplication.Caption?

Update ThisApplication.Caption?

SometimesInventorMakesMeAngry
Advocate Advocate
646 Views
6 Replies
Message 1 of 7

Update ThisApplication.Caption?

SometimesInventorMakesMeAngry
Advocate
Advocate

I'd like to include the current document's description in the ThisApplication.Caption. For this, I'm using ApplicationEvents.OnNewEditObject, but I found that Caption doesn't always update visually. When it doesn't update, I can force it to update if I hover over the Caption. Is there a way to update the Caption programmatically? I tried ActiveView.Update(), but it doesn't work (I didn't really expect it to). Below is a code snippet. Any feedback is appreciated.

 

 

        private void OnNewEditObject(object EditObject, 
                                    EventTimingEnum BeforeOrAfter, 
                                    NameValueMap Context, 
                                    out HandlingCodeEnum HandlingCode)
        {
            HandlingCode = HandlingCodeEnum.kEventHandled;
            if (BeforeOrAfter != EventTimingEnum.kBefore ||
                !(EditObject is Document)) return;

            string description =
                new InventorEnhancements.iProperties(EditObject as Document).
                Description.Value.ToString();

            inventorApp.Caption = $"{description}    -";
            inventorApp.ActiveView.Update();

        }

 

 

 Also, if there is a way to get rid of or hide or re-order the persistent "ShortFileName" in the ThisApplication.Caption, that would be awesome. Ideally, the ShortFileName is first and description is second, but haven't found a way to do that. I'm thinking it's not exposed in the API.

0 Likes
647 Views
6 Replies
Replies (6)
Message 2 of 7

WCrihfield
Mentor
Mentor

It looks like your code is likely in C#, but I'm not fully fluent in that so I decided to post a similar, but perhaps more detailed solution using iLogic/vb.net.  When ran on an assembly, any time I in-place edit a component, it instantly updates the 'Caption' to show the 'Description' of the component document I'm in-place editing, followed by the short file name of the main assembly.  Then when I 'Return' (exit out of in-place editing) to the main assembly, the 'Caption' instantly updates to show only the short file name of the main assembly.  Then when I close that main assembly, both event handlers are removed/destroyed, so they don't continue to run in the background, degrading Inventor's performance.  After I added the little check in there to see if the EditObject was the active main assembly document, that would then clear the Caption, that seemed to fix the issue of the left over caption text from the last component I had worked on, seemingly fixing the updating problem.

 

This works best as a 'local' rule, so that it can more reliably identify the main assembly document, but could also be used as an external rule too, but if using as external, it might be better to change the ThisDoc.Document terms to ThisApplication.ActiveDocument instead, then be sure the main assembly is 'active'.

Here's what I've got:

Sub Main
	Dim oAppEvents As ApplicationEvents = ThisApplication.ApplicationEvents
	AddHandler oAppEvents.OnNewEditObject, AddressOf oAppEvents_OnNewEditObject
	AddHandler oAppEvents.OnCloseDocument, AddressOf oAppEvents_OnCloseDocument
End Sub

Public Sub oAppEvents_OnNewEditObject(oEditObj As Object, oTiming As Inventor.EventTimingEnum, oContext As Inventor.NameValueMap, ByRef oHCode As Inventor.HandlingCodeEnum)
	If TypeOf oEditObj Is Inventor.Document Then
		Dim oDoc As Inventor.Document = oEditObj
		If oDoc Is ThisDoc.Document Then
			ThisApplication.Caption = ""
		Else
			Dim oDesc As String = oDoc.PropertySets.Item("Design Tracking Properties").Item("Description").Value
			If Not String.IsNullOrEmpty(oDesc) Then
				ThisApplication.Caption = oDesc
			End If
		End If
	End If
End Sub

Public Sub oAppEvents_OnCloseDocument(oDoc As Inventor._Document, oFullDocName As String, oTiming As Inventor.EventTimingEnum, oContext As Inventor.NameValueMap, ByRef oHCode As Inventor.HandlingCodeEnum)
	If oDoc Is ThisDoc.Document Then 'the 'local' document, or one that was 'active' when the code started
		Dim oAppEvents As ApplicationEvents = ThisApplication.ApplicationEvents
		RemoveHandler oAppEvents.OnNewEditObject, AddressOf oAppEvents_OnNewEditObject
		MsgBox("Removed 'OnNewEditObject' Event handler.",,"")
		RemoveHandler oAppEvents.OnCloseDocument, AddressOf oAppEvents_OnCloseDocument
		MsgBox("Removed 'OnCloseDocument' Event handler.",,"")
	End If
End Sub

 

If this solved your problem, or answered your question, please click ACCEPT SOLUTION.
Or, if this helped you, please click (LIKE or KUDOS) 👍.

If you want and have time, I would appreciate your Vote(s) for My IDEAS 💡or you can Explore My CONTRIBUTIONS

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

0 Likes
Message 3 of 7

SometimesInventorMakesMeAngry
Advocate
Advocate
Hi, thanks for the reply. Your rule looks very similar to my code. Of course I stripped error handling to reduce clutter for posting here, but other than that they're almost the same.

I wonder how this rule is triggered, though? Do you add an event trigger for when the document is opened?

My code works well when activating a new document. Meaning, opening a document in a new View/window. It also works when in-place editing AND the environment changes (meaning if the active document is an assembly, then you in-place edit a part document). However, it does not work when in-place editing and the environment doesn't change (for example, active doc is assembly and you in-place edit an assembly).

Did you try this with your rule? Running the rule from an assy and in-place editing an assy? I tried it and it didn't work with your rule either. That is until I hovered over the caption.
0 Likes
Message 4 of 7

I just manually ran that rule to start it.  But it could be triggered to start on 'After Open Document' event, if the rule and the trigger were set up in that document.  This is likely better suited for use in an Inventor Add-in if you want it to work across multiple (or all) documents while Inventor is running, but I suppose you could set it up under the 'Assemblies' tab of the Event Triggers dialog, for that event too, which will run this rule the first time any assembly is opened.  Then maybe change the OnCloseDocument portion to check if there are any more assemblies in the ThisApplication.Documents collection, and if not, destroy the event handler.  Then if/when you open another assembly, it would start/create it again.  But I don't know how well that scenario would work, or what effect it might have on Inventor's performance.

No, I hadn't tested it with editing sub-assemblies in place, but I checked it out after you mentioned it, and it's acting as you described (have to hover over it to update it).  That behavior is likely something not too difficult to fix for a regular Windows software developer, who deals with various application windows on a regular basis, but it seems just out of my reach at the moment.  I've tried a few other things, as a long shot attempt, but none of them were successful so far.

The following are a few of the odd things I tried in my tests:

ThisApplication.UserInterfaceManager.DoEvents
AppActivate(ThisApplication.Caption)
ThisApplication.RefreshRibbonForComparison

I was hoping to find something similar to the 'Application.RefreshTitleBar' method used in some Office applications, but didn't find anything like that.

 

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 5 of 7

SometimesInventorMakesMeAngry
Advocate
Advocate

I tried inventorApp.ScreenUpdating = true; without success. I am doing this for an add-in, by the way.

I did some research and it looks like OnRender() in System.Windows.UIElement can update the UI, but I'm not sure how to get the Inventor window. Maybe there's a way to do it via other methods in other libraries like the Marshal.GetActiveObject() gets the Inventor application object.

 

Edit: I did some digging and found that using 

 

                System.Windows.Window.GetWindow((System.Windows.DependencyObject)inventorApp.GetInterfaceObject("Inventor.Application")).UpdateLayout();

 

actually works as I initially expected it to work, but there is like a 4 second delay when EditObject is a Document -- this is definitely not ideal and maybe there's a better way.

 

I thought about getting ThisApplication.Top as a coordinate on the screen and simulating a mouse hover over the approximate region that Caption uses before returning the mouse to the original location. But this is clearly a workaround and would rather not use it.

 

Edit: The above code creates a new Inventor process every time that line executes. Definitely not good.

0 Likes
Message 6 of 7

I also tried a couple more things after that last post too.  I tried starting Notepad.exe, switching focus to that application, then switching focus back to the Inventor application, then close the Notepad app,  to see if that would cause the title to update, but it didn't seem to work (unless I just wasn't doing something right).  I created a Sub for this process, and tried putting it after one or both Caption = "" and after Caption = oDef, in the calling Sub.

 

Sub UpdateAppTitle()
	Dim oPID As Integer = Shell("NOTEPAD.EXE", AppWinStyle.NormalFocus)
	AppActivate(oPID)
	AppActivate(ThisApplication.Caption)
	Process.GetProcessById(oPID).CloseMainWindow
End Sub

 

  I also tried capturing the Process.ID of Inventor, to see if I could access the Inventor application from Windows standpoint to explore the options for updating its title.  I was able to get the ProcessID, the MainWindowHandle, and the MainWindowTitle (ReadOnly sadly).  So I thought I should be able to use that MainWindowHandle to somehow 'refresh' the Inventor application's main window title.

Dim oProc As Process = System.Diagnostics.Process.GetCurrentProcess
Dim oMWHandle As IntPtr = oProc.MainWindowHandle
Dim oMWTitle As String = oProc.MainWindowTitle

  I tried something I found here, but it always seemed to just show an error or didn't work, for some reason (you can try it if you want).  What did end up working for me, though still not ideal, was the timed message box (shows a MessabeBox for a limited amount of time), which I tried to set to the absolute minimal amount of time and still keep it effective.  I'm guessing it works just because it moved the focus back and forth a couple of times.  It seems that when you click on the 'Return' button in the Ribbon to return to editing the main assembly, it executes two commands (AssemblyFinishEditCmd & AppReturnPreviousCmd).  I set the timer to 150 milliseconds, and it still seems to work, but you still see the MessageBox flash on the screen twice, but it has been updating the application's title correctly each time.  I did notice though, if the Description in the other document is too long, it simply won't show anything in the title (maybe an empty string though, because the title moves slightly).

I was using this in the calling Sub (OnNewEditObject), right after editing the Caption, to force the update:

 

Call MessageBoxTimeOut(0, "", "", vbInformation, 0, 150)

 

and had this Function below:

 

' see http://www.pinvoke.net/default.aspx/user32/MessageBoxTimeout.html
<DllImport("user32.dll",  setLastError:=True, EntryPoint:="MessageBoxTimeoutW", CharSet:= CharSet.Unicode)> _
Private Shared Function MessageBoxTimeOut( _
	ByVal hWnd As IntPtr, _
	ByVal lpText As String, _
	ByVal lpCaption As String, _
	<MarshalAs(UnmanagedType.U4)> ByVal uType As UInteger, _
	<MarshalAs(UnmanagedType.U2)> ByVal wLanguage As Int16, _
	<MarshalAs(UnmanagedType.U4) > ByVal dwMilliseconds As Int32) As <MarshalAs(UnmanagedType.U4) > UInteger
End Function

 

 And because I'm testing in iLogic, I had to include the following in the 'Header':

 

Imports System.Runtime.InteropServices

 

 

If this solved your problem, or answered your question, please click ACCEPT SOLUTION.
Or, if this helped you, please click (LIKE or KUDOS) 👍.

If you want and have time, I would appreciate your Vote(s) for My IDEAS 💡or you can Explore My CONTRIBUTIONS

Wesley Crihfield

EESignature

(Not an Autodesk Employee)

Message 7 of 7

SometimesInventorMakesMeAngry
Advocate
Advocate

I also tried

 

[DllImport("user32.dll")]
static extern bool SetWindowText(IntPtr hWnd, string text);

 

and

 

IntPtr thisHandle = System.Diagnostics.Process.GetCurrentProcess().Handle;

 

and

 

SetWindowText(thisHandle,"text");

 

But noticed no changes to ThisApplication.Caption.

 


I did notice though, if the Description in the other document is too long, it simply won't show anything in the title (maybe an empty string though, because the title moves slightly).


I have a method that trims the description string to a certain number of characters because I noticed this as well.

 

I appreciate your effort, but I think I'd rather either leave it as is or use OnActivateDocument or OnViewView to update the caption only when a new file is opened instead of including in-place editing as well.

0 Likes