Author Archive

Quicksort

Quicksort este un algoritm de sortare care se bazeaza pe principiul divide et impera, impartind lista care trebuie sortata in subliste mai usor de sortat.

 

#include <Array.au3>
 
Dim $Array[10] = [11,5,6,19,21,18,17,4,10,13]
 
_ArrayDisplay($Array,"Vector nesortat")
 
Quicksort($Array,0,9)
 
_ArrayDisplay($Array,"Vector sortat")
 
Func Quicksort(ByRef $Array,$First,$Last)
	Local $pivot, $i, $j, $temp
	If $First < $Last Then
		$pivot = $First
		$i = $First
		$j = $Last
		While ($i < $j)
			While ($Array[$i] <= $Array[$pivot]) And ($i < $Last)
				$i += 1
			WEnd
			While ($Array[$j] > $Array[$pivot])
				$j -= 1
			WEnd
			If ($i < $j) Then _ArraySwap($Array[$i],$Array[$j])
			_ArraySwap($Array[$pivot],$Array[$j])
			Quicksort($Array,$First,$j-1)
			Quicksort($Array,$j+1,$Last)
		WEnd
	EndIf
EndFunc

Bubble sort

Bubble sort este un algoritm de sortare care consta in parcurgerea unui vector si schimbarea a doua elemente adiacente daca valoarea elementului curent este mai mare decat valoarea elementului urmator. Operatia se repeta pana cand vectorul este sortat in intregime. La fiecare parcurgere a vectorului elementul cu valoarea cea mai mare ajunge ultimul in vector.

 

Sa presupunem ca avem urmatorul vector cu 10 elemente:

Dim $Array[10]
 
$Array[0] = 87
$Array[1] = 24
$Array[2] = 11
$Array[3] = 68
$Array[4] = 42
$Array[5] = 9
$Array[6] = 30
$Array[7] = 100
$Array[8] = 15
$Array[9] = 76

 

Implementarea unei functii care efectueaza o sortare folosind acest algoritm, in AutoIt, poate fi cea de mai jos:

Func BubbleSort(ByRef $aArray)
	For $i = UBound($aArray)-1 To 1 Step -1
		For $j = 1 To $i
			If ($aArray[$j-1] > $aArray[$j]) Then
				_ArraySwap($aArray[$j-1],$aArray[$j])
			EndIf
		Next
	Next
EndFunc

Nota: functia _ArraySwap este definita in Array.au3

 

Avand in vedere vectorul de mai sus, o prima trecere prin vector executand schimbari intre elementele adiacente, poate fi schitata ca in tabelul de mai jos. Cu culoarea rosu sunt reprezentate schimbarile de valori in vector iar cu albastru am reprezentat perechi adiacente care nu necesita schimbare de valori.

87

24

11

68

42

9

30

100

15

76

24

87

11

68

42

9

30

100

15

76

24

11

87

68

42

9

30

100

15

76

24

11

68

87

42

9

30

100

15

76

24

11

68

42

87

9

30

100

15

76

24

11

68

42

9

87

30

100

15

76

24

11

68

42

9

30

87

100

15

76

24

11

68

42

9

30

87

100

15

76

24

11

68

42

9

30

87

15

100

76

24

11

68

42

9

30

87

15

76

100

Se poate observa ca la finalul primei treceri prin vector, valoarea maxima ajunge pe ultima pozitie. Analog se executa treceri prin vector executand schimbari de valori, la fiecare trecere valoarea maxima ajunge in pozitie terminala (la fiecare trecere prin vector, numarul de pasi in vector se decrementeaza – plecand de la premisa ca pe ultima pozitie ajunge totdeauna valoarea maxima, nu mai este necesar ca vectorul sa fie parcurs in intregime).

Pentru o exemplificare mai buna a operatiilor efectuate de acest algoritm, urmariti animatia de mai jos:

Un exemplu de utilizare a acestei functii:

#include <Array.au3> 
 
Dim $Array[10]
 
$Array[0] = 87
$Array[1] = 24
$Array[2] = 11
$Array[3] = 68
$Array[4] = 42
$Array[5] = 9
$Array[6] = 30
$Array[7] = 100
$Array[8] = 15
$Array[9] = 76
 
_ArrayDisplay($Array,"Vector nesortat")
BubbleSort($Array)
_ArrayDisplay($Array,"Vector sortat")
 
Func BubbleSort(ByRef $aArray)
	For $i = UBound($aArray)-1 To 1 Step -1
		For $j = 1 To $i
			If ($aArray[$j-1] > $aArray[$j]) Then
				_ArraySwap($aArray[$j-1],$aArray[$j])
			EndIf
		Next
	Next
EndFunc

Accesarea Gmail

In unele cazuri veti dori sa verificati cat mai repede cu putinta daca aveti emailuri necitite, folosind serviciile Gmail. In acest tutorial voi prezenta doua metode pentru a realiza acest lucru.

 
1. Folosind functiile IE
 
Pentru inceput avem nevoie de functiile IE si cele pentru managementul sirurilor de caractere.

#include <IE.au3>
#include <String.au3>
#include <Array.au3> ;doar pentru a afisa rezultatul

 
Apoi vom declara doua variabile care contin datele de conectare:

$sEmail = '[email protected]'
$sPasswd = 'parola'

Nota: modificati continutul cu date reale de conectare
 
Cream un obiect(instanta) InternetExplorer:

$oIE = _IECreate('https://mail.google.com/',0,0)

Ultimii parametri indica faptul ca nu se ataseaza unei ferestre existente si nu este o fereastra vizibila.
 
Obtinem referintele pentru form-ul de logare si pentru fiecare element necesar pentru conectare (email, parola, butonul SignIn):

$oForm = _IEFormGetObjByName($oIE,'gaia_loginform')
$oEmail = _IEFormElementGetObjByName($oForm,'Email')
$oPasswd = _IEFormElementGetObjByName($oForm,'Passwd')
$oSignIn = _IEFormElementGetObjByName($oForm,'signIn')

 
Setam datele de logare si apasam butonul pentru conectare, apoi asteptam incarcarea paginii noi:

_IEFormElementSetValue($oEmail,$sEmail)
_IEFormElementSetValue($oPasswd,$sPasswd)
_IEAction($oSignIn,'click')
_IELoadWait($oIE)

 
Obtinem sursa paginii:

$sHTML = _IEBodyReadHTML($oIE)

 
Mai ramane sa ne deconectam si sa distrugem obiectul creat:

_IENavigate($oIE,'https://mail.google.com/mail/?logout&hl=en')
_IEQuit($oIE)

 
Ajunsi in aceasta faza am terminat cu preluarea datelor, mai ramane sa gasim continutul dorit. Pentru acest lucru am creat functia GetMessages, avand ca parametru sursa paginii obtinuta anterior:

$Messages = GetMessages($sHTML)
_ArrayDisplay($Messages)

Fiind un tutorial, pentru a pastra lucrurile cat mai simple, am ales sa afisam rezultatul sub forma matriceala dar pentru a arata mai bine se poate crea o interfata grafica.
 
Functia GetMessages:

Func GetMessages($sHTML)
	Local $aMsg = _StringBetween($sHTML,'<SPAN dir=ltr>','e-mail options')
	If IsArray($aMsg) Then
		Local $Max = UBound($aMsg)
		Local $Messages[1][2]
		$Messages[0][0] = 0
		For $Index = 0 To $Max-1
			Local $Info = _StringBetween($aMsg[$Index],'<B>','</B>')
			If Not @error Then
				$Messages[0][0] += 1
				ReDim $Messages[$Messages[0][0]+1][2]
				$Messages[$Messages[0][0]][0] = $Info[0]
				$Messages[$Messages[0][0]][1] = $Info[1]
			EndIf
		Next
		Return $Messages
	EndIf
	Return False
EndFunc

In prima linie obtinem intr-un vector niste portiuni din codul sursa, specifice pentru fiecare mesaj. Daca au fost gasite astfel de portiuni atunci variabila $aMsg este cu siguranta un vector.
Variabila $Max contine numarul total de mesaje (citite si necitite).
Variabila $Messages o sa contina rezultatul functiei (este o matrice bidimensionala). Initial se creaza doar un index in matrice (inca nu stim cate mesaje sunt necitite), iar pe parcurs vom mai adauga indecsi. $Messages[0][0] este indexul la care stocam numarul de mesaje (emailuri) necitite, valoarea initiala este 0.
Apoi verificam intr-o bucla For…Next, pentru fiecare portiune de cod HTML specific unui email, daca acesta este scris cu text care are atributul bold(specific unui email necitit). Daca se gasesc asemenea texte in portiunea de cod, acestEa reprezinta numele celui care a trimis emailul si subiectul acestuia. Pentru fiecare caz favorabil, se incrementeaza numarul mesajelor necitite, se redimensioneaza matricea care contine rezultatul final si se pun datele obtinute in matrice.
In final se returneaza matricea care contine rezultatul sau valoarea booleana False in caz de eroare.
 
Daca asamblati portiunile de cod de mai sus, obtineti urmatorul script:

#include <IE.au3>
#include <String.au3>
#include <Array.au3> ;doar pentru a afisa rezultatul
 
$sEmail = '[email protected]'
$sPasswd = 'parola'
 
