Save AHK-Operation: winSend, winClick and more

Post your working scripts, libraries and tools for AHK v1.1 and older
Hotte
Posts: 32
Joined: 03 Jan 2018, 14:39

Save AHK-Operation: winSend, winClick and more

03 Jan 2018, 17:25

Hi,
I am working on a huge AHK-project for more than two years now. One of the biggest issues concerning stable operation is that send and click commands are being received by the correct window. If the sends drop in too early or too late or if the user interferes, you easily get a mess. This is why I have written the function winSend. In complex macros I replace Send, Click or PixelGetColor with winSend, winClick, winPixelGetColor. This way I gain much more stability with less code. I like to share it with you.

Thanks for any feedback.

winSend ("!e!f","myWinTitle")
=> Makes sure !e!f is being sent to the "myWinTitle"-window. winSend will wait for the window to appear. It will activate the window (if it is not active) before !e!f is being sent.
The function will return true (which is an errorcode) if myWinTitle does not exist for more than ~3 seconds:

Code: Select all

if winSend("!Enter","myWinTitle")
	msgBox Window not found
winSend("!{Enter}","ahk_id myWinID, myWinText,myExcludedWinTitle,myExcludedWinText")
You can address the window with a full parameter set within one string

winSend("!{Enter}",edWinTL,false,edWinClpE,true)
!Enter sent to the windows in variable edWinTL expects to open a 2nd Window with its name in variable edWinClpE. winSend waits for edWinClpE to open, but will not activate it (false). edWinClpE will be opened invisbly (true. 100% transparent, but fully working). Currently the function will wait endlessly for the 2nd window. This could easily be changed in code if there is a demand to so (I did not have this demand up to now, because my follow-up window are sure to pop up).

winSend("!e",edWinTL,true,edWinGeschw,,100,400,200,300)
Window edWinGeschw is made to appear (visible) at screen coordinates 100,400 and will be sized to 200x300

More new functions:
c := winPixelGetColor("myWinTitlte,....",100,200)
Returns savely the color of position 100,200 in myWinTitle. Will wait for the window and activate it before it reads the color. Returns -1 if myWindowTitle does not exist.

winClick("myWinTitle,...")
Perform a single click onto myWinTitle

winClick(edWinTL,100,200,2)
Perform 2 clicks at 100,200 onto the Window in variable edWinTL

winClick("notepad","Right")
Perform a right click onto the notepad window

winControlClick("Button1", "myWinTitle,...","LEFT",2)
Left clicks twice onto control Button1 in Window myWinTitle. Instead of LEFT you can use MIDDLE,X1,X2,WheelUp (or WU), WheelDown (WD), WheelRight (WR), WheelLeft (WL)

Copy all the Code (with comments in German - sorry):

Code: Select all

