Creating Unfurling/Furling Alerts

Scripting Week 3: Kick It Up a Notch


When you’re a script writer you have a lot to be thankful for, especially when you compare yourself to the typical developer. Developers pretty much have to use full-fledged IDEs (integrated development environments) such as Visual Studio; script writers can get by just fine with Notepad. Developers have to compile every line of code they write; script writers can skip the compilation step and just write and run. Developers often find themselves worrying about things like data types and memory allocation; script writers rarely, if ever, have to give stuff like that a second thought.

And yet, as good as we script writers have it we can’t help but feel a bit envious of developers from time-to-time. Scripting is faster and easier than development, but developers definitely can do more things than script writers can. For example, one of the cool new trends in developer land is to create alerts and notifications that seem to magically roll down from the screen, display their message, then magically roll themselves back up and disappear. Pretty cool, but the kind of thing a script writer can only dream about doing.

Oh, really:

<HTA:APPLICATION 
     ID="objNoTitleBar"
     APPLICATIONNAME="Warning"
     BORDERSTYLE="static"
     BORDER="thick"
     SCROLL="no"
     SINGLEINSTANCE="yes"
     CAPTION="no"
>

<html>

<SCRIPT LANGUAGE="VBScript">

    Sub Window_OnLoad
        window.resizeTo 200,1
        window.moveTo 0,0
        For i = 1 to 200
            window.resizeTo 200, i
        Next
        iTimerID = window.setInterval("CloseWindow", 10000)
    End Sub

    Sub CloseWindow
        For i = 200 to 1 Step -1
            window.resizeTo 200, i
        Next
       self.close
    End Sub

</SCRIPT>

<body bgcolor="buttonface" onkeypress="CloseWindow">
    <center>
    <font face="Arial" size="2"><b>Problem Detected</b><p>
    The domain controller is not responding to ping attempts.</font>
    </center>
</body>
</html>

The preceding code is a little HTA that mimics the behavior of these unfurling/furling alerts we all know and love. It’s a tiny bit crude: for example, the rolling and unrolling isn’t always 100% smooth. (It’s close, but not perfect.) But it works, and it’s definitely an attention-grabber.

We should note that the HTA itself is really designed to be called from another script; for example, you might have a monitoring script that periodically pings a domain controller to ensure that it is still online. What happens if the domain controller fails to respond to a ping request? Well, you could display that alert in a message box, or you could unfurl a nifty little notification that looks like this:

Unfurling Notification


OK, granted, this might not look all that cool. But this is one case where you really need to see the HTA in action in order to appreciate it.

Let’s take a look at how this all works. To begin with, we include the <HTA:APPLICATION> tag, in which we set a number of parameters:

<HTA:APPLICATION 
     ID="objNoTitleBar"
     APPLICATIONNAME="Warning"
     BORDERSTYLE="static"
     BORDER="thick"
     SCROLL="no"
     SINGLEINSTANCE="yes"
     CAPTION="no"
>

Out of all these parameters the one that really matters is this:

CAPTION="no"

Setting the Caption to no removes the title bar from our window; in turn that takes away the close button, the minimize and maximize buttons, and everything else that makes a window look like a window. What we’re left with, then, is an HTA that looks like a little alert box rather than an actual application.

Our HTA also includes a pair of subroutines: one to control how the HTA opens, the other to control how the HTA closes. When the HTA starts up, the Window_OnLoad subroutine automatically runs:

Sub Window_OnLoad
    window.resizeTo 200,1
    window.moveTo 0,0
    For i = 1 to 200
        window.resizeTo 200, i
    Next
    iTimerID = window.setInterval("CloseWindow", 10000)
End Sub

What we do here is resort to a little bit of trickery. To begin with, we immediately resize the window to 200 pixels wide by 1 pixel high, then use the moveTo method to move the HTA window to the top left-hand corner of the screen (0 pixels from the left-hand edge and 0 pixels from the top edge). All in all this happens pretty quick: even if you’re looking for it you probably won’t see any of it taking place.

We then use a second little trick to make the HTA window unfurl. We want our final window size to be 200 pixels wide by 200 pixels high. In order to create the illusion of the window unrolling from the top of the screen, we set up a For Next loop that runs from 1 to 200; each time we go through the loop, we make the window size a tiny bit bigger:

For i = 1 to 200
    window.resizeTo 200, i
Next

As you can see, the first time through the loop our window will be 200 pixels wide by 1 pixel high; the second time through the loop it will be 200 pixels wide by 2 pixels high. (All we’re really doing here is leaving the width the same and extending the bottom of the window down 1 pixel at a time.) When we’re all done we’ll have a window 200 pixels by 200 pixels, a window which will seem to have unfurled from the top of the screen.

The last line of code in the Window_OnLoad subroutine is optional, but we wanted our notice to automatically disappear after 10 seconds. Therefore, we set up a timer and set it for 10 seconds (10,000 milliseconds). When those 10 seconds are up, the subroutine CloseWindow will be called:

iTimerID = window.setInterval("CloseWindow", 10000)

Speaking of CloseWindow, this subroutine is pretty much the Window_OnLoad subroutine in reverse. Window_OnLoad starts with a window 200 pixels wide by 1 pixel high and ends with a window 200 pixels wide by 200 pixels high. With CloseWindow we do just the opposite: we start with a window 200 pixels by 200 pixels, and then end with one 200 pixels by 1 pixel.

To do that we set up a For Next loop that runs backwards from 200 to 1 (the Step -1 instructs the script to go backwards instead of forwards):

For i = 200 to 1 Step -1
    window.resizeTo 200, i
Next

After the loop finishes we then call the Close method to close the window and terminate the HTA.

Thanks, we thought it was kind of cool, too.

As for the rest of the HTA, the body tag simply contains the message we want to display, along with any HTML formatting. (At this point, our HTA is just a Web page.) One parameter that we added to the <BODY> tag was this:

onkeypress="CloseWindow"

What does that do? Well, the onkeypress event is fired whenever the HTA has the focus and any key on the keyboard is pressed. What we’re doing here is calling the CloseWindow subroutine if the user presses any key on the keyboard; that provides a way for the user to dismiss the window without waiting for the 10-second timeout period to expire.

Probably not the most important piece of code you’ll ever write, but, hey, there’s nothing wrong with writing scripts that are both useful and fun, especially when the fun part doesn’t require any more work than this.

*

Top of pageTop of page