$oIE = _IECreate('https://mail.google.com/',0,0)
$oForm = _IEFormGetObjByName($oIE,'gaia_loginform')
$oEmail = _IEFormElementGetObjByName($oForm,'Email')
$oPasswd = _IEFormElementGetObjByName($oForm,'Passwd')
$oSignIn = _IEFormElementGetObjByName($oForm,'signIn')
_IEFormElementSetValue($oEmail,$sEmail)
_IEFormElementSetValue($oPasswd,$sPasswd)
_IEAction($oSignIn,'click')
_IELoadWait($oIE)
$sHTML = _IEBodyReadHTML($oIE)
_IENavigate($oIE,'https://mail.google.com/mail/?logout&hl=en')
_IEQuit($oIE)
 
$Messages = GetMessages($sHTML)
_ArrayDisplay($Messages)
 
Func GetMessages($sHTML)
	Local $aMsg = _StringBetween($sHTML,'<SPAN dir=ltr>','e-mail options')
	If IsArray($aMsg) Then
		Local $Max = UBound($aMsg)
		Local $Messages[1][2]
		$Messages[0][0] = 0
		For $Index = 0 To $Max-1
			Local $Info = _StringBetween($aMsg[$Index],'<B>','</B>')
			If Not @error Then
				$Messages[0][0] += 1
				ReDim $Messages[$Messages[0][0]+1][2]
				$Messages[$Messages[0][0]][0] = $Info[0]
				$Messages[$Messages[0][0]][1] = $Info[1]
			EndIf
		Next
		Return $Messages
	EndIf
	Return False
EndFunc

 
 
2. Folosind un obiect WinHTTPRequest si Gmail feed atom
 
Si in acest caz vom avea nevoie de functii pentru managementul sirurilor de caractere, deci vom avea nevoie de:

#include <String.au3>
#include <Array.au3> ;doar pentru a afisa rezultatul

 
Apoi vom declara doua variabile care contin datele de conectare:

$sEmail = '[email protected]'
$sPasswd = 'parola'

Nota: modificati continutul cu date reale de conectare
 
Cream un obiect WinHTTPRequest, initiem o cerere GET, setam credentialele si trimitem cererea. Apoi asteptam un raspuns.

$oHTTP = ObjCreate('WinHTTP.WinHTTPRequest.5.1')
With $oHTTP
	.Open('GET','https://gmail.google.com/gmail/feed/atom',False)
	.SetCredentials($sEmail,$sPasswd,0)
	.Send()
EndWith
$sXML = $oHTTP.ResponseText

 
In aceasta faza avem informatiile necesare, mai trebuie doar sa le aranjam intr-o forma utilizabila. Pentru acest lucru am scris functia GetMessages, avand ca parametru o variabila cu datele obtinute anterior. In felul urmator se apeleaza si afiseaza rezultatul functiei(sub forma matriceala):

$Messages = GetMessages($sXML)
_ArrayDisplay($Messages)

 
Functia GetMessages:

Func GetMessages($sXML)
	Local $New = _StringBetween($sXML,'<fullcount>','</fullcount>')
	If $New[0] <> 0 Then
		Local $Messages[$New[0]+1][2]
		$Messages[0][0] = $New[0]
		Local $Entry = _StringBetween($sXML,'<entry>','</entry>')
		For $Index = 0 To $New[0]-1
			Local $sName = _StringBetween($Entry[$Index],'<name>','</name>')
			Local $sTitle = _StringBetween($Entry[$Index],'<title>','</title>')
			$Messages[$Index+1][0] = $sName[0]
			$Messages[$Index+1][1] = $sTitle[0]
		Next
		Return $Messages
	EndIf
	Return False
EndFunc

In prima linie se obitne numarul de emailuri necitite. Daca acest numar este diferit de 0 se trece la procesarea acestora.
Se creaza o matrice bidimensionala care sa stocheze rezultatul functiei.
La indexul [0][0] se stocheaza numarul total de emailuri necitite.
In urmatoarea linie se obtine un vector cu date despre fiecare email.
Apoi intr-o bucla For…Next se obtin doar datele care ne intereseaza(numele si subiectul mesajului) si se stocheaza in matricea cu rezultatele finale.
La iesirea din bucla functia returneaza matricea cu emailuri necitite sau in caz de eroare se returneaza valoarea booleana False
 
Daca asamblati portiunile de cod scrise anterior, obtineti urmatorul script:

#include <String.au3>
#include <Array.au3>
 
$sEmail = '[email protected]'
$sPasswd = 'parola'
 
$oHTTP = ObjCreate('WinHTTP.WinHTTPRequest.5.1')
With $oHTTP
	.Open('GET','https://gmail.google.com/gmail/feed/atom',False)
	.SetCredentials($sEmail,$sPasswd,0)
	.Send()
EndWith
$sXML = $oHTTP.ResponseText
 
$Messages = GetMessages($sXML)
_ArrayDisplay($Messages)
 
 
Func GetMessages($sXML)
	Local $New = _StringBetween($sXML,'<fullcount>','</fullcount>')
	If $New[0] <> 0 Then
		Local $Messages[$New[0]+1][2]
		$Messages[0][0] = $New[0]
		Local $Entry = _StringBetween($sXML,'<entry>','</entry>')
		For $Index = 0 To $New[0]-1
			Local $sName = _StringBetween($Entry[$Index],'<name>','</name>')
			Local $sTitle = _StringBetween($Entry[$Index],'<title>','</title>')
			$Messages[$Index+1][0] = $sName[0]
			$Messages[$Index+1][1] = $sTitle[0]
		Next
		Return $Messages
	EndIf
	Return False
EndFunc

GDI+ 2D Game Demo

Urmatorul tutorial a fost gandit pentru incepatori, pentru a intelege cum se creaza un joc simplu 2D, folosind GDI+. In acest tutorial nu veti intalni optimizari, trebuie sa tineti cont ca este un joc demonstrativ.

De preferat este sa fiti familiarizati cu tutorialele Interfata personalizata cu WinAPI, Double Buffering si Coliziunea Obiectelor pentru o mai buna intelegere a acestui tutorial.
 
Pentru inceput o sa avem nevoie de doua fisiere antet pentru a putea accesa functiile GDI+ si cele pentru managementul sunetelor.

#include <GDIPlus.au3>
#include <Sound.au3>

Mai avem nevoie de cateva variabile cu scop global, pe care le vom folosi in diverse functii:

Global $hMain, $hWall, $hPlayer, $hMob, $hGate, $hGraphics, $hClone, $hBackBuffer
Global $GameOver = False, $GameFinish = False, $Pause = False, $Sound

$hMain este handle-ul ferestrei principale
$hWall este handle-ul imaginii pentru zid
$hPlayer este handle-ul imaginii pentru jucator
$hMob este handle-ul imaginii pentru mob
$hGate este handle-ul imaginii pentru poarta
$hGraphics este handle-ul unui obiect Graphics (suprafata de desenare)
$hClone este handle-ul unei obiect Bitmap (portiunea in care se desfasoara actiunea jocului)
$hBackBuffer este handle-ul unui obiect Graphics (buffer in memorie pentru operatiile de desenare)
$GameOver este o variabila booleana care indica daca jucatorul a pierdut (mancat de mob)
$GameFinish este o variabila booleana care indica daca jucatorul a terminat jocul (a intrat pe poarta)
$Pause este o variabila booleana care indica daca jocul este suspendat(pauza) pentru o perioada de timp
$Sound contine sound ID-ul melodiei de fundal
 
Cream cele 3 obiecte care vor interactiona in joc:

Global $ObjPlayer = CreateObject(30,30,30,30,30,390,30,420)
Global $ObjMob = CreateObject(210,210,30,30,30,390,30,420)
Global $ObjGate = CreateObject(390,420,30,30,30,390,30,420)

 
Incarcam resursele grafice (directorul curent\Gfx):

_GDIPlus_Startup()
$hWall = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\Gfx\Wall.bmp")
$hPlayer = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\Gfx\Player.bmp")
$hMob = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\Gfx\Mob.bmp")
$hGate = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\Gfx\Gate.bmp")

 
Cream fereastra principala, desenam o imagine de fundal si cream butoanele de minimizare si inchidere a programului:

$hMain = GUICreate("GDI+ 2D Game Demo",458,505,-1,-1,0x80000000,0x00000008)
$hBackground = GUICtrlCreatePic(@ScriptDir & "\Gfx\Background.bmp",0,0,458,505)
$hLabel = GUICtrlCreateLabel("GDI+ 2D Game Demo",5,2,150,18)
$hMinimize = GUICtrlCreatePic(@ScriptDir & "\Gfx\Minimize.bmp",415,0,20,20)
$hClose = GUICtrlCreatePic(@ScriptDir & "\Gfx\Close.bmp",435,0,20,20)
GUICtrlSetColor($hLabel,0xFFFFFF)
GUICtrlSetBkColor($hLabel,0x000000)
GUICtrlSetFont($hLabel,10,600,0,"Garamond")
GUICtrlSetState($hBackground,128)
GUISetState(@SW_SHOW,$hMain)

Fereastra principala nu are bara de titlu si butoane de sistem (stilul $WS_POPUP), fapt pentru care cream manual un control Pic pentru imaginea de fundal, un control Label pentru titlu si alte doua controale Pic pentru butoanele de minimizare si inchidere. Pentru controlul care pastreaza titlul se seteaza culoarea textului, a fundalului si fontul, iar controlul care pastreaza imaginea de fundal este dezactivat. In final se seteaza fereastra principala ca fiind vizibila.
 
Urmatorul lucru de care ne vom ocupa este sunetul de fundal:

SoundSetWaveVolume(50)
$Sound = _SoundOpen(@ScriptDir & "\Snd\Medley.wav")
_SoundPlay($Sound)

