AutoIt Wait until browser window is visible not working as expected - windows

Consider that I have the handle ($browser_handle) of a web browser window ('firefox') available in my AutoIt script.
I would like perform some keystrokes after I know that the firefox browser window is open and visible on my display so that I can bring it to focus using -
WinActivate($browser_handle)
or
WinWaitActive($browser_handle)
To make sure that the window is visible before I try to bring it into focus I have a while loop which waits till the state of the window handle is visible (2).
While (Not BitAND(WinGetState($browser_handle), 2)) WEnd //until window visible
If I use a Sleep(5000) function before the while loop then I do not face any issues.
If I do not use an arbitrary Sleep function in my script, the Whileloop condition never becomes true and turns into an infinite loop.
When I tried to check what the return value of WinGetState($browser_handle) is when there is no Sleep function,
It remains 5 even if the browser is visible and becomes 0 after the browser window is closed.
I'm unable to understand why the WinGetStatereturn value never becomes 2(visible) even if the browser is visible when there is no Sleep function.
This is a test code which can reproduce the issue -
#include <Constants.au3>
Local $browser_name = 'C:\Program Files (x86)\Internet Explorer\iexplore.exe'
Run($browser_name)
ProcessWait('iexplore.exe')
Local $browsers = ProcessList('iexplore.exe')
Local $pid = $browsers[1][1];
_WinActiveByPID($pid)
Local $sText = WinGetTitle("[ACTIVE]")
; Display the window title.
MsgBox($MB_SYSTEMMODAL, "", $sText)
Func _WinActiveByPID($pid) ;False to WinActivate, True to just see if it's active
Local $aWL = WinList()
For $iCC = 1 To $aWL[0][0]
If ($aWL[$iCC][0] <> '') And _
(WinGetProcess($aWL[$iCC][1]) = $pid) Then
While (Not BitAND(WinGetState($aWL[$iCC][1]), 2))
MsgBox($MB_SYSTEMMODAL, "", WinGetState($aWL[$iCC][1]))
WEnd
WinWait($aWL[$iCC][1])
WinActivate($aWL[$iCC][1])
WinWaitActive($aWL[$iCC][1])
Return 1
EndIf
Next
Return SetError(2, 0, 0)
EndFunc
Note:
WinWait does not work in this situation, If you see the example in the link there is a Sleep after WinWait, this function returns even if the window is hidden.
The browser window in my original script is not launched using Run, it is a Java program which opens the browser. I know that the Run method returns the PID of the browser which I can use to resolve this issue but since it starts from Java I have to use ProcessList to obtain the PID of the browser.
Please let me know how I can get this to work.
Thanks

