Status Bar Text

The ski tour season in the alps has opened again, and I went on my first tour of the year last weekend, to the Ramoz hut and the Arosa Rothorn:

Ski tour on Arosa Rothorn

Many thanks to Chris for the beautiful pictures!

Here is another idea from Rudolf Honke of acadGraph CADstudio GmbH. He says:

I previously explained how you can use UIAutomation event handlers in Revit.

When playing around a bit further with this, I thought about how to display the events.

Using good old P/Invoke, you can simply display any text in the Revit status bar (http://www.pinvoke.net helps a lot):

  [DllImport( "user32.dll", 
    SetLastError = true, 
    CharSet = CharSet.Auto )]
  static extern int SetWindowText( 
    IntPtr hWnd, 
    string lpString );
 
  [DllImport( "user32.dll", 
    SetLastError = true )]
  static extern IntPtr FindWindowEx( 
    IntPtr hwndParent, 
    IntPtr hwndChildAfter, 
    string lpszClass, 
    string lpszWindow );
 
  public static void SetStatusText( string text )
  {
    IntPtr statusBar = FindWindowEx( 
      m_mainWndFromHandle, IntPtr.Zero, 
      "msctls_statusbar32", "" );
 
    if( statusBar != IntPtr.Zero )
    {
      SetWindowText( statusBar, text );
    }
  }

This is a comfortable way to show the events being fired. Here is an example of resizing the main Revit window:

Status bar displaying UI Automation event

Resizing the main Revit window again:

Status bar displaying UI Automation event

Selecting the Home ribbon tab:

Status bar displaying UI Automation event

Selecting the Insert ribbon tab:

Status bar displaying UI Automation event

Selecting a button on the Annotation ribbon tab:

Status bar displaying UI Automation event

One point to keep in mind is that Revit will overwrite your text as soon as it sees fit, which may be within a few milliseconds, depending on the command you invoked.

Here is another button being selected and the corresponding UI Automation event displayed:

Status bar displaying UI Automation event

In this case, it is immediately overwritten by Revit:

Status bar displaying UI Automation event

Actually, this function could be combined with another function to replace the global variable 'm_mainWndFromHandle':

public static void SetStatusText( string text )
{
  IntPtr mainWindowHandle = IntPtr.Zero;
 
  Process[] processes 
    = Process.GetProcessesByName( "Revit" );
 
  if( 0 < processes.Length )
  {
    mainWindowHandle 
      = processes[0].MainWindowHandle;
 
    IntPtr statusBar = FindWindowEx( 
      mainWindowHandle, IntPtr.Zero, 
      "msctls_statusbar32", "" );
 
    if( statusBar != IntPtr.Zero )
    {
      SetWindowText( statusBar, text );
    }
  }
}

So, this function could be called without filling the global Revit app handle before. Or even shorter:

public static void SetStatusText( string text )
{
  Process[] processes 
    = Process.GetProcessesByName( "Revit" );
 
  if( 0 < processes.Length )
  {
    IntPtr statusBar = FindWindowEx( 
      processes[0].MainWindowHandle, IntPtr.Zero, 
      "msctls_statusbar32", "" );
 
    if( statusBar != IntPtr.Zero )
    {
      SetWindowText( statusBar, text );
    }
  }
}

Think of a situation there more than one instance of Revit is running, RAC and MEP, for example. Using the original code, the wrong window might be addressed.

Jeremy adds: I went ahead and implemented a minimal new external command CmdStatusBar for The Building Coder samples to demonstrate this. I actually make use of the GetCurrentProcess method instead, since I am inside the Revit process, like this:

public static void SetStatusText( 
  IntPtr mainWindow,
  string text )
{
  IntPtr statusBar = FindWindowEx(
    mainWindow, IntPtr.Zero,
    "msctls_statusbar32", "" );
 
  if( statusBar != IntPtr.Zero )
  {
    SetWindowText( statusBar, text );
  }
}
 
public Result Execute(
  ExternalCommandData commandData,
  ref string message,
  ElementSet elements )
{
  IntPtr revitHandle = System.Diagnostics.Process
    .GetCurrentProcess().MainWindowHandle;
 
  SetStatusText( revitHandle, "Kilroy was here." );
 
  return Result.Succeeded;
}

It works fine. Here is version 2011.0.83.0 of The Building Coder samples including the complete source code and Visual Studio solution with the new command.