How Can I Center an HTA on the Screen?

How Can I Center an HTA on the Screen?

  • Comments 15
  • Likes
Hey, Scripting Guy! Question

Hey, Scripting Guy! How can I center an HTA on the screen?

-- BH

SpacerHey, Scripting Guy! AnswerScript Center

Hey, BH. Well, we have an answer for you, although it’s not perfect: we can resize (if need be) and center your window, but there will be a momentary flash on the screen when all this happens. It’s not too terribly distracting and the net effect is what you want: the HTA will be centered on screen. We were hoping to make this process a little smoother, but this approach will have to do for now.

Here’s the code for our sample HTA. (To try this out, copy the code, paste it into Notepad, and then save the file with a .hta file extension.) The part we care about (and the only part that really does much of anything) is the Window_Onload subroutine, a subroutine which automatically runs any time the HTA is loaded or refreshed:

<html>
<head>

<title>Centered HTA</title>

<HTA:APPLICATION 
     ID="objHTA"
     APPLICATIONNAME="Centered HTA"
     SCROLL="yes"
     SINGLEINSTANCE="yes"
>
</head>

<SCRIPT Language="VBScript">
    Sub Window_Onload
        strComputer = "."
        Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
        Set colItems = objWMIService.ExecQuery("Select * From Win32_DesktopMonitor")
        For Each objItem in colItems
            intHorizontal = objItem.ScreenWidth
            intVertical = objItem.ScreenHeight
        Next
        intLeft = (intHorizontal - 800) / 2
        intTop = (intVertical - 600) / 2
        window.resizeTo 800,600
        window.moveTo intLeft, intTop
    End Sub
</SCRIPT>

<body></body>
</html>

Start this HTA and - after a brief flash - the window will be resized to 800 pixels by 600 pixels, and will be centered onscreen.

Good question: what is going on here? Well we start off with some standard WMI code that connects to the WMI service on the local computer and then queries the Win32_DesktopMonitor class.

Note. We’re assuming that you have only one monitor connected to your machine. If you have multiple monitors you might have to add a WHERE clause that ensures you will retrieve the screen height and width of the primary monitor.

After connecting to the Win32_DesktopMonitor class we then use these two lines of code to determine the current screen dimensions:

intHorizontal = objItem.ScreenWidth
intVertical = objItem.ScreenHeight

We’ve already decided, in advance, that we want our HTA window to be 800 pixels wide by 600 pixels high. Therefore we can use this code to figure out where the top left-hand corner of the window needs to be positioned:

intLeft = (intHorizontal - 800) / 2
intTop = (intVertical - 600) / 2

As you can see, we’re taking the screen width (stored in the variable intHorizontal) and subtracting 800 pixels (the horizontal size of the HTA window). Let’s assume we have a monitor resolution of 1024x768. Subtracting 800 from 1024 leaves us with 224: that tells how us how much wider the screen is than our HTA window. To center the window, we just need to make sure we have 112 pixels on each side; that’s why we divide 224 (intHorizontal - 800) by 2.

We then repeat the process for the screen height. On our sample monitor, that gives us 768 - 600, or 168. Dividing that by two leaves us with 84 pixels above and below the window.

And that leaves us with two final chores. First, we resize the window to 800 pixels by 600 pixels:

window.resizeTo 800,600

Next, we position the window accordingly. That’s what we do here:

window.moveTo intLeft, intTop

All we’re doing is calling the moveTo method and moving the HTA window so that the top left-hand corner is located 112 pixels in from the left and 84 pixels down from the top.

Incidentally, we put the resizeTo method near the bottom of the subroutine for educational purposes: we wanted to talk about resizeTo and moveTo at the same time. However, you’ll get a slightly less-distracting flash if you start the subroutine off by resizing the window:

Sub Window_Onload
    window.resizeTo 800,600
    strComputer = "."
    Set objWMIService = GetObject("Winmgmts:\\" & strComputer & "\root\cimv2")
    Set colItems = objWMIService.ExecQuery("Select * From Win32_DesktopMonitor")
    For Each objItem in colItems
        intHorizontal = objItem.ScreenWidth
        intVertical = objItem.ScreenHeight
    Next
    intLeft = (intHorizontal - 800) / 2
    intTop = (intVertical - 600) / 2
    window.moveTo intLeft, intTop
End Sub

