Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chris Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Can't get specific window focus within HTA

Status
Not open for further replies.

jturnervbs

Programmer
Aug 27, 2007
3
US
I have this problem with HTA's. Whenever a subroutine within an hta takes an extended amount of time to execute the HTA application window becomes this lifeless blob on the desktop. You can't move it or minimize it while it's working. I was able to use a window.moveto -2000, -2000 to tuck it away while it performs the tasks and I was able to bring it back with a window.moveto 1,1 when the process was done. The problem, however, is if I'm working within another application like Excel for instance when the HTA finishes, my HTA window does not receive focus and does not return to the visible coordinates.
Is there anyway to give this specific HTA window a name and focus and also specify a specific window name "move" within my HTA? I would like to avoid using msgbox (which works sort of) but the msgbox does not present itself on-top and is often buried behind other apps. FWIW, I'm using vbscript within the HTA.
 
Thanks PH, I've tried that as well as a timer event. Both work as long as you are not actively engaged in an operation in another window. If you happen to be scrolling an Excel workbook for instance, the focus stays within Excel. If you are just sitting at the Excel worksheet viewing it then focus does shift to the HTA. I can live with this, but if there were a way to point to a specific window (by name for instance) and move it that would be prefered. This app is destined for other users that's one reason I'd really like to find a method that worked consistantly.
 
What sorts of things are you doing in this subroutine that take too long?

Blocking operations need to be avoided. The worst are probably network I/O operations like making an HTTP request using synchronous methods of some object.

If you're performing some repetitious task in a loop you may need to "unroll" the loop somewhat into smaller burdens called via setTimeout() with a small interval value.

The problem is that your subroutine is either an event handler or called by an event handler. Until the event handler is exited the Winow message loop won't run. After a certain amount of time Windows will mark the process "not responding" and before that you'll find that GUI operations don't work because these are done by sending messages to MSHTA.exe and you have it tied up.

An example might be:
Code:
<html>
  <head>
    <META HTTP-EQUIV="MSThemeCompatible" CONTENT="yes">
    <title>Keep long operation responsive</title>
    <script type="text/vbscript" language="VBScript">
Option Explicit

Dim objEvents(), intEvent, intLastEvent

Sub Echo(ByVal strMsg)
  Dim objDIV

  Set objDIV = document.createElement("DIV")
  objDIV.innerText = strMsg
  document.body.appendChild objDiv
End Sub

'Initiate event log listing.
Sub ListEventLog
  Dim strComputer, objWMIService, colLoggedEvents, objEvent

  strComputer = "."
  Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

  Set colLoggedEvents = objWMIService.ExecQuery _
    ("Select * from Win32_NTLogEvent Where Logfile = 'Application'")

  'Scoop up the objects so we can defer use.  Only For-Each
  'enumeration can be used with an SWbemObjectSet.
  intEvent = 0
  intLastEvent = colLoggedEvents.Count - 1
  ReDim objEvents(intLastEvent)
  For Each objEvent in colLoggedEvents
    Set objEvents(intEvent) = objEvent
    intEvent = intEvent + 1
  Next
  
  Set colLoggedEvents = Nothing
  Set objWMIService = Nothing
  intEvent = 0
  ListEventLogSubset
End Sub

Sub ListEventLogSubset()
  Dim intCount, objEvent
  
  For intCount = 1 To 10
    Set objEvent = objEvents(intEvent)
    Echo String(10, "#") & " EVENT # " & CStr(intEvent)
    Echo "Category: " & objEvent.Category
    Echo "Computer Name: " & objEvent.ComputerName
    Echo "Event Code: " & objEvent.EventCode
    Echo "Message: " & objEvent.Message
    Echo "Record Number: " & objEvent.RecordNumber
    Echo "Source Name: " & objEvent.SourceName
    Echo "Time Written: " & objEvent.TimeWritten
    Echo "Event Type: " & objEvent.Type
    Echo "User: " & objEvent.User
    Echo " "
    Set objEvents(intEvent) = Nothing
    intEvent = intEvent + 1
    If intEvent > intLastEvent Then
      lblStatus.innerText = "Complete!"
      btnCheck.disabled = False
      window.focus
      Exit Sub
    End If
  Next
  
  window.setTimeout "ListEventLogSubset", 50, "VBScript"
End Sub

Sub btnCheck_onclick
  btnCheck.disabled = True
  lblStatus.innerText = "Working..."
  window.setTimeout "ListEventLog", 50
End Sub
    </script>
  </head>
  <body>
    <input type=button id=btnCheck value="Check Event Logs">
    <span id=lblStatus></span>
    <hr>
  </body>
</html>
 
The problem is that I don't know how to set the focus back to a specific window or do a specific window "moveto". The process is evaluating a huge text file dump, but that really shouldn't matter. I move this particular HTA window out of the way because it's very user unfriendly while the process is running. I really just need to know if there's a way to reference a specific HTA application window and move it at the same time, regardless of whether I happen to be working in another application window or not.
 
Well I was proposing making the HTA "more friendly" - not just to the user but to Windows too. The failure of the HTA to move itself back and steal focus may be because Windows has marked it "not responding."

Can you move it manually once this long running activity has finished?
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top