How to Write Easy-Merge AutoHotkey Scripts (Technique Example)

These Steps Make Integrating Your Script Into Combo Apps Simple

In my last blog, “Encapsulate AutoHotkey Code for Multi-Script Integration and Portability (Scripting Techniques)“, I explained how to hermetically seal the auto-execute section of a script, then make variable and code object names unique—thereby reducing the risk of conflict within other scripts when building combo apps. By doing this, the script turns into a robust entity easily added to any other .ahk script while continuing to stand on its own as an independent app. As the example for this blog, I’ve rewritten the ScreenDimmer.ahk script. ScreenDimmer(I explain in detail how ScreenDimmer.ahk works in the e-book AutoHotkey Applications—which offers numerous AutoHotkey tips and tricks while reviewing all of the available AutoHotkey GUI (Graphical User Interface) pop-up controls with practical demonstrations of how to use each.)

In the rewrite of the ScreenDimmer.ahk script, I took the following steps:

  1. Insert special Label name(s) enclosing the auto-execute section.
  2. To prevent conflicts, make variable names, Label subroutines, and Menu names unique across scripts by adding custom identifiers to each.
  3. Add unique names to GUIs to allow multiple pop-ups in the same script.
  4. Evaluate user-defined functions for possible redundancy.
  5. Check for script-wide commands which affect everything (e.g. Reload, ExitApp)

Encapsulate the Auto-Execution Section

Cover 250 BorderThis first important step creates script portability by adding a Label name to the auto-execute section at the top of the script. Without this rarely used Label name, the master script can’t find the critical startup code even though inserted with the #Include directive.

Most AutoHotkey scripts don’t include this extra Label since the auto-execute section sits at the top of the script and runs automatically. However, as a best practice, I recommend adding an encapsulating Label name to the top of any script regardless of future app integration plans. Why not? Since AutoHotkey ignores uncalled Label names, it can’t hurt. (Tip: Don’t use Autoexecute: as a Label name. Make it script specific.)

ScreenDimmer:     ; Label name added to encapsulate auto-execute

  Gui Dimmer:+AlwaysOnTop
  Gui, Dimmer:Add, Text, vDim x0 y0, Dimmer
  Gui, Dimmer:Add, Text, vBright x0 y0, Brighter
  Options := "Range60-180 NoTicks Buddy1Dim Buddy2Bright vMySlider gSD_Dimmer"
  Gui, Dimmer:Add, Slider, W200 x50 y5 AltSubmit Tooltip Reverse %options% , 128
  Gui, Dimmer:Add, StatusBar, gSD_Reset, Default Brightness 128 `t`t(Click Status Bar to Reset)
  SB_SetIcon("Shell32.dll", 44)
  DisplaySetBrightness( 128 )

  Menu, Tray, Icon, Shell32.dll, 44
  Menu, Tray, Add, Reset Dimmer, SD_Reset
  Menu, Tray, Icon, Reset Dimmer, Shell32.dll, 44 ; Change icon to a star
  Menu, Tray, Add, Show Dimmer, SD_ShowWindow
  Menu, Tray, Icon, Show Dimmer, Shell32.dll, 44 ; Change icon to a star
  Menu, Tray, Default, Show Dimmer
  Menu, Tray, Click, 1

Return

Now, whenever you #Include the script in another app, you only need to add a GoSub command in the auto-execute of the combined script:

GoSub, ScreenDimmer  ; Label name of target auto-execute section

This calls the auto-execute of the ScreenDimmer.ahk script. (Note:  In the target script, be sure to place the Return command at the end of the auto-execute section. Otherwise, the GoSub command won’t return to the calling point in the combo script—causing AutoHotkey to get lost.)

Create Unique Variable, Label, and Menu Names

In anticipation of possible naming conflict in variables, Label names, and Menu names, add unique identifiers (hopefully) to each. I used SD_ for Screen Dimmer:

SD_Dimmer:
 Gui, Dimmer:Submit, NoHide
 DisplaySetBrightness( SD_MySlider )
 SB_SetText("Brightness level is " . SD_MySlider 
     . "`t`t(Click Status Bar to Reset)")
Return

DisplaySetBrightness( Br=128 ) {
 Loop, % VarSetCapacity( GR,1536 ) / 6
 NumPut( ( n := (Br+128)*(A_Index-1)) > 65535 ? 65535 : n, GR
      , 2*(A_Index-1), "UShort" )
 DllCall( "RtlMoveMemory", UInt,&GR+512, UInt,&GR, UInt,512 )
 DllCall( "RtlMoveMemory", UInt,&GR+1024, UInt,&GR, UInt,512 )
 Return DllCall( "SetDeviceGammaRamp"
     , UInt,hDC := DllCall( "GetDC", UInt,0 ), UInt,&GR )
     , DllCall( "ReleaseDC", UInt,0, UInt,hDC )
}

SD_ShowWindow:
  Gui, Dimmer:Show, W300, Screen Brightness
Return

SD_Reset:
 DisplaySetBrightness( 128 )
 GuiControl, Dimmer:, SD_MySlider, 128
 SB_SetText("Default Brightness 128`t`t(Click Status Bar to Reset)")
Return

While this may not eliminate all possible conflicts, it certainly reduces the odds of encountering a problem.

Add Names to GUI (Graphical User Interface) Pop-ups

Since many scripts commonly use at least one GUI pop-up, eliminate confusion by adding a GUI name to each:

Gui Dimmer:+AlwaysOnTop
Gui, Dimmer:Add, Text, vDim x0 y0, Dimmer
Gui, Dimmer:Add, Text, vBright x0 y0, Brighter
Options := "Range60-180 NoTicks Buddy1Dim Buddy2Bright vSD_MySlider gSD_Dimmer"
Gui, Dimmer:Add, Slider
  , W200 x50 y5 AltSubmit Tooltip Reverse %options% , 128
Gui, Dimmer:Add, StatusBar
  , gSD_Reset, Default Brightness 128 `t`t(Click Status Bar to Reset)

Unless the combined script includes another GUI pop-up named Dimmer, no conflict occurs.

Note these special rules for built-in Labels from the online AutoHotkey documentation:

For windows other than number 1, the window’s name or number (if it has one) is used as a prefix for the special labels mentioned above; for example, 2GuiEscape and 2GuiClose would be the default labels for window number 2,  while MyGuiGuiEscape and MyGuiGuiClose would be the default labels for MyGui.

Evaluate Functions

With the exception of DisplaySetBrightness( Br=128 ), all the functions in the ScreenDimmer.ahk script are built-in AutoHotkey functions. With a low likelihood of conflict, you may not need to make any changes here. However, if AutoHotkey finds a problem with duplicate functions while loading, it throws an error.

If you find conflicting function names, use unique identifiers as described above for renaming variables, Label names, and Menu names.

Check for Script-wide AutoHotkey Commands

You should replace AutoHotkey commands which affect the entire script (e.g. Reload, ExitApp) with less severe subroutines (as discussed last time). Otherwise, you might find that your added app unexpectedly zeros all setting or, worse yet, closes all the apps in the master file.

Final Script Integration

After completing all these changes, you can add the script to any other combination script with the #Include command located somewhere after the end of the auto-execute section:

#Include C:\AutoHotkey\ScreenDimmer\ScreenDimmer.ahk

This #Include along with the GoSub, ScreenDimmer command in the auto-execute section of the combo file should do the job for integrating the Screen Dimmer script with any other AutoHotkey master script.

Best Practices

If you review the scripts available at the ComputorEdge Free AutoHotkey Script Page, you’ll see that very few of them include any of these important script integration recommendations. These epiphanies took quite a while to sink into my brainpan. However, as I go back to review these scripts (and in future examples), I’ll make every effort to build more robust code by following my own advice. It might save me a great deal of work later. I recommend that you do the same when writing an AutoHotkey script.

jack

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s