Many of the JW freeware plug-ins use the window concept of a tree view to the left (with tasks arranged into containers) and a panel to the right that is specific to the task. This page contains code for AutoHotkey for Windows on how to fully automate a task in such a plug-in.

AutoHotkey is a script-based Windows freeware macro application that's robust and extremely powerful, although it has some learning curve to work fluently (there are also GUI frontends and other tools available to simplify tasks). However, once the basic script is set up, adding new tasks is extremely trivial. This page contains functions and scripts to get you started.

The full example can be downloaded here, so you can tweak it with more hotkeys: Finale-autohotkey-jwplugins.zip

All you need to know

When you're basic script is set up, the following example should cover all you need to know to interact with the plug-in:

#IfWinActive, ahk_class Finale
^!T::
if (openJWpluginwindow("JW Plug-ins", "JW Meter and Rhythm", 5, 1) = 1)
{
   setJWpluginpanelvalue("JW Meter and Rhythm", 1, 1)
   applyandcloseJWpluginwindow("JW Meter and Rhythm")
}
return

Since it's important to understand these lines of code, here's a closer look.

#IfWinActive, ahk_class Finale

means that the keyboard macro will only be available when Finale is active. (More specifically, it requires that a window with a window class called Finale is active.)

^!T::

is the start of a keyboard macro. ^ is the Ctrl key. ! is the Alt key. So the keyboard combination in the example is Ctrl+Alt+T.

if (openJWpluginwindow("JW Plug-ins", "JW Meter and Rhythm", 5, 1) = 1)

calls the openJWpluginwindow function in the script (the code for the function is listed below). The function will start the plug-in from the menu, assure that the window opens and select container and task in the window. If everything went well, the function returns 1. Since the plug-in is modeless, you can execute this function even if the window is already on the screen. The first parameter to the function is the name of the submenu in Finale's Plug-in menu.

How the code works

This section lists the specific functions and other code that are required for the script.

At the start of the script, add the following standard lines:

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.
#Warn  ; Enable warnings to assist with detecting common errors.
SendMode Input  ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir%  ; Ensures a consistent starting directory.

Here's a general function, called openJWpluginwindow() that will open a plug-in and selects a task from the tree list.

; This function will open a plug-in and selects a task from the tree list.
; 
; submenuname: The name of the Plug-ins submenu (where the plug-in is located) within quotes.
; Use "" for the root Plug-in menu.
; pluginname: The name of the plug-in name and window title (supply it within quotes)
; containerindex: The 1-based container from the top. Top container is 1, second container is 2, etc.
; taskindex: The 1-based task from the top of the container. First task is 1, second task is 2, etc.
openJWpluginwindow(submenuname, pluginname, containerindex, taskindex)
{
; open plugin window (from submenu or root Plug-in menu)
   if (submenuname = "")
   {
      WinMenuSelectItem, Finale 201, , Plug-ins, %pluginname%    ; Root Plug-ins menu
   }
   else
   {
      WinMenuSelectItem, Finale 201, , Plug-ins, %submenuname%, %pluginname%   ; Submenu in Plug-ins menu
   }
; Wait for max 1 second for the plug-in window to open
   WinWaitActive %pluginname%, ,1
   if ErrorLevel
   {
      return 0  ; fail
   }
; Set focus to the tree view
   WinActivate %pluginname%
   ControlFocus SysTreeView321, %pluginname%
   if (ErrorLevel)
   {
       return 0
   }
; Collapse all containers
   Send {Home}
   Loop 20
   {
      Send {NumpadSub}{Down}
   }
; Move up to first container
   Send {Home}
; Move down to the correct container

   containerloop := containerindex - 1
   Loop %containerloop%
   {
      Send {Down}    
   }
   Send {NumpadAdd}
; Expand the container
   Send {NumpadAdd}
; Select the task in the container
   Loop %taskindex%
   {
      Send {Down}
   }
   return 1  ; Success
}

The setJWpluginpanelvalue() function sets a value in the panel to the right.

setJWpluginpanelvalue(pluginname, panelitemnumber, value)
{
   ControlFocus SysTreeView321, %pluginname%
   if (ErrorLevel)
   {
       return 0
   }
; Tab to the panel item
   Loop %panelitemnumber%
   {
      Send {Tab}
   }   
; Allow the new control to get focus, which take some time...
   Sleep 20

   ControlGetFocus controlvar, %pluginname%
   IfInString controlvar, Button
   {
      ; *** Checkbox ***
      if (value = 0)
         Control Uncheck, ,%controlvar%
      else
         Control Check, ,%controlvar%    
   }
   IfInString controlvar, ComboBox
   {
      ; *** Pull-down list - 1-based list index ***
      Control Choose, %value%, %controlvar%
   }
   IfInString controlvar, Edit
   {
      ; *** Edit - set the text **
      ControlSetText %controlvar%, %value%
      sleep 20  ; a little sleep here as well, since multiple edit boxes seem to need it
   }
;   MsgBox %controlvar%
   return 1
}

The applyandcloseJWpluginwindow() function will simulate a press of the Enter key and close the plug-in window:

applyandcloseJWpluginwindow(pluginname)
{
   WinActivate %pluginname%
   if (ErrorLevel)
   {
       return 0
   }
   ControlFocus SysTreeView321, %pluginname%
   if (ErrorLevel)
   {
       return 0
   }
   Send {Enter}
   sleep 50
   WinClose %pluginname%
}