Initial setam volumul la 50% (depinde de performantele audio de care dispuneti, puteti modifica valoare dupa preferinta), deschidem fisierul care contine melodia de fundal si pornim melodia.
 
In continuare ne vom ocupa de crearea suprafetelor de desenare:

$hGraphics = _GDIPlus_GraphicsCreateFromHWND($hMain)
$hBitmap = _GDIPlus_BitmapCreateFromGraphics(458,505,$hGraphics)
$hClone = _GDIPlus_BitmapCloneArea($hBitmap,4,21,450,480,$GDIP_PXF24RGB)
$hBackBuffer = _GDIPlus_ImageGetGraphicsContext($hClone)

Am explicat mai sus ce inseamna fiecare, cu exceptia $hBitmap care este handle-ul unui obiect Bitmap specific pentru intreaga fereastra, dar in cazul nostru nu vrem sa redesenam peste bara de titlu, marginile ferestrei si butoanele de minimizare si inchidere. De aceea suprafata activa va fi cea in care se desfasoara jocul, implicit portiunea clonata din acest $hBitmap.
 
Trebuie sa ne gandim si la cazul in care fereastra este restaurata dupa o minimizare sau daca fereastra este scoasa in afara ecranului si apoi readusa pe ecran, etc. Toate aceste evenimente vor distruge ce a fost desenat cu GDI+. In consecinta, cand unul din aceste evenimente are loc imaginea din buffer trebuie redesenata pe ecran. Pentru a apela functia de redesenare cand aceste evenimente au loc, folosim urmatoarele doua linii:

GUIRegisterMsg(0x85,"REPAINT")
GUIRegisterMsg(0x0F,"REPAINT")

Prima linie apeleaza functia REPAINT cand se intercepteaza mesajul WM_NCPAINT. A doua linie apeleaza functia REPAINT cand se intercepteaza mesajul WM_PAINT.
 
Urmeaza liniile de cod care ii permit userului sa miste jucatorul, sa puna pauza si pe ultima linie se inregistreaza apelul functiei MoveMobRandom la fiecare secunda, pentru a misca mobul:

HotKeySet("{UP}","MoveUp")
HotKeySet("{DOWN}","MoveDown")
HotKeySet("{LEFT}","MoveLeft")
HotKeySet("{RIGHT}","MoveRight")
HotKeySet("{PAUSE}","Pause")
AdlibRegister("MoveMobRandom",1000)

 
Apoi urmeaza bucla principala:

Do
	Switch GUIGetMsg()
		Case -7
			_SendMessage($hMain,0x0112,0xF012,0)
		Case $hMinimize
			GUISetState(@SW_MINIMIZE,$hMain)
		Case $hClose
			ExitLoop
	EndSwitch
	If (_SoundStatus($Sound) <> "playing") And (Not $Pause) Then _SoundPlay($Sound)
	_GDIPlus_GraphicsClear($hBackBuffer,0xFF000000)
	For $X = 0 To 450 Step 30
		_GDIPlus_GraphicsDrawImage($hBackBuffer,$hWall,$X,0)
		_GDIPlus_GraphicsDrawImage($hBackBuffer,$hWall,$X,450)
	Next
	For $Y = 0 To 480 Step 30
		_GDIPlus_GraphicsDrawImage($hBackBuffer,$hWall,0,$Y)
		_GDIPlus_GraphicsDrawImage($hBackBuffer,$hWall,420,$Y)
	Next
	If ObjectsOverlap($ObjPlayer,$ObjMob) Then
		AdlibUnRegister("MoveMobRandom")
		$GameOver = True
	EndIf
	If ObjectsOverlap($ObjPlayer,$ObjGate) Then
		AdlibUnRegister("MoveMobRandom")
		$GameFinish = True
	EndIf
	If ObjectsOverlap($ObjMob,$ObjGate) Then
		UpdateObject($ObjMob,$ObjMob[0]-30,$ObjMob[1])
	EndIf
	_GDIPlus_GraphicsDrawImage($hBackBuffer,$hPlayer,$ObjPlayer[0],$ObjPlayer[1])
	_GDIPlus_GraphicsDrawImage($hBackBuffer,$hMob,$ObjMob[0],$ObjMob[1])
	_GDIPlus_GraphicsDrawImage($hBackBuffer,$hGate,$ObjGate[0],$ObjGate[1])
	_GDIPlus_GraphicsDrawImage($hGraphics,$hClone,4,21)
	Sleep(10)
Until $GameOver Or $GameFinish

Codul sursa continut in interiorul buclei principala poate fi impartit in 6 parti:
1. Expresia conditionala care gestioneaza mesajele interceptate de fereastra pincipala (Primary Down, Minimize si Close)
2. Linia in care se testeaza daca melodia de fundal continua sa ruleze, in caz contrar (daca nu este in modul pauza) melodia este rulata iar
3. Linia in care se curata bufferul din memorie, in care se deseneaza
4. Cele doua bucle For…Next, in care se deseneaza zidurile marginale in buffer
5. Testarea celor 3 posibile coliziuni: jucator-mob, jucator-poarta sau mob-poarta. In cazul coliziunii jucator-mob, variabila $GameOver este setata ca True, bucla va rula pentru ultima data (pentru desenare). In cazul coliziunii jucator-poarta, variabila $GameFinish este setata ca True, bucla va rula pentru ultima data (pentru desenare). In cazul coliziunii mob-poarta (am vrut ca acest lucru sa fie interzis), pozitia mobului este reactualizata in partea stanga a portii.
6. Desenarea jucatorului, mobului si a portii in buffer, apoi copierea bufferului pe suprafata de desenare.

Iesirea din bucla are loc in 3 cazuri: daca userul apasa butonul Close(x), in cazul in care jucatorul este mancat de mob sau in cazul in care jucatorul intra pe poarta.
 
La iesirea din bucla principala se opreste melodia de fundal si se inchide fisierul care contine melodia:

_SoundStop($Sound)
_SoundClose($Sound)

 
Urmeaza partea in care este tratat finalul jocului (cauza):

If $GameOver Then
	$Sound = _SoundOpen(@ScriptDir & "\Snd\Over.wav")
	TrayTip("Game Over","Mancat de mob",1)
ElseIf $GameFinish Then
	TrayTip("Game Finish","Ajuns la poarta",1)
	$Sound = _SoundOpen(@ScriptDir & "\Snd\Finish.wav")
Else
	$Sound = _SoundOpen(@ScriptDir & "\Snd\Exit.wav")
	TrayTip("Exit","Userul a inchis jocul",1)
EndIf
_SoundPlay($Sound)
Sleep(5000)

Se testeaza daca iesirea din bucla principala s-a datorat faptului ca jucatorul a fost mancat de mob. Daca acesta este motivul se deschide si reda o melodie care indica acest lucru, plus un mesaj vizual care persista 5 secunde.
Daca motivul pentru iesirea din bucla principala s-a datorat faptului ca jucatorul a intrat pe poarta, la fel se deschide si reda o melodie care indica acest lucru, plus un mesaj vizual care persista 5 secunde.
Pentru oricare alt caz (incluzand cazul in care userul inchide aplicatia) se deschide si reda o melodie care indica acest lucru, plus un mesaj vizual care persista 5 secunde.
 
Mai trebuie doar oprita melodia care este redata (pentru unul din cazurile de mai sus) si inchis fisierul care contine melodia.

_SoundStop($Sound)
_SoundClose($Sound)

 
Apoi eliberate resursele folosite:

_GDIPlus_ImageDispose($hGate)
_GDIPlus_ImageDispose($hMob)
_GDIPlus_ImageDispose($hPlayer)
_GDIPlus_ImageDispose($hWall)
_GDIPlus_BitmapDispose($hClone)
_GDIPlus_GraphicsDispose($hBackBuffer)
_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_Shutdown()

 
Functiile apelate pentru miscarea jucatorului:

Func MoveUp()
	UpdateObject($ObjPlayer,$ObjPlayer[0],$ObjPlayer[1]-30)
EndFunc
 
Func MoveDown()
	UpdateObject($ObjPlayer,$ObjPlayer[0],$ObjPlayer[1]+30)
EndFunc
 
Func MoveLeft()
	UpdateObject($ObjPlayer,$ObjPlayer[0]-30,$ObjPlayer[1])
EndFunc
 
Func MoveRight()
	UpdateObject($ObjPlayer,$ObjPlayer[0]+30,$ObjPlayer[1])
EndFunc

In fond, pentru fiecare directie noua este reactualizata pozitia obiectului asociat jucatorului, cu 30 pixeli, plus sau minus.
 
Functia care misca mobul:

Func MoveMobRandom()
	Switch Random(1,4,1)
		Case 1
			UpdateObject($ObjMob,$ObjMob[0],$ObjMob[1]-30)
		Case 2
			UpdateObject($ObjMob,$ObjMob[0],$ObjMob[1]+30)
		Case 3
			UpdateObject($ObjMob,$ObjMob[0]-30,$ObjMob[1])
		Case 4
			UpdateObject($ObjMob,$ObjMob[0]+30,$ObjMob[1])
	EndSwitch
EndFunc

Se genereaza un numar aleator intre 1-4, fiecare corespunzator unei directii. Pentru fiecare directie se reactualizeaza pozitia obiectului asociat mobului cu 30 pixeli, plus sau minus.
 
Functia care trateaza suspendarea/redarea actiunilor:

Func Pause()
	$Pause = Not $Pause
	If $Pause Then
		AdlibUnRegister("MoveMobRandom")
		HotKeySet("{UP}")
		HotKeySet("{DOWN}")
		HotKeySet("{LEFT}")
		HotKeySet("{RIGHT}")
		_SoundPause($Sound)
	Else
		AdlibRegister("MoveMobRandom",1000)
		HotKeySet("{UP}","MoveUp")
		HotKeySet("{DOWN}","MoveDown")
		HotKeySet("{LEFT}","MoveLeft")
		HotKeySet("{RIGHT}","MoveRight")
		_SoundResume($Sound)
	EndIf
EndFunc

In prima linie se trece din starea intial in alta stare (True->False sau False->True).
Daca valoarea curenta este True(pauza) atunci se dezactiveaza apelarea functiei care misca mobul, se dezactiveaza tastele asociate pentru miscarea jucatorului si melodia de fundal este pusa pe pauza.
Daca valoarea curenta este False(iesire din modul pauza) se reactiveaza apelarea functiei care misca mobul, se reactiveaza tastele asociate pentru miscarea jucatorului si melodia de fundal este reluata.
 
Functia pentru redesenare (WM_PAINT si WM_NCPAINT):

Func REPAINT($hWnd,$msg,$wParam,$lParam)
    _GDIPlus_GraphicsDrawImage($hGraphics,$hClone,4,21)
    Return _WinAPI_DefWindowProc($hWnd,$msg,$wParam,$lParam)
EndFunc

Se copiaza bufferul din memorie pe suprafata de desenare.
 
Functiile pentru lucrul cu obiecte (identice cu cele descrise in tutorialul Coliziunea Obiectelor):

Func CreateObject($X,$Y,$W,$H,$MinX,$MaxX,$MinY,$MaxY)
	Local $Object[8] = [$X,$Y,$W,$H,$MinX,$MaxX,$MinY,$MaxY]
	Return $Object
EndFunc
 
Func UpdateObject(ByRef $Obj,$X,$Y)
	If $X < $Obj[4] Then $X = $Obj[4]
   	If $X > $Obj[5] Then $X = $Obj[5]
	If $Y < $Obj[6] Then $Y = $Obj[6]
   	If $Y > $Obj[7] Then $Y = $Obj[7]
	$Obj[0] = $X
	$Obj[1] = $Y
EndFunc
 
Func ObjectsOverlap($Obj1,$Obj2)
    Local $SX = Abs($Obj2[0] - $Obj1[0]) + $Obj2[2]
    Local $SY = Abs($Obj2[1] - $Obj1[1]) + $Obj2[3]
    Return ($SX < $Obj1[2] + $Obj2[2] And $SY < $Obj1[3] + $Obj2[3])
EndFunc

 
 
Daca asamblati toate portiunile de cod sursa de mai sus, scriptul arata asa:

#include <GDIPlus.au3>
#include <Sound.au3>
 
Global $hMain, $hWall, $hPlayer, $hMob, $hGate, $hGraphics, $hClone, $hBackBuffer
Global $GameOver = False, $GameFinish = False, $Pause = False, $Sound
 
Global $ObjPlayer = CreateObject(30,30,30,30,30,390,30,420)
Global $ObjMob = CreateObject(210,210,30,30,30,390,30,420)
Global $ObjGate = CreateObject(390,420,30,30,30,390,30,420)
 
_GDIPlus_Startup()
$hWall = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\Gfx\Wall.bmp")
$hPlayer = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\Gfx\Player.bmp")
$hMob = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\Gfx\Mob.bmp")
$hGate = _GDIPlus_ImageLoadFromFile(@ScriptDir & "\Gfx\Gate.bmp")
 
$hMain = GUICreate("GDI+ 2D Game Demo",458,505,-1,-1,0x80000000,0x00000008)
$hBackground = GUICtrlCreatePic(@ScriptDir & "\Gfx\Background.bmp",0,0,458,505)
$hLabel = GUICtrlCreateLabel("GDI+ 2D Game Demo",5,2,150,18)
$hMinimize = GUICtrlCreatePic(@ScriptDir & "\Gfx\Minimize.bmp",415,0,20,20)
$hClose = GUICtrlCreatePic(@ScriptDir & "\Gfx\Close.bmp",435,0,20,20)
GUICtrlSetColor($hLabel,0xFFFFFF)
GUICtrlSetBkColor($hLabel,0x000000)
GUICtrlSetFont($hLabel,10,600,0,"Garamond")
GUICtrlSetState($hBackground,128)
GUISetState(@SW_SHOW,$hMain)
 
SoundSetWaveVolume(50)
$Sound = _SoundOpen(@ScriptDir & "\Snd\Medley.wav")
_SoundPlay($Sound)
 
$hGraphics = _GDIPlus_GraphicsCreateFromHWND($hMain)
$hBitmap = _GDIPlus_BitmapCreateFromGraphics(458,505,$hGraphics)
$hClone = _GDIPlus_BitmapCloneArea($hBitmap,4,21,450,480,$GDIP_PXF24RGB)
$hBackBuffer = _GDIPlus_ImageGetGraphicsContext($hClone)
 
GUIRegisterMsg(0x85,"REPAINT")
GUIRegisterMsg(0x0F,"REPAINT")
 
HotKeySet("{UP}","MoveUp")
HotKeySet("{DOWN}","MoveDown")
HotKeySet("{LEFT}","MoveLeft")
HotKeySet("{RIGHT}","MoveRight")
HotKeySet("{PAUSE}","Pause")
AdlibRegister("MoveMobRandom",1000)
 
Do
	Switch GUIGetMsg()
		Case -7
			_SendMessage($hMain,0x0112,0xF012,0)
		Case $hMinimize
			GUISetState(@SW_MINIMIZE,$hMain)
		Case $hClose
			ExitLoop
	EndSwitch
	If (_SoundStatus($Sound) <> "playing") And (Not $Pause) Then _SoundPlay($Sound)
	_GDIPlus_GraphicsClear($hBackBuffer,0xFF000000)
	For $X = 0 To 450 Step 30
		_GDIPlus_GraphicsDrawImage($hBackBuffer,$hWall,$X,0)
		_GDIPlus_GraphicsDrawImage($hBackBuffer,$hWall,$X,450)
	Next
	For $Y = 0 To 480 Step 30
		_GDIPlus_GraphicsDrawImage($hBackBuffer,$hWall,0,$Y)
		_GDIPlus_GraphicsDrawImage($hBackBuffer,$hWall,420,$Y)
	Next
	If ObjectsOverlap($ObjPlayer,$ObjMob) Then
		AdlibUnRegister("MoveMobRandom")
		$GameOver = True
	EndIf
	If ObjectsOverlap($ObjPlayer,$ObjGate) Then
		AdlibUnRegister("MoveMobRandom")
		$GameFinish = True
	EndIf
	If ObjectsOverlap($ObjMob,$ObjGate) Then
		UpdateObject($ObjMob,$ObjMob[0]-30,$ObjMob[1])
	EndIf
	_GDIPlus_GraphicsDrawImage($hBackBuffer,$hPlayer,$ObjPlayer[0],$ObjPlayer[1])
	_GDIPlus_GraphicsDrawImage($hBackBuffer,$hMob,$ObjMob[0],$ObjMob[1])
	_GDIPlus_GraphicsDrawImage($hBackBuffer,$hGate,$ObjGate[0],$ObjGate[1])
	_GDIPlus_GraphicsDrawImage($hGraphics,$hClone,4,21)
	Sleep(10)
Until $GameOver Or $GameFinish
 
_SoundStop($Sound)
_SoundClose($Sound)
 
If $GameOver Then
	$Sound = _SoundOpen(@ScriptDir & "\Snd\Over.wav")
	TrayTip("Game Over","Mancat de mob",1)
ElseIf $GameFinish Then
	TrayTip("Game Finish","Ajuns la poarta",1)
	$Sound = _SoundOpen(@ScriptDir & "\Snd\Finish.wav")
Else
	$Sound = _SoundOpen(@ScriptDir & "\Snd\Exit.wav")
	TrayTip("Exit","Userul a inchis jocul",1)
EndIf
_SoundPlay($Sound)
Sleep(5000)
 
_SoundStop($Sound)
_SoundClose($Sound)
 
_GDIPlus_ImageDispose($hGate)
_GDIPlus_ImageDispose($hMob)
_GDIPlus_ImageDispose($hPlayer)
_GDIPlus_ImageDispose($hWall)
_GDIPlus_BitmapDispose($hClone)
_GDIPlus_GraphicsDispose($hBackBuffer)
_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_Shutdown()
 
Func MoveUp()
	UpdateObject($ObjPlayer,$ObjPlayer[0],$ObjPlayer[1]-30)
EndFunc
 
Func MoveDown()
	UpdateObject($ObjPlayer,$ObjPlayer[0],$ObjPlayer[1]+30)
EndFunc
 
Func MoveLeft()
	UpdateObject($ObjPlayer,$ObjPlayer[0]-30,$ObjPlayer[1])
EndFunc
 
Func MoveRight()
	UpdateObject($ObjPlayer,$ObjPlayer[0]+30,$ObjPlayer[1])
EndFunc
 
Func MoveMobRandom()
	Switch Random(1,4,1)
		Case 1
			UpdateObject($ObjMob,$ObjMob[0],$ObjMob[1]-30)
		Case 2
			UpdateObject($ObjMob,$ObjMob[0],$ObjMob[1]+30)
		Case 3
			UpdateObject($ObjMob,$ObjMob[0]-30,$ObjMob[1])
		Case 4
			UpdateObject($ObjMob,$ObjMob[0]+30,$ObjMob[1])
	EndSwitch
EndFunc
 