It’s not a big deal, but it helps a little. And we’ll continue to hunt for ways to eliminate the flashing. (Why is that so difficult? Well, ideally, we’d hide the HTA window until it has been resized and moved, something you can do with Internet Explorer. However, we haven’t found a way to do that with HTAs. But we haven’t given upon that.)

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Hi,

    To remove the flicker, rename Window_Onload to something else and call it before the body renders.

    ......

    </head>

    <script>

    Sub DoResize 'Do not use Window_Onload

       window.resizeTo 800,600

       strComputer = "."

       Set objWMIService = GetObject("Winmgmts:\\" & strComputer & "\root\cimv2")

       Set colItems = objWMIService.ExecQuery("Select * From Win32_DesktopMonitor")

       For Each objItem in colItems

           intHorizontal = objItem.ScreenWidth

           intVertical = objItem.ScreenHeight

       Next

       intLeft = (intHorizontal - 800) / 2

       intTop = (intVertical - 600) / 2

       window.moveTo intLeft, intTop

    End Sub

    DoResize() 'Run the subroutine to position the containing window (your HTA dialog) before the body is rendered.

    </script>

    <body>

    ......

    Regards,

  • If you trigger the sub before the HTA:APPLICATION tag, you shouldn't get the flashing window.

  • I copied and pasted the above code and when I run the HTA I get the following error:

    Line: 26

    Error: Type mismatch.

  • Hi Derek,

    Maybe your computer have more than one Desktop Monitor available.

    Try something like this :

    [...]

    Set colItems = objWMIService.ExecQuery("Select * From Win32_DesktopMonitor")

      For Each objItem in colItems

          if objItem.Availability = 3 then

          intHorizontal = objItem.ScreenWidth

          intVertical = objItem.ScreenHeight

          end if

      Next

    [...]

    msdn.microsoft.com/.../aa394122(VS.85).aspx

  • or try

    window.moveTo (screen.width - document.body.clientwidth)/2, (screen.height - document.body.clientheight)/2

  • Jim -

    Windows changes constantly. When this article was writen in 2005, Windows was just a little baby.  Today Windows is all grown up.  Windows can remain stable and centered without much help from the outside community.

    Windows is very thankful for all of your help.

    If you need any furthur assistance from Windows please contact you vendor.

    Thsnk you - The Window Washers Team.

    P.S. - Good luck with that long division.  Even Dr. Scripto has trouble with that.

  • This does not work if the HTA is running as a non-admin user.

  • Since 2005 we have moved from Civil War techniques to modern methods.

    window.moveTo (screen.width - document.body.clientwidth)/2, (screen.height - document.body.clientheight)/2

  • Another Solution to resolve the flicker is to make the script do an initial re-size to 1px and move off screen, then on Window_OnLoad bring the script back on screen (after the calculations have been made.)

    This should work, with a slight delay/problem:

    1: user will see the Program Load by additional Taskbar app being indicated, yet the application would not have appeared into view yet. Depending on how much the content loaded takes the user might think that it failed to load.

    Could be solved by adding  SHOWINTASKBAR="no" to the HTA:Application portion of the <Head

    2. The Flicker might still manifest, yet should be minimal as compared without the initial resize, then move.

    I was able to view the flicker on my computer (Intel P4 desktop with 2GB DDR), yet not on my work laptop (Intel i5 laptop with 8GB DDR3)

    <SCRIPT Language="VBScript">

    window.resizeto 1,1                      'makes the app just 1px or as significant as 1 dead-pixel

    window.moveto -100,-100             'makes the app move someplace it can't be seen

    Sub Window_Onload

           strComputer = "."

                 Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

                 Set colItems = objWMIService.ExecQuery("Select * From Win32_DesktopMonitor")

           For Each objItem in colItems

               intHorizontal = objItem.ScreenWidth

               intVertical = objItem.ScreenHeight

           Next

                intLeft = (intHorizontal - 300) / 2

                intTop = (intVertical - 200) / 2

                     window.resizeTo 300,200

                     window.moveTo intLeft, intTop

    End Sub

    </SCRIPT>

  • I just used this straight after the inital <html> tag.

    <script language=VbScript>

    window.resizeTo 250,130

    </script>

    Continue with code.....

  • <script type="text/javascript">

       // reduces flicker down to minimum

       window.resizeTo(0, 0);

       var objWMIService = GetObject("winmgmts:\\\\.\\root\\cimv2");

       var colItems = objWMIService.ExecQuery("Select * From Win32_DesktopMonitor");

       for (var enumItems = new Enumerator(colItems); !enumItems.atEnd(); enumItems.moveNext()) {

           var objItem = enumItems.item();

           var intHorizontal = objItem.ScreenWidth;

           var intVertical = objItem.ScreenHeight;

       }

       intLeft = (intHorizontal - 800) / 2;

       intTop = (intVertical - 600) / 2;

       window.moveTo(intLeft, intTop);

       window.resizeTo(800, 600);

    </script>

  • This is the way we have been doing this for more than a deceade and it always works: Sub CenterWindow( widthX, heightY ) self.ResizeTo widthX, heightY self.MoveTo (screen.Width - widthX)/2, (screen.Height - heightY)/2 End Sub

  • This forum editor is so flakey: Sub CenterWindow( widthX, heightY ) self.ResizeTo widthX, heightY self.MoveTo (screen.Width - widthX)/2, (screen.Height - heightY)/2 End Sub

  • var windowWidth = 600, windowHeight = 405; window.resizeTo ( windowWidth, windowHeight ); window.moveTo ( (screen.width - windowWidth) / 2, (screen.height - windowHeight) / 2 );

  • This forum editor is so flakey: Sub CenterWindow( widthX, heightY ) self.ResizeTo widthX, heightY self.MoveTo (screen.Width - widthX)/2, (screen.Height - heightY)/2 End Sub