; winSend sends the string "senden" to the window "startFenster".
; "startFenster" can be qualified by e.g. "myWinTitle,myWinText,myExcludeTitle,myExcludeText" in the "startFenster" string.
; It waits for window "folgeFenster" and activates it if "aktivieren" is true.
; "folgeFenster" can be qualified by e.g. "myWinTitle,myWinText,myExcludeTitle,myExcludeText" in the "folgeFenster" string.
; Window "folgeFenster" is being opened invisible (100% transparent) if "unsichtbar" is true.
; Window "folgeFenster" might be opened at screenposition "xpos,ypos" with width "breite" and height "hoehe"
winSend(senden:= "", startFenster:="A", aktivieren:=true,  folgeFenster:="", unsichtbar:=false, xpos := -1, ypos := -1, breite := -1, hoehe := -1)
{	Loop,4
	{	W%A_index% :=
    	WF%A_index% :=
        P%A_index% := 0
    }
	
	WClose := false
    i := 1
    Loop, parse, startFenster, `, 
	{	if Instr(A_Loopfield,"Close")
    		WClose := true	
        else
        {	W%i% := Trim(A_Loopfield)
        	i := i + 1
        }
    }
    Loop, parse, folgeFenster, `, 
    {	WF%A_index% := Trim(A_Loopfield)
    }
	if (SubStr(senden,1,14) = "PixelGetColor,") or (Substr(senden,1,6) = "Click,") or (SubStr(senden,1,13) = "ControlClick,")
    {   Loop, parse, senden, `,									; Parameter aus Senden-String holen									
    	{	P%A_index% := Trim(A_Loopfield)						; Vorsicht: P1="Click" bzw. "PixelGetColor" bzw. "ControlClick"
        }
    	cmp := A_CoordModePixel
    	cmm := A_CoordModeMouse
		CoordMode,Pixel,Relative
        CoordMode,Mouse,Relative
    }	
   	Loop														; Warte und aktiviere Fenster ggf. mehrfach
    {   fehler := 0
        ifWinActive,%W1%,%W2%,%W3%,%W4%							;	Startfenster ist aktiv
    	{	c := f_winSend01_senden(senden,W1,W2,W3,W4		;	    Senden/Klicken/PixelGetColor ausführen. c = Farbe bei PixelGetColor
             ,P1,P2,P3,P4) 								
            if not folgeFenster								;	    Kein Folge-Fenster erwartet
            {	if WClose
                    break
                ifWinActive,%W1%,%W2%,%W3%,%W4%				;		  Start-Fenster nach dem Senden noch aktiv ?
                    break									;		    Ja => OK und Ende
            }												;		  	(Nein, nicht mehr aktiv => Bleibe in der Schleife)
            else											;		Folge-Fenster erwartet
            {	
                if aktivieren								;		  Folge-Fenster soll aktiviert werden
                {	ifWinExist,%WF1%,%WF2%,%WF3%,%WF4%		; 			Folge-Fenster ist schon da (von vorherigem Loopdurchlauf mit erfolgloser Aktivierung)
                        WinActivate,%WF1%,%WF2%,%WF3%,%WF4%	;			  Erneuter Aktivierungsversuch
                    else 									;			Folge-Fenster noch nicht da											
                    {	if not f_winSend02_folgeFensterExist(W1 ;		  Warte bis 2s auf Fenster, ggf. positionieren und transparent machen
                         ,W2,W3,W4,WF1,WF2,WF3,WF4,unsichtbar
                         ,xpos,ypos,breite,hoehe)
                            continue						;				Folge-Fenster weiter nicht da => Neuer Versuch über Schleife
                    }
                    WinWaitActive,%WF1%,%WF2%,2,%WF3%,%WF4% ;		  	Folge-Fenster sollte aktiv hochkommen, Bestehendes wurde neu aktiviert
                    if not Errorlevel						;			  		Fenster ist aktiviert							  
                        break								;			  		  => OK und raus
                }
                else										;		  Folge-Fenster braucht nicht aktiviert zu werden
                {	if f_winSend02_folgeFensterExist(W1 	;		  	Warte bis 2s auf Fenster, ggf. positionieren und transparent machen
                     ,W2,W3,W4,WF1,WF2,WF3,WF3,unsichtbar
                     ,xpos,ypos,breite,hoehe)
                        break								;			Folge-Fenster ist da => OK und raus
                } 
            }
    	}
        else   													; 	Startfenster ist nicht aktiv
        {   starttime1 := A_Tickcount
        	Loop
        	{	ifWinExist,%W1%,%W2%,%W3%,%W4%					;	  Existiert Startfenster überhaupt (noch) ?
 					break
            } Until ((A_Tickcount - starttime1) > 2000) 		;		Nach 2s ist anzunehmen, dass es inzwischen geschlossen wurde
            IfWinNotExist,%W1%,%W2%,%W3%,%W4%					;	  (Mit Loop, da WinWait mit 2s Timeout manchmal eine Dauerschleife machte)
            {	fehler := 1										;		NOTOK		
                break											;		=> Ende
            }
            WinActivate,%W1%,%W2%,%W3%,%W4%						;	  Startfenster ist da. Versuche, das Fenster zu aktivieren
            ifWinActive,%W1%,%W2%,%W3%,%W4%						;		Schnelle Prüfung
            {	c := f_winSend01_senden(senden,W1,W2,W3,W4	;	  		Senden/Klicken/PixelGetColor ausführen. c = Farbe bei PixelGetColor
                 ,P1,P2,P3,P4) 								
                if not folgeFenster							;	    	Kein Folge-Fenster erwartet
                {	if WClose
                        break
                    ifWinActive,%W1%,%W2%,%W3%,%W4% 		;	  	  	  Startfenster nach dem Senden noch aktiv ?
                        break								;		    	Ja => OK und Ende
                }											;		  		(Nein, nicht mehr aktiv => Bleibe in der Schleife)
                else										;			Folge-Fenster erwartet
                {	if aktivieren							;		  	  Folge-Fenster soll aktiviert werden
                    {	ifWinExist,%WF1%,%WF2%,%WF3%,%WF4%	;   			Folge-Fenster ist schon da (von vorherigem Loopdurchlauf mit erfolgloser Aktivierung)
                            WinActivate,%WF1%,%WF2%,%WF3%,%WF4%	; 		  	  Erneuter Aktivierungsversuch
                        {	if not f_winSend02_folgeFensterExist(W1 ;		    Warte bis 2s auf Fenster, ggf. positionieren und transparent machen
                             ,W2,W3,W4,WF1,WF2,WF3,WF4,unsichtbar
                             ,xpos,ypos,breite,hoehe)
                                continue					;				  Folge-Fenster weiter nicht da => Neuer Versuch über Schleife
                        }
                        WinWaitActive,%WF1%,%WF2%,2,%WF3%,%WF4% ;	  		Neues Fenster sollte aktiv hochkommen, Bestehendes wurde neu aktiviert
                        if not Errorlevel					;			  	Fenster ist aktiviert							  
                            break							;			  	  => OK und raus
                    }
                    else									;		  	  Folge-Fenster braucht nicht aktiviert zu werden
                    {	if f_winSend02_folgeFensterExist(W1 ;		  		Warte bis 2s auf Fenster, ggf. positionieren und transparent machen
                         ,W2,W3,W4,WF1,WF2,WF3,WF4,unsichtbar
                         ,xpos,ypos,breite,hoehe)
                            break							;			  Folge-Fenster ist da => OK und raus
                    }
                } 
            } 	
		}
     	fehler := 3												;   false setzen, wenn Looptime ohne Erfolg abläuft
    }

    CoordMode,Mouse,%cmm%
    CoordMode,Pixel,%cmp%
    
    if (P1 = "PixelGetColor")
    {	if fehler 
    		Return -fehler										; Errorcode negativ zurückgeben
    	else
        	Return c											; Farbe zurückgeben	
    } else
    	Return fehler
}	 

;Hilfsroutine 1 zu winSend. Sendet Sequenzen oder macht PixelGetColor
f_winSend01_senden(senden, W1, W2, W3, W4, P1, P2, P3, P4)
{   c := 0
    if (P1 = "PixelGetColor")
        PixelGetColor,c,%P2%,%P3%								;   c (color) wird auf den gefundenen Farbwert gesetzt
    else if (P1 = "Click")										; Für Mausclick muss Fenster kurzfristig enabled werden
    {	WinGet,s,Style,%W1%,%W2%,%W3%,%W4%
        if (s & 0x8000000)										;   Startfenster ist disabled
            WinSet,Enable,,%W1%,%W2%,%W3%,%W4%
        Click,%P2%,%P3%,%P4%
        if (s & 0x8000000)										;	und wieder zurücksetzen
            WinSet,Disable,,%W1%,%W2%,%W3%,%W4%
    }       
    else if (P1 = "ControlClick")								; Für Mausclick muss Fenster kurzfristig enabled werden
    {	WinGet,s,Style,%W1%,%W2%,%W3%,%W4%
        if (s & 0x8000000)										;	Startfenster ist disabled
            WinSet,Enable,,%W1%,%W2%,%W3%,%W4%
        ControlClick,%P2%,%W1%,%W2%,%P3%,%P4%,,%W3%,%W4%
        if (s & 0x8000000)										;	und wieder zurücksetzen
            WinSet,Disable,,%W1%,%W2%,%W3%,%W4%
    }       
    else
        Send %senden%											; Sende, was zu senden ist                    
    Return c
}
;Hilfsroutine 2 zu winSend. Wartet auf Erscheinen des Folgefensters, ggf. wird Größe und Position justiert und es unsichtbar gemacht
f_winSend02_folgeFensterExist(W1, W2, W3, W4, WF1, WF2, WF3, WF4, unsichtbar, xpos, ypos, breite, hoehe)
{	WinGet,s,Style,%W1%,%W2%,%W3%,%W4%
    Loop,13000													; 13.000x dauert ca. 2s (keine Sleeps einbauen, da diese unkalkulierbar sind)
	{	ifWinExist,%WF1%,%WF2%,%WF3%,%WF4%
    		goto g_winSend02
    }
    ifWinNotExist,%WF1%,%WF2%,%WF3%,%WF4%
    	Return false

g_winSend02:
	if (s & 0x8000000)
		WinSet,Disable,,%W1%,%W2%,%W3%,%W4%
    if(xpos >= 0) or (breite > 0)								; Wenn x-position des Fensters oder Breite mitgegeben und das Fenster hat
	{	WinGetPos,x,y,b,h,%WF1%,%WF2%,%WF3%,%WF4%				; ... hat diese Einstellung nicht, dann in nur einem Move-Befehl einstellen  
        if (xpos = -1)											; Nicht angetastete Einstellungen bleiben bestehen											
        {	xpos := x
            ypos := y
        }
        if (breite = -1)
        {	breite := b
        	hoehe := h
        }
        if ((x != xpos) or (y != ypos)) and ((b != breite) and (h != hoehe))
        {	WinSet,Transparent,0,%WF1%,%WF2%,%WF3%,%WF4%		; Für die Bewegung der Fenster zunächst unsichtbar machen und dann bewegen
        	WinMove,%WF1%,%WF2%,xpos,ypos,breite,hoehe,%WF3%,%WF4%
        }
        else if (x != xpos) or (y != ypos)
        { 	WinSet,Transparent,0,%WF1%,%WF2%,%WF3%,%WF4%
        	WinMove,%WF1%,%WF2%,xpos,ypos,,,%WF3%,%WF4%
        }
        else if (b != breite) or (h != hoehe)
        {	WinSet,Transparent,0,%WF1%,%WF2%,%WF3%,%WF4%
        	WinMove,%WF1%,%WF2%,,,breite,hoehe,%WF3%,%WF4%
        } 
        else if unsichtbar										; Fenster muss nicht neu positioniert werden
        	WinSet,Transparent,0,%WF1%,%WF2%,%WF3%,%WF4%
        
        if not unsichtbar										; Neu positionierte Fenster wieder sichtbar machen, wenn verlangt
        	WinSet,Transparent,255,%WF1%,%WF2%,%WF3%,%WF4%
       		    
    } else if unsichtbar										; Nicht zu positionierenden Fenster unsichtbar machen, wenn verlangt
    	WinSet,Transparent,0,%WF1%,%WF2%,%WF3%,%WF4%
   
    Return true
}

winPixelGetColor(Window:="A", x:=0, y:=0)
{	Return winSend("PixelGetColor," . x . "," . y, Window)
}
winClick(Window:="A", a:="", b:="", c:="")
{	Return winSend("Click," . a . "," . b . "," . c, Window)
}        
winControlClick(cntrl, Window:="A", button:="LEFT", count:=1)
{	Return winSend("ControlClick," . cntrl . "," . button . "," . count, Window)	
}
Last edited by Hotte on 05 Jan 2018, 12:01, edited 1 time in total.
jsmain
Posts: 62
Joined: 07 Feb 2014, 08:21

Re: Save AHK-Operation: winSend, winClick and more

04 Jan 2018, 22:32

Thanks for sharing.
To understand, I needed to convert to English, so I thought I'd share the translated code/comments.

Code: Select all

; winSend sends the string "Send" to the window "StartWindow".
; "StartWindow" can be qualified by e.g. "myWinTitle,myWinText,myExcludeTitle,myExcludeText" in the "StartWindow" string.
; It waits for window "FollowWindow" and activates it if "activate" is true.
; "FollowWindow" can be qualified by e.g. "myWinTitle,myWinText,myExcludeTitle,myExcludeText" in the "FollowWindow" string.
; Window "FollowWindow" is being opened invisible (100% transparent) if "invisible" is true.
; Window "FollowWindow" might be opened at screenposition "xpos,ypos" with width "width" and height "height"
winSend(Send:= "", StartWindow:="A", activate:=true,  FollowWindow:="", invisible:=false, xpos := -1, ypos := -1, width := -1, height := -1)
{	Loop,4
	{	W%A_index% :=
    	WF%A_index% :=
        P%A_index% := 0
    }
	
	WClose := false
    i := 1
    Loop, parse, StartWindow, `, 
	{	if Instr(A_Loopfield,"Close")
    		WClose := true	
        else
        {	W%i% := Trim(A_Loopfield)
        	i := i + 1
        }
    }
    Loop, parse, FollowWindow, `, 
    {	WF%A_index% := Trim(A_Loopfield)
    }
	if (SubStr(Send,1,14) = "PixelGetColor,") or (Substr(Send,1,6) = "Click,") or (SubStr(Send,1,13) = "ControlClick,")
    {   Loop, parse, Send, `,									; Parameters from send string pick up									
    	{	P%A_index% := Trim(A_Loopfield)						; Attention: P1="Click" bzw. "PixelGetColor" bzw. "ControlClick"
        }
    	cmp := A_CoordModePixel
    	cmm := A_CoordModeMouse
		CoordMode,Pixel,Relative
        CoordMode,Mouse,Relative
    }	
   	Loop														; Wait and activate windows if necessary several times
    {   error := 0
        ifWinActive,%W1%,%W2%,%W3%,%W4%							;	StartWindow is active
    	{	c := f_winSend01_Send(Send,W1,W2,W3,W4		;	    Send/click/PixelGetColor To run. c = Color at PixelGetColor
             ,P1,P2,P3,P4) 								
            if not FollowWindow								;	    No follow-up window expected
            {	if WClose
                    break
                ifWinActive,%W1%,%W2%,%W3%,%W4%				;		  Startup window still active after the send?
                    break									;		    Yes => OK and end
            }												;		  	(No, no longer active => stay in the loop)
            else											;		Follow-up window expected
            {	
                if activate									;		Follow-up window should be activated
                {	ifWinExist,%WF1%,%WF2%,%WF3%,%WF4%		; 			Follow-up window is already there (from previous loop pass with unsuccessful activation)
                        WinActivate,%WF1%,%WF2%,%WF3%,%WF4%	;			 Renewed activation attempt
                    else 									;			Follow-up window is not there yet
                    {	if not f_winSend02_FollowWindowExist(W1 ;		  Wait for 2s for windows, position if necessary and make transparent
                         ,W2,W3,W4,WF1,WF2,WF3,WF4,invisible
                         ,xpos,ypos,width,height)
                            continue						;				Next window is not there => New attempt over loop
                    }
                    WinWaitActive,%WF1%,%WF2%,2,%WF3%,%WF4% ;		  	Follow-up window should come up actively, existing one was reactivated
                    if not Errorlevel						;			  		Window is activated							  
                        break								;			  		  => OK and out
                }
                else										;		  Follow-up window does not need to be activated
                {	if f_winSend02_FollowWindowExist(W1 	;		  	Wait for 2s for windows, position if necessary and make transparent
                     ,W2,W3,W4,WF1,WF2,WF3,WF3,invisible
                     ,xpos,ypos,width,height)
                        break								;			Follow-up window is there => OK and out
                } 
            }
    	}
        else   													; 	StartWindow is not active
        {   starttime1 := A_Tickcount
        	Loop
        	{	ifWinExist,%W1%,%W2%,%W3%,%W4%					;	  Does StartWindow exist (still)?
 					break
            } Until ((A_Tickcount - starttime1) > 2000) 		;		After 2s, it can be assumed that it has now closed
            IfWinNotExist,%W1%,%W2%,%W3%,%W4%					;	  (With loop, since WinWait sometimes made a continuous loop with 2s timeout)
            {	error := 1										;		NOTOK		
                break											;		=> End
            }
            WinActivate,%W1%,%W2%,%W3%,%W4%						;	  StartWindow is there. Attempt to activate the window
            ifWinActive,%W1%,%W2%,%W3%,%W4%						;		Fast exam
            {	c := f_winSend01_Send(Send,W1,W2,W3,W4	;	  		Send / Click / Run PixelGetColor. c = color at PixelGetColor
                 ,P1,P2,P3,P4) 								
                if not FollowWindow							;	    	No follow-up window expected
                {	if WClose
                        break
                    ifWinActive,%W1%,%W2%,%W3%,%W4% 		;	  	  	  StartWindow still active after the send?
                        break								;		    	Ja => OK and End
                }											;		  		(No, no longer active => stay in the loop)
                else										;			Follow-up window expected
                {	if activate							;		  	  Follow-up window should be activated
                    {	ifWinExist,%WF1%,%WF2%,%WF3%,%WF4%	;   			Follow-up window is already there (from previous loop pass with unsuccessful activation)
                            WinActivate,%WF1%,%WF2%,%WF3%,%WF4%	; 		  	  Renewed activation attempt
                        {	if not f_winSend02_FollowWindowExist(W1 ;		    Wait for 2s for windows, position if necessary and make transparent
                             ,W2,W3,W4,WF1,WF2,WF3,WF4,invisible
                             ,xpos,ypos,width,height)
                                continue					;				  Next window is not there => New attempt over loop
                        }
                        WinWaitActive,%WF1%,%WF2%,2,%WF3%,%WF4% ;	  		New window should come up actively, existing one was reactivated
                        if not Errorlevel					;			  	Window is activated							  
                            break							;			  	  => OK and end
                    }
                    else									;		  	  Follow-up window does not need to be activated
                    {	if f_winSend02_FollowWindowExist(W1 ;		  		Wait for 2s for windows, position if necessary and make transparent
                         ,W2,W3,W4,WF1,WF2,WF3,WF4,invisible
                         ,xpos,ypos,width,height)
                            break							;			  Follow-up window is there => OK and end
                    }
                } 
            } 	
		}
     	error := 3												;   set false if looptime expires without success
    }

    CoordMode,Mouse,%cmm%
    CoordMode,Pixel,%cmp%
    
    if (P1 = "PixelGetColor")
    {	if error 
    		Return -error										; Return error code negatively
    	else
        	Return c											; Return color	
    } else
    	Return error
}	 