You got thing too complicated for no reason there. Let me show you.
Local $browser_name = 'C:\Program Files (x86)\Internet Explorer\iexplore.exe'
Run($browser_name)
ProcessWait('iexplore.exe')
Sleep(500) ; because ProcessWait will exit when the process is created not when the window is visible. If your computer is slow you will have an problem
Local $BrowsersHWND = WinList()
Local $hBrowserHandle[2]
For $i = 0 To $BrowsersHWND[0][0] -1
If StringInStr($BrowsersHWND[$i][0], "Internet Explorer") Then
$hBrowserHandle[0] = $BrowsersHWND[$i][0] ;title
$hBrowserHandle[1] = $BrowsersHWND[$i][1] ;handle
ExitLoop
EndIf
Next
If $hBrowserHandle[0] = "" Or $hBrowserHandle[1] = "" Then Exit MsgBox(0, 0, "Internet Explorer not found")
Local $hState = WinGetState($hBrowserHandle[0])
Local $sVisibleStates[24] = [2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 34, 35, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47] ;visible states
Local $hCheck = False
For $j = 0 To UBound($sVisibleStates) -1
If $hState = $sVisibleStates[$j] Then
ConsoleWrite("Window state(visisble): " & $hState & #LF)
$hCheck = True
ExitLoop
EndIf
Next
If $hCheck = False Then
ConsoleWrite("Activating: " & $hBrowserHandle[0] & #LF)
WinActivate($hBrowserHandle[0])
EndIf
I have added all the cases of states where your window would be visible.
WinWait will not activate any window and I recommend you never use it. It could freeze a script for ever without reason. I will not explain why because it would take pages but avoid it. Also avoid using WinWaitActive. For similar reasons.
You have too many issues in your code that's why I completely changed it. Not worth explaining it.

I think the problem is not necessarily with the code, but possibly with the logic. I could be way off base here, but maybe we should not be looking for a state of 2, but something closer to 15.
A sample with notepad:
$WIN_STATE_EXISTS (1) = Window exists
$WIN_STATE_VISIBLE (2) = Window is visible
$WIN_STATE_ENABLED (4) = Window is enabled
$WIN_STATE_ACTIVE (8) = Window is active
A window that is active (8), enabled (4), visible(2), and exists(1) will have a windows state of 15.
; Look for notepad and display WindowState number
if WinExists("[Class:Notepad]") Then
MsgBox($MB_SYSTEMMODAL, "", "Found")
WinActivate("[Class:Notepad]")
$WinState = WinGetState("[Class:Notepad]")
MsgBox($MB_SYSTEMMODAL, "", $WinState)
EndIf

Related

VB6 Don't Auto-Activate Child Form on Form-Resize Windows 10

A window in this VB6 legacy system that I'm supporting hosts a Word 2007 instance as a child window. On Windows 7, the parent window can be resized without any issues: the window doesn't update until the mouse is released after resizing. On Windows 10, however, the window updates dynamically while being resized.
The issue I'm encountering in Windows 10 is that the child Word window is getting activated/focused upon the first update: you can only drag to resize the parent window by a couple pixels at a time, before the child window gets focused and the resize event on the parent window is canceled (the cursor is still on the resize icon, but continued dragging has no effect). Maximizing, minimizing, and restoring the parent window all work normally. Once the child Word window is closed (through the file menu in Word), the parent window can be resized normally, because there's no child window to activate/focus. The same automatic-child-window-activation-after-parent-window-resizing occurs in Windows 7, but because the resize event doesn't fire until after the parent window has actually updated, it's not an issue there.
My conundrum is that I don't see anything in the code that suggests why the child window is getting automatically activated/focused, unless that's just default Windows behavior. In either case, I'm pretty sure I need a way to make that not happen.
All that this code is explicitly doing (primarily the ResizeControls() sub; the rest is here mostly for context) is resizing/positioning the Word window to correspond to the new size of the container in the parent window, which is consistent with the behavior in Windows 7.
From what I can tell, I don't believe that GetWindow() actually activates the window it gets a handle to, but if it does, then that's likely the cause of the issue, in which case I need to be able to get a handle to the window without activating it.
PDFView.frm:
Begin VB.Form frmPDFView
Caption = "Untitled"
ClientHeight = 8655
ClientLeft = 1320
ClientTop = 1665
ClientWidth = 9270
' ...
Begin VB.PictureBox picContainer
BackColor = &H00FFFFFF&
Height = 4215
Left = 1080
ScaleHeight = 4155
ScaleWidth = 4995
TabIndex = 0
Top = 120
Width = 5055
End
End
Private Sub ResizeControls()
On Error Resume Next
Dim pWndChild As Long
Dim r As RECT
Dim rtn As Long
picContainer.Left = 100
picContainer.Height = Me.Height - 1300
picContainer.Width = Me.Width - 350
picContainer.Top = 300
pWndChild = GetWindow(picContainer.hWnd, GW_CHILD)
rtn = GetLastError
If (pWndChild) Then
rtn = GetClientRect(picContainer.hWnd, r)
rtn = SetWindowPos(pWndChild, 0, 0, 0, r.Right - r.Left, r.Bottom - r.Top, SWP_NOZORDER Or SWP_NOMOVE)
Else
rtn = GetLastError
End If
End Sub
Private Sub Form_Resize()
On Error GoTo ERROR_HANDLER
Call ResizeControls
Exit Sub
ERROR_HANDLER:
Err.Clear
Resume Next
End Sub
Turns out I'm blind and/or didn't read the documentation thoroughly enough for all the Windows functions used in the code. Found the solution the next day and forgot to come back and answer this, but as confirmed by #wqw's comment, the issue was with SetWindowPos(). The SWP_NOACTIVATE flag needed to be passed in to SetWindowPos() to prevent activation of the target window (in my case, the child Word window).

Jaspersoft iReports designer 5.6.0; how to fix size of expression editor window

As I am working mainly with large expressions within iReport designer, I want to fix the window size of the expression editor of the iReport designer to a larger size compared with what it defaults to.
Each time I open the expression editor within the iReport designer, it defaults to a relatively small window and then I always have to re-arrange it. As a double click on the title bar doesn't do anything, this is using a considerable amount of time when I have to do this 100ths of time each day.
Is there a way to set the position, width and height of the iReport designer 5.6.0 (I don't use Jaspersoft Studio because of its even more time-consuming file save behavior) so that next time I open the expression editor it will use this position, width and height?
(I have already searched the internet, also here on SO - but nobody seems to have this problem)
As I could nowhere find an answer to this I have quickly developed a workaround with AutoIt.
;Here the AutoIt code:
; *** Variables ***
$FrameInPercent = 10
do
$hWindow = WinWaitActive("[CLASS:SunAwtDialog;TITLE:Expression editor]", "") ; *** Wait here until the Expression editor window is opened ***
WinActivate($hWindow)
; *** Calculate distance from screen edge for Expression editor window ***
$DeskSize = _GetWorkingArea()
$WindowWidth = $DeskSize[2]-($DeskSize[2]*(0.01*2*$FrameInPercent))
$WindowHeight = $DeskSize[3]-($DeskSize[3]*(0.01*2*$FrameInPercent))
$windowStartLeft = ($DeskSize[2]*(0.01*$FrameInPercent))
$windowStartTop = ($DeskSize[3]*(0.01*$FrameInPercent))
WinMove($hWindow, "",$windowStartLeft, $windowStartTop, $WindowWidth, $WindowHeight)
;WinMove($hWindow, "",71, 116, 1815, 863)
Do
Sleep(1000) ; calmly idle around as long as the Expression editor window is open
until NOT(WinExists($hWindow))
until False ; *** Loop forever ***
;===============================================================================
;
; Credits for this function goes to: https://www.autoitscript.com/forum/topic/53788-getting-windows-desktop-size/
; Function Name: _GetWorkingArea()
; Description: Returns the coordinates of desktop working area rectangle
; Parameter(s): None
; Return Value(s): On Success - Array containing coordinates:
; $a[0] = left
; $a[1] = top
; $a[2] = right
; $a[3] = bottom
; On Failure - 0
;
;===============================================================================
Func _GetWorkingArea()
#cs
BOOL WINAPI SystemParametersInfo(UINT uiAction, UINT uiParam, PVOID pvParam, UINT fWinIni);
uiAction SPI_GETWORKAREA = 48
#ce
Local $dRECT = DllStructCreate("long; long; long; long")
Local $spiRet = DllCall("User32.dll", "int", "SystemParametersInfo", _
"uint", 48, "uint", 0, "ptr", DllStructGetPtr($dRECT), "uint", 0)
If #error Then Return 0
If $spiRet[0] = 0 Then Return 0
Local $aRet[4] = [DllStructGetData($dRECT, 1), DllStructGetData($dRECT, 2), DllStructGetData($dRECT, 3), DllStructGetData($dRECT, 4)]
Return $aRet
EndFunc
In order to use this you have to install AutoIt: https://www.autoitscript.com/site/autoit/downloads/
And then run this script (doubleclick it). The script will run forever but will not take much CPU power as it is event driven while waiting for the Expression editor to appear and while the expression editor is open, it only scans every 1 second if this window is still open.
Hope this helps someone.
As this is my first AutoIt script, optimizations are welcome :-)

AutoIT Close all windows except shutdown

I'm building a program that shuts down all open windows after 60 seconds of no mouse movement using AutoIT and a code I found here:
https://www.autoitscript.com/forum/topic/97638-closing-all-open-windows/
I edited it a little such that it looks like this:
#include <MsgBoxConstants.au3>
Opt("WinTitleMatchMode", 3) ;3 = exact title match
Opt("TrayIconDebug", 1)
$S_running = "check-4-app2" ;name the script
If WinExists($S_running) Then Exit
AutoItWinSetTitle($S_running)
$count = 0
$mousePos = MouseGetPos()
while 1
$count += 1
$mousePosNow = mouseGetPos()
If $mousePosNow[0] <> $mousePos[0] Or $mousePosNow[1] <> $mousePos[1] Then $count = 0
$mousePos = MouseGetPos()
;ToolTip("count = " & $count, 0, 0)
If $count > 60 Then
$count = 0
$var = WinList ()
$length = UBound($var) - 2
For $i = 1 to $length
If BitAnd (WinGetState ($var[$i][1]), 2) And $var[$i][0] <> "" AND $var[$i][0] <> "Program Manager" Then WinClose ($var[$i][1], "")
Next
EndIf
Sleep(1000)
WEnd
It does actually close all open windows after 60 seconds but it opens the windows shutdown window as well (like when you press the alt+f4 combination) in windows 7.
How to stop this window from popping up? I just like all windows to close and have a clean desktop view.
First you should do some debug for all values in $var=WinList() to see if some window in your OS is special ,that means, if such window is shutdown, it will trigger windows shutdown, if problem still exists, I found a walkround way , I tried in my computer to do following code
WinClose("Close Windows")
; or maybe WinClose("Shutdown Windows")
to close what you said "windows shutdown window",maybe you can put this line at the bottom of your code
attention: in my computer, its OS language is not english, so maybe you should first trigger "windows shutdown window" and use AutoIt window info tool to see its window title precisely

How to get and set Windows Explorer view settings

I'm trying to make a script cycle views in Windows Explorer (Windows 7 libraries don't allow remembering view settings per folder).
I found postMessage with the WM_COMMAND message (code 0x111), but can't seem to use it to affect the Explorer view. Nothing happens when I send:
PostMessage,0x111,0x702c,0,,ahk_id %parent%
where %parent% is the handle of the window. Examples on the forums are for Windows XP, which seems to work differently. How to get and set the view setting?
You can try the following. It starts a persistent script that runs a timer subroutine looking for Save-As type windows, and when it encounters one, it sends that found window certain key strokes. Note, the keys to send WILL DEFINITELY DEPEND on which Win version you use -- and I had trouble with the standard Win 7 shortcuts and hence used a kludgey work-around. It should be clear from the comments in the code what I am doing, and this should get you on your way to doing what you need.
#Persistent
SetTitleMatchMode, 2 ; Matches all titles with the designated words in it (picks the top most)
SetTimer, MaxAll, 150 ; time in ms
return
MaxAll:
IfWinActive, Save MoviePlus File As ; runs only on "Save MoviePlus File As"
DoIt("Movie")
IfWinActive, Save ; runs on "Save" "Save As" "Save File" etc.
DoIt("Save")
IfWinExist, Open ; runs on "Open" "Open File" "File Open" etc.
DoIt("Open")
IfWinExist, Import ; runs on "Import" "File Import" "Import Commands" etc.
DoIt("Import")
return
DoIt(Type)
{
SetTimer, MaxAll, Off ; turn of timer
sleep, 250
WinMaximize ; maximize the window (or comment out)
sleep, 250
Send, !n ; start at the Filename textbox
sleep, 250
Send, +{tab} ; SHIFT+TAB to move to files pane
sleep, 250
; Send, ^+5 ; CTRL+SHIFT+5: Win8.1 to go to "List View"
; Send, ^!5 ; CTRL+ALT+5: Win8 to go to "List View"
; Send, {LAlt}vl ; LEFTALT+V+L: Win7 to go to "List View" - but doesn't work consistently
SendEvent, {F3}{tab}{right 2}{down}{end}{up 3}{enter} ; Navigate to "View" drop-down-list starting from from search bar
sleep, 250
IfEqual, Type, Open ; If the dialog was a File Open
{
Send, !p ; ALT+P: Toggles preview pane
sleep, 250
}
IfEqual, Type, Movie ; If the dialog was for MoviePlus
{
Send, ^!p ; Ctrl+ALT+P: Toggles preview pane? Google the keyboard shortcuts (I didn't check)
sleep, 250
}
Send, !n ; back to Filename textbox
WinWaitClose ; wait to close the dialog
SetTimer, MaxAll, On ; turn timer back on
return
}
+esc::ExitApp ; Shift+Esc ends script
HTH,
Found a UDF for AutoIt that works for me. It's called automating windows explorer. The code below I wrote based on the forum example, it shows a working example of getting the view and changing it by incrementing the existing state.
Since it is for Windows 7 I skip the thumbnail and thumbstrip views--I think those are for Vista. The content view is not supported by Vista either.
I googled the Windows Constants names and values. I found the correct view sizes by experimenting/looking at my own results.
#include "Includes\AutomatingWindowsExplorer.au3"
;Icon sizes are standard: 16, 48, 96, 196
;Details & list: 16
;Tiles: 48
;Content: 32 (!)
;~ FVM_ICON = 1, (48, 96, 196)
;~ FVM_SMALLICON = 2, (16)
;~ FVM_LIST = 3,
;~ FVM_DETAILS = 4,
;~ FVM_THUMBNAIL = 5, (seems to be same as ICON in win7)
;~ FVM_TILE = 6,
;~ FVM_THUMBSTRIP = 7, (seems to be same as ICON in win7)
;~ FVM_CONTENT = 8,
Opt( "MustDeclareVars", 1 )
Example()
Func Example()
; Windows Explorer on Vista, 7, 8
Local $hExplorer = WinGetHandle( "[REGEXPCLASS:^(Cabinet|Explore)WClass$]" )
If Not $hExplorer Then
MsgBox( 0, "Automating Windows Explorer", "Could not find Windows Explorer. Terminating." )
Return
EndIf
; Get an IShellBrowser interface
GetIShellBrowser( $hExplorer )
If Not IsObj( $oIShellBrowser ) Then
MsgBox( 0, "Automating Windows Explorer", "Could not get an IShellBrowser interface. Terminating." )
Return
EndIf
; Get other interfaces
GetShellInterfaces()
; Get current icon view
Local $view = GetIconView() ;returns array [view,size]
; Determine the new view
Local $iView, $iSize, $iNewView, $iNewSize
$iView = $view[0] ; Icon view
$iSize = $view[1] ; Icon size
If $iView = 8 Then
$iNewView = 1
$iNewSize = 48
Else
$iNewView = $iView + 1
If $iNewView = 5 Or 7 Then
$iNewView += 1 ;skip from 5 to 6, or from 7 to 8
EndIf
EndIf
Switch $iNewView
Case 2 To 4
$iNewSize = 16
Case 6
$iNewSize = 48
Case 8
$iNewSize = 32
EndSwitch
;MsgBox( 0, "NewView", $iNewView )
SetIconView( $iNewView, $iNewSize ) ; Set details view
Sleep( 1000 ) ; Wait
SetIconView( $iView, $iSize ) ; Restore old view
EndFunc

webcam, Video Source dialog comes up

So have seen a ton of people with the same issue's but no answers. My SendMessage pop's up the "Video Source" dialog box on a windows 7 laptop with one camera. I have Cyber Link YouCam installed.
If I uninstall Cyber Link YouCam the "Video Source" dialog goes away. It appears to be the OS is acting as though YouCam is a second driver for the same device. My question is how do I stop the dialog box for "Video Source" from appearing? Once I choose an option in the dialog I don't get the dialog box (until I restart the application) so there must be a setting somewhere being set.
Though debugging found this bit of code (see whole section below) is the one that seems to be the one that calls the dialog box - SendMessage (deviceHandle, WM_CAP_CONNECT, deviceno, ((IntPtr) 0).ToInt32 ())
public void StartWebCam (int height, int width, int handleofthepicturebox, int deviceno)
{
string deviceIndex = "" + deviceno;
deviceHandle = capCreateCaptureWindowA (ref deviceIndex, WS_VISIBLE | WS_CHILD, 0, 0, width, height, handleofthepicturebox, 0);
if (SendMessage (deviceHandle, WM_CAP_CONNECT, deviceno, ((IntPtr) 0).ToInt32 ()) > 0)
{
SendMessage (deviceHandle, WM_CAP_SET_SCALE, -1, 0);
SendMessage (deviceHandle, WM_CAP_SET_PREVIEWRATE, 0x42, 0);
SendMessage (deviceHandle, WM_CAP_SET_PREVIEW, -1, 0);
}
else
{
// nothing failed maybe some clean up needed
}
}
So again the question is - how do I stop the dialog box for "Video Source" from appearing?
I developed a form to display two live captures with avicap32 on Windows XP. There is a chance the fix I found in my case also applies to yours.
In the case of avicap, it is possible to programmatically manage your webcams, and all that is registry-based. Here is the thread I found to guide me and achieve what I wanted.
In this thread, the role of the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\MediaResources\msvideo\MSVideo.VFWWDM\DevicePath registry key is highlighted for the selection of the active webcam.
And here is maybe a helpful piece of info: I had to set the value in lowercase to avoid the Video Source dialog popping up.
I determined it by monitoring the registry key before and after the call to SendMessage with WM_CAP_CONNECT.
To the best of my knowledge (and googling), nobody else has offered a fix, so even though I might be answering a little late, it would be great if you could tell us whether it worked for you as well.
Finally I Found a solution for this.
The problem happens in Windows 7 / 8
First you need this API function
Private Declare Function GetTickCount Lib "kernel32" () As Long
Then... after you call capCreateCaptureWindowA() you have to wait 1 second processing events, (note: sleep don't work the same)
IniTime = GetTickCount()
While GetTickCount() < (IniTime + 1000)
DoEvents
Wend
then you call WM_CAP_DRIVER_CONNECT (maybe a couple of times).. and THAT's IT ... no more video source dialog
With this solution it works perfect. The GetTickCount() waiting for events worked along with calling the function until it returned true.
Private Sub PreviewVideo(ByVal pbCtrl As PictureBox)
hWnd = capCreateCaptureWindowA(VideoSource, WS_VISIBLE Or WS_CHILD, 0, 0, 0,
0, pbCtrl.Handle.ToInt64, 0)
Dim IniTime As Long = GetTickCount()
While GetTickCount() < (IniTime + 1000)
Application.DoEvents()
End While
Dim OKAnswer As Boolean = False
For xretries As Integer = 1 To 10
' I'll give you Only 10 tries to connect, otherwise I AM LEAVING MICROSOFT!
OKAnswer = SendMessage(hWnd, WM_CAP_DRIVER_CONNECT, VideoSource, 0)
If OKAnswer Then
Exit For
End If
Next
If okanswer Then
SendMessage(hWnd, WM_CAP_SET_SCALE, True, 0)
SendMessage(hWnd, WM_CAP_SET_PREVIEWRATE, 30, 0)
SendMessage(hWnd, WM_CAP_SET_PREVIEW, True, 0)
SetWindowPos(hWnd, HWND_BOTTOM, 0, 0, pbCtrl.Width, pbCtrl.Height, SWP_NOMOVE Or SWP_NOZORDER)
Else
DestroyWindow(hWnd)
End If
End Sub
I had the same issue. Make sure you call capDriverDisconnect once you no longer need the webcam. Note that I'm using Logitech C110, but I suppose it should work in your case too.
Came over here searching for a solution for the "WM_CAP_DRIVER_CONNECT" and "Video Setup" dialog popup Error.
FOUND the solution:
It's a driver problem. Use the OEM's driver, because the Generic Microsoft Drivers are NOT working for your camera.
Use www.astra32.com to find out the USB camera's device info: Manufacturer or Model; then google for the correct drivers.
Good Luck!

Resources