Func Pause()
	$Pause = Not $Pause
	If $Pause Then
		AdlibUnRegister("MoveMobRandom")
		HotKeySet("{UP}")
		HotKeySet("{DOWN}")
		HotKeySet("{LEFT}")
		HotKeySet("{RIGHT}")
		_SoundPause($Sound)
	Else
		AdlibRegister("MoveMobRandom",1000)
		HotKeySet("{UP}","MoveUp")
		HotKeySet("{DOWN}","MoveDown")
		HotKeySet("{LEFT}","MoveLeft")
		HotKeySet("{RIGHT}","MoveRight")
		_SoundResume($Sound)
	EndIf
EndFunc
 
Func REPAINT($hWnd,$msg,$wParam,$lParam)
    _GDIPlus_GraphicsDrawImage($hGraphics,$hClone,4,21)
    Return _WinAPI_DefWindowProc($hWnd,$msg,$wParam,$lParam)
EndFunc
 
Func CreateObject($X,$Y,$W,$H,$MinX,$MaxX,$MinY,$MaxY)
	Local $Object[8] = [$X,$Y,$W,$H,$MinX,$MaxX,$MinY,$MaxY]
	Return $Object
EndFunc
 
Func UpdateObject(ByRef $Obj,$X,$Y)
	If $X < $Obj[4] Then $X = $Obj[4]
   	If $X > $Obj[5] Then $X = $Obj[5]
	If $Y < $Obj[6] Then $Y = $Obj[6]
   	If $Y > $Obj[7] Then $Y = $Obj[7]
	$Obj[0] = $X
	$Obj[1] = $Y
EndFunc
 
Func ObjectsOverlap($Obj1,$Obj2)
    Local $SX = Abs($Obj2[0] - $Obj1[0]) + $Obj2[2]
    Local $SY = Abs($Obj2[1] - $Obj1[1]) + $Obj2[3]
    Return ($SX < $Obj1[2] + $Obj2[2] And $SY < $Obj1[3] + $Obj2[3])
EndFunc

 
Daca rulati scriptul, fereastra care va aparea o sa fie asemanatoare cu cea de mai jos:

 
Nota: multumiri pentru sunetul de fundal lui Pippo Noviello (aka Kaminari3).
 
Puteti descarca scriptul, resursele si o versiune compilata de aici.

Coliziunea obiectelor

In special pentru pasionatii de jocuri, este important sa stiti cand doua obiecte se lovesc reciproc. In acest tutorial vom aborda forme simple ale obiectelor si vom invata sa testam daca exista o coliziune intre acestea.

 

Ca un prim exemplu vom lua doua obiecte dreptunghiulare (sau patrate). Pentru simulare vom folosi functii GDI+, in concluzie prima linie din script este:

#include <GDIPlus.au3>

Apoi vom crea o fereastra pentru simulare:

$hMain = GUICreate("Exemplu",200,200)
GUISetState(@SW_SHOW,$hMain)

Pentru aceasta simulare avem nevoie de trei functii:

Func CreateObject($X,$Y,$W,$H,$MinX,$MaxX,$MinY,$MaxY)
	Local $Object[8] = [$X,$Y,$W,$H,$MinX,$MaxX,$MinY,$MaxY]
	Return $Object
EndFunc

Functia CreateObject creaza un array cu caracteristicile unui obiect (coordonatele punctului de la care incepe obiectul, latimea, inaltimea si coorodonatele minime si maxime pentru X si Y pe care se poate misca obiectul).

Poate imaginea de mai jos este mai sugestiva:

Daca consideram patratul negru (fereastra 200×200), pentru MaxX = 160 si MaxY = 160, in coltul dreapta-jos ramane exact spatiul de desenare pentru un patrat cu latimea 40 si inaltimea 40. Deci MaxX = latimea ferestrei – latimea patratului si MaxY = inaltimea ferestrei – inaltimea patratului.

 

Func UpdateObject(ByRef $Obj,$X,$Y)
	If $X < $Obj[4] Then $X = $Obj[4]
   	If $X > $Obj[5] Then $X = $Obj[5]
	If $Y < $Obj[6] Then $Y = $Obj[6]
   	If $Y > $Obj[7] Then $Y = $Obj[7]
	$Obj[0] = $X
	$Obj[1] = $Y
EndFunc

Functia UpdateObject o vom folosi pentru a seta o noua pozitie obiectului. Primele 4 conditii testeaza noua pozitie sa nu fie in afara limitelor impuse iar ultimele doua seteaza pozitia.

 

Func ObjectsOverlap($Obj1,$Obj2)
    Local $SX = Abs($Obj2[0] - $Obj1[0]) + $Obj2[2]
    Local $SY = Abs($Obj2[1] - $Obj1[1]) + $Obj2[3]
    Return ($SX < $Obj1[2] + $Obj2[2] And $SY < $Obj1[3] + $Obj2[3])
EndFunc

Functia ObjectOverlap verifica daca cele doua obiecte au ajuns in contact. Imaginea de mai jos este sugestiva:

Pentru oricare doua obiecte, daca valoarea SX este mai mica decat suma latimiilor obiectelor atunci cele doua obiecte se suprapun pe verticala. Daca valoarea SY este mai mica decat suma inaltimiilor obiectelor atunci cele doua obiecte se suprapun pe orizontala. Pentru a  determina coliziunea dintre doua obiecte, trebuie indeplinite ambele conditii.

 

Cream suprafata de desenare, bufferul in memorie pentru Double Buffering si doua obiecte Brush cu care desenam patratele.

_GDIPlus_Startup()
$hGraphics = _GDIPlus_GraphicsCreateFromHWND($hMain)
$hBitmap = _GDIPlus_BitmapCreateFromGraphics(200,200,$hGraphics)
$hBackBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
$hBrush1 = _GDIPlus_BrushCreateSolid(0xFFFF0000)
$hBrush2 = _GDIPlus_BrushCreateSolid(0xFF00FF00)

Inainte de a incepe verificarea coliziunii intr-o bucla, trebuie sa cream cele doua obiecte:

$Step = 5
$Obj1 = CreateObject(0,0,40,40,0,160,0,160)
$Obj2 = CreateObject(160,160,40,40,0,160,0,160)

Variabila $Step reprezinta pasul cu care se vor misca obiectele in simulare.

In bucla principala trebuie facute trei lucruri importante: generarea unei noi pozitii pentru obiect (aleator in cazul nostru), reactualizarea pozitiei pentru obiect si desenarea acestuia pe suprafata de desenare. Bucla principala arata asa:

Do
	Switch Random(1,8,1)
		Case 1
			UpdateObject($Obj1,$Obj1[0]+$Step,$Obj1[1])
		Case 2
			UpdateObject($Obj1,$Obj1[0]-$Step,$Obj1[1])
		Case 3
			UpdateObject($Obj1,$Obj1[0],$Obj1[1]+$Step)
		Case 4
			UpdateObject($Obj1,$Obj1[0],$Obj1[1]-$Step)
		Case 5
			UpdateObject($Obj2,$Obj2[0]+$Step,$Obj2[1])
		Case 6
			UpdateObject($Obj2,$Obj2[0]-$Step,$Obj2[1])
		Case 7
			UpdateObject($Obj2,$Obj2[0],$Obj2[1]+$Step)
		Case 8
			UpdateObject($Obj2,$Obj2[0],$Obj2[1]-$Step)
	EndSwitch
	_GDIPlus_GraphicsClear($hBackBuffer,0xFF000000)
	_GDIPlus_GraphicsFillRect($hBackBuffer,$Obj1[0],$Obj1[1],$Obj1[2],$Obj1[3],$hBrush1)
	_GDIPlus_GraphicsFillRect($hBackBuffer,$Obj2[0],$Obj2[1],$Obj2[2],$Obj2[3],$hBrush2)
	_GDIPlus_GraphicsDrawImage($hGraphics,$hBitmap,0,0)
	Sleep($Step*10)
Until ObjectsOverlap($Obj1,$Obj2)

In bucla, primul lucru care se face este generarea unei noi pozitii pentru unul din obiecte. Pentru aceasta folosim o expresie conditionala cu un numar aleator intre 1-8. Primele 4 cazuri simuleaza miscarea (pozitiva si negativa) pe axa X, respectiv miscarea (pozitiva si negativa) pe axa Y, pentru primul obiect. Ultimele 4 cazuri simuleaza miscarea (pozitiva si negativa) pe axa X, respectiv miscarea (pozitiva si negativa) pe axa Y, pentru al doilea obiect.

Pentru oricare din aceste cazuri se efectueaza o operatie de reactualizare a pozitiei pentru un obiect.

Ultimele linii ale buclei curata bufferul, deseneaza obiectele in buffer si apoi copiaza imaginea din buffer pe ecran. Dupa cum stiti, pentru a nu suprasolicita CPU, in bucle se folosesc pauze scurte, in acest caz durata pauzei o sa fie proportionala cu pasul de miscare al obiectelor.

Bucla ruleaza in acest mod pana cand cele doua obiecte ajung in coliziune.

La iesirea din bucla se afiseaza mesajul de atentionare ca obiectele sunt in coliziune, timp de 5 secunde.

TrayTip("Coliziune","Obiectele au ajuns in contact.",1)
Sleep(5000)

Mai trebuie doar sa eliberam resursele GDI+ folosite:

_GDIPlus_BrushDispose($hBrush1)
_GDIPlus_BrushDispose($hBrush2)
_GDIPlus_GraphicsDispose($hBackBuffer)
_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_Shutdown()

 