; Auxiliary routine 1 to winSend. Sends sequences or makes PixelGetColor
f_winSend01_Send(Send, W1, W2, W3, W4, P1, P2, P3, P4)
{   c := 0
    if (P1 = "PixelGetColor")
        PixelGetColor,c,%P2%,%P3%								;   c (color) is set to the found color value
    else if (P1 = "Click")										; For mouse click window must be enabled at short notice
    {	WinGet,s,Style,%W1%,%W2%,%W3%,%W4%
        if (s & 0x8000000)										;   StartWindow is disabled
            WinSet,Enable,,%W1%,%W2%,%W3%,%W4%
        Click,%P2%,%P3%,%P4%
        if (s & 0x8000000)										;	and reset again
            WinSet,Disable,,%W1%,%W2%,%W3%,%W4%
    }       
    else if (P1 = "ControlClick")								; For mouse click window must be enabled at short notice
    {	WinGet,s,Style,%W1%,%W2%,%W3%,%W4%
        if (s & 0x8000000)										;	StartWindow is disabled
            WinSet,Enable,,%W1%,%W2%,%W3%,%W4%
        ControlClick,%P2%,%W1%,%W2%,%P3%,%P4%,,%W3%,%W4%
        if (s & 0x8000000)										;	and reset again
            WinSet,Disable,,%W1%,%W2%,%W3%,%W4%
    }       
    else
        Send %Send%											; Send what is to send                   
    Return c
}
; Auxiliary routine 2 to winSend. Wait for the FollowWindows to show, if necessary size and position will be adjusted and it will be made invisible
f_winSend02_FollowWindowExist(W1, W2, W3, W4, WF1, WF2, WF3, WF4, invisible, xpos, ypos, width, height)
{	WinGet,s,Style,%W1%,%W2%,%W3%,%W4%
    Loop,13000													;13.000x takes about 2s (do not install any sleeps as they are incalculable)
	{	ifWinExist,%WF1%,%WF2%,%WF3%,%WF4%
    		goto g_winSend02
    }
    ifWinNotExist,%WF1%,%WF2%,%WF3%,%WF4%
    	Return false

g_winSend02:
	if (s & 0x8000000)
		WinSet,Disable,,%W1%,%W2%,%W3%,%W4%
    if(xpos >= 0) or (width > 0)								; If x-position of the window or width given and the window has
	{	WinGetPos,x,y,b,h,%WF1%,%WF2%,%WF3%,%WF4%				; ... does not have this setting, then set in just a Move command
        if (xpos = -1)											; Undocked settings remain
        {	xpos := x
            ypos := y
        }
        if (width = -1)
        {	width := b
        	height := h
        }
        if ((x != xpos) or (y != ypos)) and ((b != width) and (h != height))
        {	WinSet,Transparent,0,%WF1%,%WF2%,%WF3%,%WF4%		; For the movement of the windows first make invisible and then move
        	WinMove,%WF1%,%WF2%,xpos,ypos,width,height,%WF3%,%WF4%
        }
        else if (x != xpos) or (y != ypos)
        { 	WinSet,Transparent,0,%WF1%,%WF2%,%WF3%,%WF4%
        	WinMove,%WF1%,%WF2%,xpos,ypos,,,%WF3%,%WF4%
        }
        else if (b != width) or (h != height)
        {	WinSet,Transparent,0,%WF1%,%WF2%,%WF3%,%WF4%
        	WinMove,%WF1%,%WF2%,,,width,height,%WF3%,%WF4%
        } 
        else if invisible										; Window does not have to be repositioned
        
        if not invisible										; Make repositioned windows visible when requested
        	WinSet,Transparent,255,%WF1%,%WF2%,%WF3%,%WF4%
       		    
    } else if invisible										; Make invisible windows invisible if requested
    	WinSet,Transparent,0,%WF1%,%WF2%,%WF3%,%WF4%
   
    Return true
}

winPixelGetColor(Window:="A", x:=0, y:=0)
{	Return winSend("PixelGetColor," . x . "," . y, Window)
}
winClick(Window:="A", a:="", b:="", c:="")
{	Return winSend("Click," . a . "," . b . "," . c, Window)
}        
winControlClick(cntrl, Window:="A", button:="LEFT", count:=1)
{	Return winSend("ControlClick," . cntrl . "," . button . "," . count, Window)	
}
guest3456
Posts: 3463
Joined: 09 Oct 2013, 10:31

Re: Save AHK-Operation: winSend, winClick and more

05 Jan 2018, 09:13

Hotte wrote: One of the biggest issues concerning stable operation is that send and click commands are being received by the correct window. If the sends drop in too early or too late or if the user interferes, you easily get a mess.
you should give an example that we can test, where the normal Send command fails, and where your Send function succeeds. something like, "here do these steps 1,2,3 with this code and watch the normal Send command fail".

your code is quite complicated, but with the example, we can make some sense of it.

Hotte
Posts: 32
Joined: 03 Jan 2018, 14:39

Re: Save AHK-Operation: winSend, winClick and more

05 Jan 2018, 11:16

@jsmain
Thank you very much - very generous and excellent translation indeed! :bravo: :bravo: :bravo:

@guest3456:
Oh, I just realize, that my intro could be misleading. I am not saying, that send is not working for me. The idea is : For very complex applications it is increasingly difficult to have the window you want to send keys to is active. WinSend makes this easier for you:
- winSend directs your Send-Command to the desired window. The window will be auto-activated if it is not.
- winSend may wait for a secondary Window that you opened (e.g. Press ^s => Wait for "Save As" to open) to make sure, that the filename you Send is not being crippled or lost because of the open window time lag
- No sleep-commands - which never have the right duration (either too long or too short)
- You can open the secondary window invisibly and position and size it.

Example: Open Notepad empty and put it into the background.

Code: Select all

; Please adapt key and titles for English version: Speichern unter => Save As
if WinSend("Hello!du","Editor",true,"Speichern unter",false,100,100,500,600)	; Bring notepad into foreground, type sth, open&wait for "Save As" (positioning/sizing). Open invisible: Set the 2nd false to true 
	msgbox Please open Notepad
WinSend("!nhello1.txt!s","Speichern unter")										; Goto Filename-Control with !n (Germany only ?), save file (!s) under "hello1.txt"
Normal Send fails, because Notepad is not the active Window (it is in the background as supposed).
The follow-up Send might fail, because it drops in too quickly (hopefully not in Notepad, but you know what I mean :) )
guest3456
Posts: 3463
Joined: 09 Oct 2013, 10:31