Daca asamblam portiunile de cod sursa de mai sus obtinem urmatorul script (pentru vizibilitate am pus functiile la final):

#include <GDIPlus.au3>
 
$hMain = GUICreate("Exemplu",200,200)
GUISetState(@SW_SHOW,$hMain)
 
_GDIPlus_Startup()
$hGraphics = _GDIPlus_GraphicsCreateFromHWND($hMain)
$hBitmap = _GDIPlus_BitmapCreateFromGraphics(200,200,$hGraphics)
$hBackBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
$hBrush1 = _GDIPlus_BrushCreateSolid(0xFFFF0000)
$hBrush2 = _GDIPlus_BrushCreateSolid(0xFF00FF00)
 
$Step = 5
$Obj1 = CreateObject(0,0,40,40,0,160,0,160)
$Obj2 = CreateObject(160,160,40,40,0,160,0,160)
 
Do
	Switch Random(1,8,1)
		Case 1
			UpdateObject($Obj1,$Obj1[0]+$Step,$Obj1[1])
		Case 2
			UpdateObject($Obj1,$Obj1[0]-$Step,$Obj1[1])
		Case 3
			UpdateObject($Obj1,$Obj1[0],$Obj1[1]+$Step)
		Case 4
			UpdateObject($Obj1,$Obj1[0],$Obj1[1]-$Step)
		Case 5
			UpdateObject($Obj2,$Obj2[0]+$Step,$Obj2[1])
		Case 6
			UpdateObject($Obj2,$Obj2[0]-$Step,$Obj2[1])
		Case 7
			UpdateObject($Obj2,$Obj2[0],$Obj2[1]+$Step)
		Case 8
			UpdateObject($Obj2,$Obj2[0],$Obj2[1]-$Step)
	EndSwitch
	_GDIPlus_GraphicsClear($hBackBuffer,0xFF000000)
	_GDIPlus_GraphicsFillRect($hBackBuffer,$Obj1[0],$Obj1[1],$Obj1[2],$Obj1[3],$hBrush1)
	_GDIPlus_GraphicsFillRect($hBackBuffer,$Obj2[0],$Obj2[1],$Obj2[2],$Obj2[3],$hBrush2)
	_GDIPlus_GraphicsDrawImage($hGraphics,$hBitmap,0,0)
	Sleep($Step*10)
Until ObjectsOverlap($Obj1,$Obj2)
 
TrayTip("Coliziune","Obiectele au ajuns in contact.",1)
Sleep(5000)
 
_GDIPlus_BrushDispose($hBrush1)
_GDIPlus_BrushDispose($hBrush2)
_GDIPlus_GraphicsDispose($hBackBuffer)
_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_Shutdown()
 
Func CreateObject($X,$Y,$W,$H,$MinX,$MaxX,$MinY,$MaxY)
	Local $Object[8] = [$X,$Y,$W,$H,$MinX,$MaxX,$MinY,$MaxY]
	Return $Object
EndFunc
 
Func UpdateObject(ByRef $Obj,$X,$Y)
	If $X < $Obj[4] Then $X = $Obj[4]
   	If $X > $Obj[5] Then $X = $Obj[5]
	If $Y < $Obj[6] Then $Y = $Obj[6]
   	If $Y > $Obj[7] Then $Y = $Obj[7]
	$Obj[0] = $X
	$Obj[1] = $Y
EndFunc
 
Func ObjectsOverlap($Obj1,$Obj2)
    Local $SX = Abs($Obj2[0] - $Obj1[0]) + $Obj2[2]
    Local $SY = Abs($Obj2[1] - $Obj1[1]) + $Obj2[3]
    Return ($SX < $Obj1[2] + $Obj2[2] And $SY < $Obj1[3] + $Obj2[3])
EndFunc

 

 
Asemanator este si pentru alte tipuri de obiecte. Spre exemplu pentru cercuri, functia CreateObject poate arata in felul urmator:

Func CreateObject($X,$Y,$R,$MinX,$MaxX,$MinY,$MaxY)
	Local $Object[7] = [$X,$Y,$R,$MinX,$MaxX,$MinY,$MaxY]
	Return $Object
EndFunc

Pentru un cerc vor fi importante coordonatele centrului cercului si raza acestuia. Restul parametrilor raman neschimbati.
 
Functia UpdateObject ramane neschimbata, X si Y reprezentand centrul obiectului(cercului).
 
Din ecuatia cercului se poate obtine si formula pentru a verifica cand doua cercuri sunt in contact, deci vom avea functia:

Func ObjectsOverlap($Obj1,$Obj2)
	Return ((($Obj1[2]+$Obj2[2])^2) > ((($Obj2[0]-$Obj1[0])^2)+((($Obj2[1]-$Obj1[1])^2))))
EndFunc

Altfel spus cand (R1+R2)^2 > ((X2-X1)^2 + (Y2-Y1)^2) cele doua cercuri sunt in contact, unde X si Y sunt coordonatele pentru centrul cercului si R este raza cercului (indexul 1 sau 2 indica daca este vorba despre primul sau al doilea obiect).
 
Singurul lucru care poate fi derutant este la desenarea cercurilor pe ecran. In AutoIt, cercul este o elipsa in care latimea este egala cu inaltimea si pentru care X si Y nu reprezinta centrul cercului ci coordonatele punctului de la care incepe desenarea elipsei. Acest lucru poate fi scris la desenare in felul urmator:

_GDIPlus_GraphicsFillEllipse($hBackBuffer,$Obj1[0]-$Obj1[2],$Obj1[1]-$Obj1[2],$Obj1[2]*2,$Obj1[2]*2,$hBrush1)
_GDIPlus_GraphicsFillEllipse($hBackBuffer,$Obj2[0]-$Obj2[2],$Obj2[1]-$Obj2[2],$Obj2[2]*2,$Obj2[2]*2,$hBrush2)

 
Altfel spus coordonatele elipsei sunt: X = coordonata X a centrului cercului – raza, Y = coordonata Y a centrul cercului – raza, W = raza cercului * 2 si H = raza cercului * 2.
 
Un script care verifica daca doua cercuri ajung in contact poate arata asa:

#include <GDIPlus.au3>
 
$hMain = GUICreate("Exemplu",200,200)
GUISetState(@SW_SHOW,$hMain)
 
_GDIPlus_Startup()
$hGraphics = _GDIPlus_GraphicsCreateFromHWND($hMain)
$hBitmap = _GDIPlus_BitmapCreateFromGraphics(200,200,$hGraphics)
$hBackBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
$hBrush1 = _GDIPlus_BrushCreateSolid(0xFFFF0000)
$hBrush2 = _GDIPlus_BrushCreateSolid(0xFF00FF00)
 
$Step = 5
$Obj1 = CreateObject(20,20,20,20,180,20,180)
$Obj2 = CreateObject(180,180,20,20,180,20,180)
 
Do
	Switch Random(1,8,1)
		Case 1
			UpdateObject($Obj1,$Obj1[0]+$Step,$Obj1[1])
		Case 2
			UpdateObject($Obj1,$Obj1[0]-$Step,$Obj1[1])
		Case 3
			UpdateObject($Obj1,$Obj1[0],$Obj1[1]+$Step)
		Case 4
			UpdateObject($Obj1,$Obj1[0],$Obj1[1]-$Step)
		Case 5
			UpdateObject($Obj2,$Obj2[0]+$Step,$Obj2[1])
		Case 6
			UpdateObject($Obj2,$Obj2[0]-$Step,$Obj2[1])
		Case 7
			UpdateObject($Obj2,$Obj2[0],$Obj2[1]+$Step)
		Case 8
			UpdateObject($Obj2,$Obj2[0],$Obj2[1]-$Step)
	EndSwitch
	_GDIPlus_GraphicsClear($hBackBuffer,0xFF000000)
	_GDIPlus_GraphicsFillEllipse($hBackBuffer,$Obj1[0]-$Obj1[2],$Obj1[1]-$Obj1[2],$Obj1[2]*2,$Obj1[2]*2,$hBrush1)
	_GDIPlus_GraphicsFillEllipse($hBackBuffer,$Obj2[0]-$Obj2[2],$Obj2[1]-$Obj2[2],$Obj2[2]*2,$Obj2[2]*2,$hBrush2)
	_GDIPlus_GraphicsDrawImage($hGraphics,$hBitmap,0,0)
	Sleep($Step*5)
Until ObjectsOverlap($Obj1,$Obj2)
 
TrayTip("Coliziune","Obiectele au ajuns in contact.",1)
Sleep(5000)
 
_GDIPlus_BrushDispose($hBrush1)
_GDIPlus_BrushDispose($hBrush2)
_GDIPlus_GraphicsDispose($hBackBuffer)
_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_Shutdown()
 
Func CreateObject($X,$Y,$R,$MinX,$MaxX,$MinY,$MaxY)
	Local $Object[7] = [$X,$Y,$R,$MinX,$MaxX,$MinY,$MaxY]
	Return $Object
EndFunc
 
Func UpdateObject(ByRef $Obj,$X,$Y)
	If $X < $Obj[3] Then $X = $Obj[3]
	If $X > $Obj[4] Then $X = $Obj[4]
	If $Y < $Obj[5] Then $Y = $Obj[5]
	If $Y > $Obj[6] Then $Y = $Obj[6]
	$Obj[0] = $X
	$Obj[1] = $Y
EndFunc
 
Func ObjectsOverlap($Obj1,$Obj2)
	Return ((($Obj1[2]+$Obj2[2])^2) > ((($Obj2[0]-$Obj1[0])^2)+((($Obj2[1]-$Obj1[1])^2))))
EndFunc

GDI+ Double Buffering

Daca ati folosit functiile GDI+ pentru desenare, probabil ati observat inconvenientul cauzat de multiple operatii de desenare pe ecran, care cauzeaza un tremur al imaginii (flickers). Acest lucru se poate observa usor intr-o bucla in care se simuleaza miscarea unui obiect.

 

In exemplul de mai jos simulam miscare unui patrat, de culoare albastra, din partea stanga spre partea dreapta a ferestrei (observati inconvenientul despre care vorbeam putin mai sus).

#include <GDIPlus.au3>
 
$hMain = GUICreate("Exemplu")
GUISetState(@SW_SHOW,$hMain)
 
_GDIPlus_Startup()
$hGraphics = _GDIPlus_GraphicsCreateFromHWND($hMain)
$hBrush = _GDIPlus_BrushCreateSolid(0xFF000080)
 
For $X = 0 To 400
	_GDIPlus_GraphicsClear($hGraphics,0xFF000000)
	_GDIPlus_GraphicsFillRect($hGraphics,$X,180,40,40,$hBrush)
	Sleep(10)
Next
 
_GDIPlus_BrushDispose($hBrush)
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_Shutdown()

 

Acest inconvenient dispare daca vom folosi tehnica numita Double Buffering. Aceasta tehnica consta in crearea unui buffer in memorie in care vor fi randate toate operatiile de desenare, in loc sa fie desenate pe ecran. Dupa ce sunt finalizate toate operatiile de desenare bufferul este copiat pe suprafata de desenare asociata acestuia. Daca ati prins ideea, este utilizata doar o operatie de desenare pe ecran, astfel inconvenientul provocat de desenarile multiple dispare.

 

Acelasi exemplu in care simulam miscarea patratului dar de aceasta data imaginea este stabila.

 

#include <GDIPlus.au3>
 
$hMain = GUICreate("Exemplu")
GUISetState(@SW_SHOW,$hMain)
 
_GDIPlus_Startup()
; Suprafata de desenare
$hGraphics = _GDIPlus_GraphicsCreateFromHWND($hMain)
$hBitmap = _GDIPlus_BitmapCreateFromGraphics(400,400,$hGraphics)
; Suprafata de desenare din memorie (buffer)
$hBackBuffer = _GDIPlus_ImageGetGraphicsContext($hBitmap)
$hBrush = _GDIPlus_BrushCreateSolid(0xFF000080)
 
For $X = 0 To 400
	; Operatii de desenare in buffer
	_GDIPlus_GraphicsClear($hBackBuffer,0xFF000000)
	_GDIPlus_GraphicsFillRect($hBackBuffer,$X,180,40,40,$hBrush)
	; Desenare pe ecran
	_GDIPlus_GraphicsDrawImage($hGraphics,$hBitmap,0,0)
	Sleep(10)
Next
 
_GDIPlus_BrushDispose($hBrush)
_GDIPlus_GraphicsDispose($hBackBuffer)
_GDIPlus_BitmapDispose($hBitmap)
_GDIPlus_GraphicsDispose($hGraphics)
_GDIPlus_Shutdown()

Crearea unei interfete grafice personalizata

Daca va doriti o interfata mai deosebita pentru aplicatia dumneavoastra atunci acest tutorial o sa fie foarte util in acest sens.

 

In acest tutorial vom avea nevoie de functii WinAPI deci prima linie din codul sursa este:

 

#include <WinAPI.au3>

 

Urmatoarele linii vor constitui interfata grafica:

 

$hMain = GUICreateEx("Exemplu",300,250,-1,-1,"Background.bmp")
$hMinimize = GUICtrlCreatePic("Minimize.bmp",105,215,40,30)
$hClose = GUICtrlCreatePic("Close.bmp",155,215,40,30)
GUISetState(@SW_SHOW,$hMain)

La prima linie apelam functia GUICreateEx (despre care vom vorbi un pic mai jos) care creaza fereastra principala. Urmatoarele doua linii sunt controalele pentru butonul de minimizare (_) si inchidere (x). Ultima linie face vizibila fereastra principala.

Imaginile necesare pentru interfata le puteti descarca de aici.

 

Urmatoarele linii reprezinta bucla principala a programului:

 

While True
	Switch GUIGetMsg()
		Case $hMinimize
			GUISetState(@SW_MINIMIZE,$hMain)
		Case $hClose
			Exit
		Case -7	; Primary Down
			_SendMessage($hMain,0x0112,0xF012,0)
	EndSwitch
	Sleep(10)
WEnd

In bucla principala ne intereseaza 3 evenimente: minimizare, inchidere si primary down (butonul principal al mouseului apasat – sa miscam fereastra). In consecinta cand este apasat butonul de minimizare ($hMinimize) se seteaza starea ferestrei @SW_MINIMIZE; cand este apasat butonul de inchidere ($hClose) se inchide programul iar cand este interceptat mesajul Primary Down (valoarea -7) se apeleaza functia _SendMessage avand ca parametri: handle-ul ferestrei principale, mesajul WM_SYSCOMMAND (0x0112) si $SC_DRAGMOVE (0xF012).

 

Mai jos este partea cea mai importanta a tutorialului, functia care creaza interfata grafica:

 

Func GUICreateEx($sTitle,$iW,$iH,$iX=-1,$iY=-1,$sBackground="")
	Local $hGUI = GUICreate($sTitle,$iW,$iH,$iX,$iY,0x80000000)
	$hRegion1 = _WinAPI_CreateRoundRectRgn(0,0,100,$iH,10,10)
	$hRegion2 = _WinAPI_CreateRectRgn(99,40,200,$iH-40)
	$hRegion3 = _WinAPI_CreateRoundRectRgn(200,0,300,$iH,10,10)
	$hRegion4 = _WinAPI_CreateRoundRectRgn(105,5,195,35,5,5)
	$hRegion5 = _WinAPI_CreateRoundRectRgn(105,$iH-35,145,$iH-5,5,5)
	$hRegion6 = _WinAPI_CreateRoundRectRgn(155,$iH-35,195,$iH-5,5,5)
	_WinAPI_CombineRgn($hRegion1,$hRegion1,$hRegion2,2)
	_WinAPI_CombineRgn($hRegion1,$hRegion1,$hRegion3,2)
	_WinAPI_CombineRgn($hRegion1,$hRegion1,$hRegion4,2)
	_WinAPI_CombineRgn($hRegion1,$hRegion1,$hRegion5,2)
	_WinAPI_CombineRgn($hRegion1,$hRegion1,$hRegion6,2)
	_WinAPI_SetWindowRgn($hGUI,$hRegion1,True)
	If $sBackground Then
		$hPic = GUICtrlCreatePic($sBackground,0,0,$iW,$iH)
		GUICtrlSetState($hPic,128)
	EndIf
	Local $hTitle = GUICtrlCreateLabel($sTitle,106,9,87,20,0x01)
	GUICtrlSetFont($hTitle,12,700,0,"Garamond")
	GUICtrlSetBkColor($hTitle,0x008000)
	GUICtrlSetColor($hTitle,0x004040)
	Return $hGUI
EndFunc

In prima linie din corpul functiei se creaza o fereastra cu toate specificatiile pasate ca parametri si se poate observa stilul $WS_POPUP (0x80000000), folosit pentru ca nu ne intereseaza o fereastra cu o bara de titlu sau butoane sistem.

In urmatoarele linii cream 6 regiuni diferite care vor constitui interfata finala. Pentru acest lucru se folosesc functiile _WinAPI_CreateRectRgn si _WinAPI_CreateRoundRectRgn. Pentru a intelege mai bine partile care constituie interfata finala priviti imaginea de mai jos:

In urmatoarele linii de cod combinam (_WinAPI_CombineRgn) toate aceste regiuni intr-o singura regiune pe care o atribuim ferestrei (_WinAPI_SetWindowRgn) create pe prima linie.

Apoi se testeaza daca exista parametrul $sBackground, caz in care se creaza un control Pic si se seteaza o imagine de fundal. Controlul Pic care pastreaza imaginea de fundal se dezactiveaza pentru a nu se suprapune cu alte controale ($GUI_DISABLE = 128). Apoi se mai creaza un control Label care va constitui titlul ferestrei. La acesta se seteaza fontul, culoare de fundal si culoarea textului.

In final se returneaza handle-ul ferestrei create pentru a putea fi folosit in continuare.

 

Daca asamblati portiunile de cod de mai sus, obtineti scriptul:

 

#include <WinAPI.au3>	; Contine si SendMessage.au3
 
$hMain = GUICreateEx("Exemplu",300,250,-1,-1,"Background.bmp")
$hMinimize = GUICtrlCreatePic("Minimize.bmp",105,215,40,30)
$hClose = GUICtrlCreatePic("Close.bmp",155,215,40,30)
GUISetState(@SW_SHOW,$hMain)
 
While True
	Switch GUIGetMsg()
		Case $hMinimize
			GUISetState(@SW_MINIMIZE,$hMain)
		Case $hClose
			Exit
		Case -7	; Primary Down
			_SendMessage($hMain,0x0112,0xF012,0)
	EndSwitch
	Sleep(10)
WEnd
 