Re: Save AHK-Operation: winSend, winClick and more

05 Jan 2018, 13:20

Hotte wrote: Example: Open Notepad empty and put it into the background.

Code: Select all

; Please adapt key and titles for English version: Speichern unter => Save As
if WinSend("Hello!du","Editor",true,"Speichern unter",false,100,100,500,600)	; Bring notepad into foreground, type sth, open&wait for "Save As" (positioning/sizing). Open invisible: Set the 2nd false to true 
	msgbox Please open Notepad
WinSend("!nhello1.txt!s","Speichern unter")										; Goto Filename-Control with !n (Germany only ?), save file (!s) under "hello1.txt"
Normal Send fails, because Notepad is not the active Window (it is in the background as supposed).
The follow-up Send might fail, because it drops in too quickly (hopefully not in Notepad, but you know what I mean :) )
thank you for your example, it makes sense. here it is for the english version of Notepad:

Code: Select all

if WinSend("Hello!fa","Untitled - Notepad",true,"Save As",false,100,100,500,600)
	msgbox Please open Notepad
WinSend("!nhello1.txt!s","Save As")

jsmain
Posts: 62
Joined: 07 Feb 2014, 08:21

Re: Save AHK-Operation: winSend, winClick and more

05 Jan 2018, 17:35

Hotte wrote:@jsmain
Thank you very much - very generous and excellent translation indeed! :bravo: :bravo: :bravo:
Well Thanks go to you for trying to assist me with my problem.

In order for me to understand it, it needed to be converted, so I did the conversion, and so it wouldn't go to waste, I thought I'd pass it along! Google did the translation, I just did the copy/paste! ;)

Return to “Scripts and Functions (v1)”

Who is online

Users browsing this forum: No registered users and 103 guests