Func GUICreateEx($sTitle,$iW,$iH,$iX=-1,$iY=-1,$sBackground="")
	Local $hGUI = GUICreate($sTitle,$iW,$iH,$iX,$iY,0x80000000)
	$hRegion1 = _WinAPI_CreateRoundRectRgn(0,0,100,$iH,10,10)
	$hRegion2 = _WinAPI_CreateRectRgn(99,40,200,$iH-40)
	$hRegion3 = _WinAPI_CreateRoundRectRgn(200,0,300,$iH,10,10)
	$hRegion4 = _WinAPI_CreateRoundRectRgn(105,5,195,35,5,5)
	$hRegion5 = _WinAPI_CreateRoundRectRgn(105,$iH-35,145,$iH-5,5,5)
	$hRegion6 = _WinAPI_CreateRoundRectRgn(155,$iH-35,195,$iH-5,5,5)
	_WinAPI_CombineRgn($hRegion1,$hRegion1,$hRegion2,2)
	_WinAPI_CombineRgn($hRegion1,$hRegion1,$hRegion3,2)
	_WinAPI_CombineRgn($hRegion1,$hRegion1,$hRegion4,2)
	_WinAPI_CombineRgn($hRegion1,$hRegion1,$hRegion5,2)
	_WinAPI_CombineRgn($hRegion1,$hRegion1,$hRegion6,2)
	_WinAPI_SetWindowRgn($hGUI,$hRegion1,True)
	If $sBackground Then
		$hPic = GUICtrlCreatePic($sBackground,0,0,$iW,$iH)
		GUICtrlSetState($hPic,128)
	EndIf
	Local $hTitle = GUICtrlCreateLabel($sTitle,106,9,87,20,0x01)
	GUICtrlSetFont($hTitle,12,700,0,"Garamond")
	GUICtrlSetBkColor($hTitle,0x008000)
	GUICtrlSetColor($hTitle,0x004040)
	Return $hGUI
EndFunc

Daca rulati scriptul, interfata grafica o sa fie asemanatoare cu cea de mai jos:

Restul tine de imaginatie si de preferinte. Puteti sa creati forme noi (elipse, poligoane, etc), sa folositi culorile favorite, etc.

 

Scriptul, resursele si o versiune compilata puteti descarca de aici.

Incarcarea medie a unui server

Daca folositi cPanel si vreti sa obtineti incarcarea medie a serverului dar nu aveti timpul necesar sa va logati, apoi sa verificati acest lucru atunci acest script o sa se dovedeasca foarte util.

In acest tutorial vom invatat cum sa obtinem rapid informatii despre un server folosind cPanel XML API, in acest caz LoadAvg.

 

Incepem cu crearea unui script nou, in care primele linii vor fi urmatoarele:

 

In prima linie includem fisierul antet String.au3 de care avem nevoie pentru a putea accesa functia _StringBetween. Urmatoarele linii vor contine informatiile pentru conectare la server(credentialele), numele domeniului si numele API-ului. Exemplul de mai sus este un template, dumneavoastra trebuie sa modificati username-ul, parola si numele domeniului.

 

Urmatoarele doua linii sunt folosite pentru a obtine, respectiv procesa informatiile obtinute.

Functia cPanel_XML_API efectueaza conectarea la server si obtine datele in format XML iar functia LoadAverage extrage datele din format XML si le pune intr-un array.

 

Urmatoarele linii sunt folosite pentru a crea interfata grafica si main loop.

Codul scris pe linia 11, copiaza in directorul cu fisiere temporare un fisier bitmap care o sa fie folosit ca logo.

La linia 12 este creata fereastra principala.

La linia 13 se creaza un Pic control care afiseaza logo-ul.

Urmatoarele 3 linii (Label1..3) afiseaza timpul pentru care se afiseaza rezultatele, iar urmatoarele 3 linii (Value1..3) afiseaza rezultatele propriu-zise.

La linia 20 se seteaza starea vizibila pentru fereastra principala.

Liniile 22,23 si 24 constituie bucla principala, care verfica doar daca buton Close (x) este apasat.

Nota: aceasta portiune de cod este optionala, daca doriti puteti afisa rezultatele si intr-un MsgBox.

 

Codul de mai jos reprezinta functia cPanel_XML_API.

La linia 27 cream un obiect WinHTTPRequest.

La linia 29 accesam metoda Open care deschide o conexiune HTTP la o resursa.

La linia 30 setam credentialele pentru conectare.

La linia 31 trimitem cererea.

La linia 33 obtinem raspunsul serverului, datele in format XML.

La linia 34 distrugem obiectul creat.

La linia 35 sunt returnate datele obtinute (inca in format XML).

Nota: functia cPanel_XML_API nu este specifica pentru LoadAvg, cu ajutorul ei se pot accesa si alte API-uri.

 

Codul de mai jos reprezinta functia LoadAverage.

La linia 39 obtinem sirul de caractere cuprinse intre stringurile <loadavg> si </loadavg>. Rezultatul trebuie sa fie un array(vector).

La linia 40 se testeaza acest lucru.

La linia 41 se obtine valoarea incarcarii serverului pentru ultimul minut.

La linia 42 se obtine valoarea incarcarii serverului pentru ultimele 5 minute.

La linia 43 se obtine valoarea incarcarii serverului pentru ultimele 15 minute.

La linia 44 se returneaza rezultatul sub forma unui array. Am folosit functia StringSplit tocmai pentru a obtine un array din 3 stringuri.

La linia 46 se returneaza un mesaj de eroare in cazul in care rezultatul obtinut la linia 39 nu este sub forma unui array.

Nota: nu am folosit un UDF (User Defined Function) pentru procesarea datelor XML pentru ca in acest caz aceasta metoda este mai eficienta din punct de vedere a liniilor de cod scrise si a dimensiunii scriptului compilat ca executabil.

 

Daca asamblati toate portiunile de cod de mai sus, obtineti scriptul complet ca in imaginea de mai jos:

Daca modificati datele de conectare si rulati scriptul, obtineti o fereastra asemanatoare cu cea de mai jos:

Puteti descarca scriptul si resursele necesare de aici.

Instalarea automata a utilitarului 7-Zip

Pentru inceput aveti nevoie de utilitarul 7-Zip pe care il puteti descarca de aici. Apoi trebuie sa creati un script nou (in exemplul meu i-am dat numele AutoInstall 7zip.au3), de preferat in acelasi director cu executabilul 7-Zip. Daca ati procedat dupa instructiuni trebuie sa aveti un director asemanator cu cel de mai jos:

Apoi trebuie sa deschideti scriptul pentru editare. Prima linie din script este destinata rularii executabilului 7z920.exe si arata asa:

Run("7z920.exe",@ScriptDir,@SW_MINIMIZE)

Aceasta linie va executa 7z920.exe, stiind ca directorul de lucru este directorul in care este plasat scriptul, cu optiunea ca va fereastra va fi in modul minimize.

 

Apoi trebuie sa asteptam pana apare fereastra specifica procesului 7z920.exe. In acest caz fereastra se numeste “7-Zip 9.20 Setup “. Daca va intrebati cum am obtinut acest titlu pentru fereastra, raspunsul este folosind utilitarul AutoIt Window Info, pe care il gasiti Start-> All Programs -> AutoIt v3 sau in directorul AutoIt3 din Program Files.

Pentru a astepta fereastra, apelam functia WinWait:

WinWait("7-Zip 9.20 Setup ")

 

Un exemlpu folosind utilitarul AutoIt Window Info:

 

Daca dorim sa obtinem si directorul de instalare (in acest tutorial ne vom folosi de acest lucru) apelam functia ControlGetText, specificand numele ferestrei si controlul din care obtinem directorul de instalare, fara sa specificam textul ferestrei (in cele mai multe cazuri nici nu exista).

$sPath = ControlGetText("7-Zip 9.20 Setup ","","Edit1")

 

Apoi trebuie sa apasam butonul Install pentru a incepe procesul de instalare. Acest lucru se face apeland functia ControlClick, avand aceeasi parametri ca si functia ControlGetText, doar ca in cazul acesta apasam “Button2” care este a doua instanta a clasei Button.

ControlClick("7-Zip 9.20 Setup ","","Button2″)

Modul de obtinere a claselor si instantele acestora dintr-o fereastra se face cum am mentionat anterior, folosind utilitarul AutoIt Window Info.

 

Procesul de instalare poate varia ca durata, in functie de performantele sistemului, de aceea trebuie gasita o solutie prin care sa stim exact cand s-a finalizat procesul de instalare.

Pentru acest lucru vom crea o bucla in care vom verifica daca apare numele butonului de final.

Do
	Sleep(10)
Until ControlGetText("7-Zip 9.20 Setup ","","Button2") = "&amp;Finish"

 

La iesirea din bucla vom sti ca instalarea a ajuns la final. Tot ce mai trebuie sa facem este sa apasam butonul Finish.

ControlClick("7-Zip 9.20 Setup ","","Button2″)

 

Dupa ce este apasat butonul Finish, poate doriti sa informati utilizatorul ca instalarea a fost efectuata si sa intrebati daca doreste deschidere directorului de instalare.

$Question = MsgBox(0x44,"Mesaj","Instalare cu succes." &amp; @CRLF &amp; _
"Doriti deschiderea directorului de instalare?")

 

Mai trebuie doar tratat raspunsul utilizatorului:

If $Question = 6 Then
	ShellExecute($sPath)
Else
	Exit
EndIf

 

Daca asamblati toate liniile de cod de mai sus, scriptul va arata asa:

 

Daca rulati scriptul, la final de instalare va aparea mesajul:

Daca raspunsul este Yes se va deschide directorul de instalare (ca si in exemplul de mai jos) apoi scriptul se inchie, iar daca raspunsul este No atunci scriptul se incheie.

Puteti descarca de aici scriptul si executabilul utilitarului 7-Zip.