AutoIt/Ćwiczenia dla zaawansowanych - przykładowe rozwiązania

Z Wikibooks, biblioteki wolnych podręczników.

Funkcje rekurencyjne[edytuj]

1. Napisać funkcję rekurencyjną sumująca liczby całkowite w przedziale od m do n (m i n podawane jako parametry).

Funkcja powinna działać prawidłowo także dla liczb ujemnych, oraz niezależnie od kolejności podanych parametrów.

Jeżeli podamy jeden parametr to sumowanie powinno być od zera lub do zera (dla liczb ujemnych).

Przykładowe rozwiązanie:

Func suma($n, $m=0.0)              ;drugi parametr opcjonalny, z domyślną wartością 0.0
   If $n<$m Then ;kalibrowanie danych, aby można było wpisywać liczby w dowolnej kolejności
      $pom=$n
      $n=$p
      $m=$pom
   EndIf
   if $n=$m Then Return $m         ;przypadek bazowy dla najmniejszej liczby
   Return $n+suma($n-1,$m)         ;obliczenia rekurencyjne
EndFunc

Ilość sumowanych liczb jest ograniczona do ok.4000, przy większej ilości ze względu na możliwość przepełnienia stosu działanie funkcji zostanie przerwane.


2. Napisać rekurencyjną funkcję obliczającą liczbę e. Funkcja ta powinna korzystać z rekurencyjnej funkcji silna zdefiniowanej w powyższym przykładzie.

Skorzystać z rozwinięcia w szereg e = 1 + 1/1! + 1/2! + ... + 1/n! + ... (graniczna wartość n podawana jako parametr).

(dla sprawdzenia przybliżona wartość e = 2.718281828459...)

Przykładowe rozwiązanie:

Func e($n)
   if $n=0 Then Return 1.0     ;przypadek bazowy dla n=0
   Return 1/silnia($n)+e($n-1) ;wywołanie rekurencyjne i wywołanie innej funkcji rekurencyjnej
EndFunc

Func silnia($n)
   if $n=0 Then Return 1.0  
   Return $n*silnia($n-1)
EndFunc

Jak widać w powyższym przykładzie funkcja rekurencyjna może w swojej definicji wywoływać inną funkcję rekurencyjną.


Napisy (stringi)[edytuj]

1. Napisać skrypt wyświetlający ile procent znaków w wczytanym z dysku pliku tekstowym stanowi litera a (wielkość litery nie ma znaczenia). Skrypt powinien zawierać zdefiniowaną funkcję zliczającą w stringu ilość wystąpień dowolnego znaku.

;wywołanie systemowego selektora plików i wczytanie do zmiennej nazwy wybranego pliku
$sFile = FileOpenDialog("Wybierz plik tekstowy","","(*.txt)")
$sTxt = FileRead($sFile);wczytanie pliku tekstowego do zmiennej

$sChr = "a"

;wyliczenie procentowego udziału litery a w całym tekście
;(ilość_a/ilość_znaków w tekście, x100 żeby było w procentach)
$iUdzial = 100 * licz_znaki($sTxt, $sChr) / StringLen($sTxt)
                                             ;
$iUdzial = Round($iUdzial, 2)   ;zaokrąglenie wyniku do 2 miejsc po kropce dziesiętnej

;wyświetlenie wyniku na ekranie
MsgBox(0,"Stringi - ćwiczenie 1", "Litera '" & $sChr & "' stanowi " & $iUdzial & "% wszystkich znaków")

;funkcja zliczająca ilość wystąpień znaku $sChr w stringu $sTxt
Func licz_znaki($sTxt, $chr)
   StringReplace($sTxt,$sChr,$sChr)     ;zamiana znaków na te same znaki
   Return @extended                     ;to makro podaje ilość zamian
EndFunc


2. Używając funkcji formatującej StringFormat napisać skrypt wyświetlający liczby -445.987, 0.00878, 2011 z wyrównaniem na kropce dziesiętnej jak poniżej:

 -445.987
   +0.00878
+2011.00

Tego typu wyrównanie będzie możliwe tylko dla fontów nieproporcjonalnych (o stałej szerokości), np. Courier, Courier New, itp.

Przykładowe rozwiązanie:

$v1 = -445.987
$v2 = 0.00878
$v3 = 2011

$format = "%+11.5f\n%+11.5f\n%+11.5f" ;łańcuch formatujący
SplashTextOn("Formatowanie liczb:", StringFormat($format, $v1, $v2, $v3),-1,-1,-1,-1,-1,"Courier")
Sleep(5000)

Wyrażenia regularne[edytuj]

1. Napisać skrypt sprawdzający czy podany string jest prawidłową (pod względem formalnym) ścieżką dostępu do pliku.

Rozwiązanie rozpoczynamy od określenia formatu ścieżki dostępu. Wygląda on następująco: x:\...\...\...\nazwa_pliku itd., gdzie x - dowolna litera od a do z, ... - nazwa podfolderów. W systemie plików NTFS nazwa folderów i plików może składać się z dowolnych znaków z wyjątkiem /\*?<>|:"

Maksymalna długość pełnej ścieżki 260 znaków.

Przykładowe rozwiązanie:

$sPath = "c:\folder1\folder2\folder3\program.exe"             ;przykładowa ścieżka dostępu

;eliminujemy łańcuchy za długie lub zawierające niedozwolone znaki (wzorce alternatywne)
;więcej niż 1 dwukropek, któryś ze znaków /*?<>|" lub jest dłuższy niż 260 znaków
;lub między \\ nic lub tylko białe znaki

If StringRegExp($sPath, ':{2,}|[/*?<>|"]|.{260,}|\\\s*\\') Then
   MsgBox(0, "", "Zła ścieżka dostępu")
Else
   If StringRegExp($sPath,"(?i)^[a-z]:\\") Then             ;sprawdzenie formatu ścieżki
      MsgBox(0, "" ,"Prawidłowa ścieżka dostępu")
   Else
      MsgBox(0, "", "Zła ścieżka dostępu")
   Endif
Endif


2. Napisać skrypt dzielący dany tekst na pojedyncze słowa. Separatorem słów są białe znaki.

Przykładowe rozwiązanie:

#include <Array.au3>      ;dołączenie biblioteki Array.au3, aby uzyskać dostęp do funkcji _ArrayDisplay()
$txt="matma tata kasetka.  roma  1278a" ;przykładowy tekst
$tab=StringRegExp($txt,"\S+",3)         ;w tablicy $tab znajdą się wszystkie dopasowania, czyli wyrazy 
                                   ;(w naszym wypadku wyraz może się składać z dowolnych czarnych znaków)
_ArrayDisplay($tab)                     ;a tu można obejrzeć zawartość tablicy


3. Zamienić amerykański zapis dowolnej daty (mm-dd-rrrr) na zapis w formacie europejskim (rrrr.mm.dd).

Przykładowe rozwiązanie:

$sDataA = "12-22-1952"                    ;przykładowa data po amerykańsku
;zamiana na europejską z użyciem zapamiętanych dopasowań
$sDataE = StringRegExpReplace($sDataA, "(\d{2})-(\d{2})-(\d{4})", "$3.$1.$2")
MsgBox(0, $sDataA, $sDataE)


4. Napisać skrypt wyszukujący we wczytanym z dysku pliku tekstowym wszystkie słowa zaczynające się i kończące na te same dwie litery.

Przykładowe rozwiązanie:

#include <Array.au3>

;wywołanie systemowego selektora plików i wczytanie do zmiennej nazwy wybranego pliku
$sFtxt = FileOpenDialog("Wybierz plik tekstowy","","(*.txt)")
$sTxt  = FileRead($sFtxt)                                    ;wczytanie pliku tekstowego do zmiennej
$aTab  = _StringRegExp($sTxt,"(?i)\b([a-z]{2})[a-z]*\1\b",1) ;porównanie tekstu z wzorcem
_ArrayDisplay($aTab)                                         ;podgląd wyników

;==============================================================================================
;funkcja _StringRegExp (jest to zmodyfikowana funkcja StringRegExp z flagą 4)
;dla $iFlag=0 funkcja zwraca ilość dopasowań, dla $iFlag<>0 zwraca jednowymiarową tablicę
;zawierającą w kolejnych komórkach wszystkie dopasowania
;pozostałe parametry jak dla StringRegExp
;==============================================================================================
Func _StringRegExp($sTxt, $sPat, $iFlag=0, $iCount=1)
   $aTab = StringRegExp($sTxt, $sPat, 4, $iCount)
   If $iFlag = 0 Then Return UBound($aTab)  ;zwrócenie odczytanej ilości dopasowań (dla flag=0)
   Local $aRes[UBound($aTab)]               ;tworzymy tablicę wyników
   For $i = 0 to UBound($aTab)-1            ;w pętli wpisujemy do tablicy wyników kolejne dopasowania
      $aRes[$i] = ($aTab[$i])[0]
   Next
   Return $aRes                             ;zwrócenie tablicy wyników (dla flag<>0)
EndFunc


Wyskakujące okna - prosta interakcja ze skryptem[edytuj]

1. Napisać skrypt porównujący wprowadzone z klawiatury hasło, z hasłem zapamiętanym w zmiennej. Skrypt powinien wyświetlić komunikat, czy hasło jest poprawne (w komunikacie umieścić odpowiednie ikonki informacyjne). Na wprowadzenie poprawnego hasła mamy 3 próby, potem skrypt powinien zakończyć działanie (wyświetlając stosowny komunikat).

Przykładowe rozwiązanie:

$pas="AutoIt"                                         ;przykładowe hasło (wzorzec)
$title="SPRAWDZANIE HASŁA"                            ;stała część komunikatu wyświetlanego na belce
For $i=1 To 3                                         ;3 krotne sprawdzanie w pętli For...Next
   ;wprowadzenie hasła z klawiatury, znaki są maskowane
   $wpas=InputBox($title&" - próba "&$i,"Wprowadź hasło","","*")
   If $wpas==$pas Then     ;sprawdzenie czy hasło i wzorzec są jednakowe (== sprawdza wielkość liter)
      ;jeżeli tak to wyświetla stosowny komunikat (z ikoną informacyjną)
      MsgBox(64,$title&" - próba "&$i,"Hasło prawidłowe.         ",5)
      ExitLoop                             ;i kończymy pętlę po 5 sekundach (ExitLoop)
   ElseIf $i<3 Then                        ;jeżeli hasło jest nieprawidłowe, a ilość prób mniejsza od
      ;można wybrać, czy kończymy, czy próbujemy dalej
      If MsgBox(5+48,$title&" - próba "&$i,"Hasło nieprawidłowe!"&@LF&"Czy próbujesz ponownie?")=2 Then
         ;w przypadku rezygnacji stosowny komunikat
         MsgBox(16,$title&" - próba "&$i,"Hasło nieprawidłowe!"&@LF&"Rezygnacja użytkownika.",5)
         Exit                                                      ;i opuszczenie skryptu
      EndIf
   ElseIf $i=3 Then                                                ;nieprawidłowe hasło w trzeciej próbie
      ;stosowny komunikat, po 5 sekundach
      MsgBox(16,$title&" - próba "&$i,"Wprowadzono 3 razy złe hasło!"&@LF&"Program zostanie zamknięty.",5)
      Exit                                                         ;kończymy program
   EndIf 
Next

;...........................................
;dalej część skryptu,
;działająca gdy wprowadzono prawidłowe hasło
;...........................................


2. Napisać skrypt będący przeglądarką plików. Powinien wczytywać wybrany na dysku plik i wyświetlić w okienku. Obsługa plików TXT, BMP, GIF i JPG.

Sposób wyświetlania uzależniony od typu pliku (rozpoznanie po rozszerzeniu).

Przykładowe rozwiązanie:

While 1        ;pętla nieskończona
;wywołanie systemowego selektora plików, z domyślnymi rozszerzeniami
$file=FileOpenDialog("Wybierz plik tekstowy lub obrazek","","(*.txt; *.bmp; *.jpg; *.gif)")
If @error Then Exit  ;jeżeli użyto klawisz anuluj lub zamknięcia okna to makro @error=1 i koniec skryptu
If StringRight($file,4)=".txt" Then   ;jeżeli nazwa pliku kończy się na ".txt"
	$txt=FileRead($file,10000)    ;wczytanie pliku tekstowego do zmiennej
	SplashTextOn($file,$txt,600,900,20,20,2+4+16,Default,6)         ;wywołanie okienka tekstowego
Else
	SplashImageOn($file,$file,800,600,20,100,2+16)                  ;wywołanie okienka z obrazkiem
EndIf
WEnd                                                                    ;koniec pętli


GUI[edytuj]

1. W oparciu o funkcję GUICtrlCreateInput napisać funkcję umożliwiającą wprowadzanie wyłącznie liczb dziesiętnych. Liczby mogą być dodatnie lub ujemne, całkowite lub z kropką dziesiętną. Stworzoną funkcję użyj w prostym skrypcie demonstracyjnym.

Wprowadzony string może mieć na początku znak minus (-), następnie dowolną ilość cyfr, kropkę dziesiętną i znowu dowolną ilość cyfr. Oczywiście znak minus i kropka są opcjonalne.

Minus może być tylko na początku, a kropka może wystąpić najwyżej jeden raz np.: -1.25, -.02, .1, 0.1, 356 itp.

Do sprawdzania poprawności wpisywanej liczby najprościej będzie użyć wyrażeń regularnych. Będzie ono wyglądać następująco: ^-?\d*\.?\d*$

Przykładowe rozwiązanie:

#include <GUIConstantsEx.au3>
GUICreate("Wprowadź liczbę",250,200,-1,250)
$f1=GUICtrlCreateInput("", 10, 5, 200, 20,2)    ;wyrównanie do lewej
$f2=GUICtrlCreateInput("", 10, 35, 200, 20,2)
$f3=GUICtrlCreateInput("", 10, 65, 200, 20,2)
$f4=GUICtrlCreateInput("", 10, 95, 200, 20,2)
$btn=GUICtrlCreateButton("Ok", 90, 140, 60, 20)
GUISetState()
Do
   $msg=GUIGetMsg()
   $l1= _GUICtrlReadInputNumber($f1)      ;liczby rzeczywiste
   $l2= _GUICtrlReadInputNumber($f2,"+")  ;liczby rzeczywiste dodatnia
   $l3= _GUICtrlReadInputNumber($f3,"I")  ;tylko liczby całkowite ze znakiem
   $l4= _GUICtrlReadInputNumber($f4,"I+") ;tylko liczby całkowite dodatnia
   If $msg=$btn Then ExitLoop
Until $msg=$GUI_EVENT_CLOSE
MsgBox(4096, "","Wprowadziłes liczbę: "&Number($l1)&"    "&Number($l2)&"    "&Number($l3)&"  i  "&Number($l4))

;================================================================================================================
;funkcja umożliwiająca wprowadzenie tylko stringu będącego prawidłowym zapisem liczby dziesiętnej
;do sprawdzenia poprawności stringu używamy wyrażenia regularnego
;aby odtworzyć wartość poprzednią wartość stringu przy kolejnym wywołaniu funkcji używamy
;zmiennej statycznej w postaci tablicy (aby można było obsłużyć jednocześnie większą ilość kontrolek)
;zadeklarowana ilość komórek powinna być większa od łącznej ilości kontrolek (na wszelki wypadek z dużym zapasem)
;Parametry:
;$handle_input - zaczep do kontrolki INPUT
;Parametr opcjonalny:
;$op="R+" lub $op="+" - liczby rzeczywiste dodatnie i 0
;$op="I"  - liczby całkowite
;$op="I+" - liczby całkowite dodatnie i 0
;dowolna inna wartość - liczba rzeczywista (domyślne)
;================================================================================================================
Func _GUICtrlReadInputNumber($handle_input,$op=Default)
   Local $liczba, $WR="^-?\d*\.?\d*$"
   ;deklarowanie statycznej tablicy do przechowywania aktualnej prawidłowej wartości wprowadzanego stringu
   Static $liczba1[100]
   If $op="R+" Or $op="r+" Or $op="+" Then $WR="^\d*\.?\d*$"
   If $op="I" Or $op="i" Then $WR="^-?\d*$"
   If $op="I+" Or $op="i+" Then $WR="^\d*$"
   $liczba=GUICtrlRead($handle_input)   ;odczytanie aktualnej wartości stringu
   If StringRegExp($liczba,$WR) Then
      $liczba1[$handle_input]=$liczba   ;jeżeli string jest prawidłowy to zostanie zapamiętany
   Else
      GUICtrlSetData($handle_input,$liczba1[$handle_input]) ;jeżeli nie to odtwarzamy poprzednią wersję
   EndIf
   Return $liczba
EndFunc


2. Korzystając z kontrolek GUI napisać skrypt wyświetlający na ekranie zegar analogowo cyfrowy. Aby zajmować jak najmniej miejsca na ekranie zegar powinien mieć możliwość wyświetlania okna bez belki i ramki. W tym stanie zegar powinien mieć atrybut "zawsze na wierzchu". Należy także zapewnić możliwość przemieszczanie zegara w wygodne dla użytkownika miejsce ekranu.

Wyświetlacz analogowy można by zrealizować rysowania w okienku graficznym, ale prościej będzie użyć jakiejś kontrolki odwzorowującej graficznie zadaną wartość. Do wyboru mamy suwak (SLIDER) lub pasek postępu (PROGRESS). Zdecydowałem się na suwak. Okienko GUI za pomocą parametru exstyle (0x800+8=0x808) ma ustawiony atrybut "zawsze na wierzchu", oraz styl okienka narzędziowego (dzięki temu ikona nie pojawi się na pasku zadań). Ponieważ dla style = 0xc00000 nie są wyświetlane przyciski systemowe okna, musimy je stworzyć sami. Przycisk "X" służy do zamykania okna, natomiast przycisk "S" jest przełącznikiem zmieniającym styl okna (okno z belką i ramką / okno bez belki i ramki). Wyświetlacz cyfrowy został zrealizowany za pomocą kontrolki LABEL.

Przykładowe rozwiązanie:

#include <GUIConstantsEx.au3>

Local $iS1, $msg, $fWSK=True

$hGUI=GUICreate("Zegar:", 255, 95, 600, 300, 0xc00000, 0x88)
GUISetBkColor(0x00e6ff)
GUICtrlSetDefBkColor(0x00e6ff)

$hGodziny = GUICtrlCreateSlider(14, 2, 230, 30)
GUICtrlSetLimit(-1, 23)   ;godziny

$hMinuty = GUICtrlCreateSlider(14, 24, 230, 22)
GUICtrlSetLimit(-1, 59)   ;minuty

$hSekundy = GUICtrlCreateSlider(14, 46, 230, 22)
GUICtrlSetLimit(-1, 59)   ;sekundy

$hZegar = GUICtrlCreateLabel("", 45, 68, 190, 40, 0x800)
GUICtrlSetFont(-1, 20, 1000, 2, "Comic Sans MS")
GUICtrlCreateLabel("H", 4, 6, 12, 12)
GUICtrlCreateLabel("M", 4, 28, 12, 12)
GUICtrlCreateLabel("S", 4, 50, 12, 12)

$hEnd = GUICtrlCreateButton("X", 245, 1, 10, 10)
GUICtrlSetBkColor(-1, 0xe07000)

$hStyle = GUICtrlCreateButton("S", 244, 20, 10, 10)
GUICtrlSetBkColor(-1, 0x00ff00)

GUISetState()

Do
   $iH=@HOUR     ;odczyt godziny
   $iM=@MIN      ;odczyt minuty
   $iS=@SEC      ;odczyt sekundy
   If $msg=$hStyle Then  ;obsługa przełącznika stylu okna
      GUISetStyle(0x80000000 * $fWSK + (0xc00000*(Not $fWSK)))
      $fWSK = Not $fWSK
   EndIf
   If $iS<>$iS1 Then ;zmiana ustawień gdy zmieniły się sekundy
      GUICtrlSetData($hGodziny, $iH) ;ustawienie suwaka godzin
      GUICtrlSetData($hMinuty, $iM)  ;ustawienie suwaka minut
      GUICtrlSetData($hSekundy, $iS) ;ustawienie suwaka sekund
      GUICtrlSetData($hZegar, $iH&" : " & $iM & " : " & $iS) ;wyświetlacz cyfrowy
      $iS1 = $iS
   EndIf
   $msg = GUIGetMsg()
 Until $msg = $GUI_EVENT_CLOSE Or $msg = $hEnd


Przejmowanie kontroli[edytuj]

1. W oparciu o zdobyte w tym rozdziale informacje, zmodyfikować program zegara z ćwiczeń w GUI tak, aby możliwa była regulacja przejrzystości okna zegara.

Wykorzystamy funkcję ustalającą stopień przejrzystości okna WinSetTrans. Funkcja ta działa na wszystkich oknach, tak utworzonych przez zewnętrzne procesy, jak i przez sam skrypt. Wystarczy znać zaczep do okna. Nie ma z tym problemu, ponieważ sami je utworzyliśmy. Do okna zegara dodajemy dwa przyciski, jeden ze znakiem +, drugi ze znakiem -. Naciśnięcie pierwszego powoduje, że okno staje się wyraźniejsze (mniejsze przezroczystość), drugiego jego zblednięcie (większa przezroczystość).

Przykładowe rozwiązanie:

#include <GUIConstantsEx.au3>

Local $iS1, $msg, $fWSK=True, $iTrans=255

$hGUI = GUICreate("Zegar:", 255, 95, 600, 300, 0xc00000, 0x88)
GUISetBkColor(0x00e6ff)
GUICtrlSetDefBkColor(0x00e6ff)

$hGodziny = GUICtrlCreateSlider(14, 2, 230, 30)
GUICtrlSetLimit(-1, 23)   ;godziny

$hMinuty = GUICtrlCreateSlider(14, 24, 230, 22)
GUICtrlSetLimit(-1, 59)   ;minuty

$hSekundy = GUICtrlCreateSlider(14, 46, 230, 22)
GUICtrlSetLimit(-1, 59)   ;sekundy

$hZegar = GUICtrlCreateLabel("", 45, 68, 190, 40, 0x800)
GUICtrlSetFont(-1, 20, 1000, 2, "Comic Sans MS")
GUICtrlCreateLabel("H", 4, 6, 12, 12)
GUICtrlCreateLabel("M", 4, 28, 12, 12)
GUICtrlCreateLabel("S", 4, 50, 12, 12)

$hEnd = GUICtrlCreateButton("X", 245, 1, 10, 10)
GUICtrlSetBkColor(-1, 0xe07000)

$hStyle = GUICtrlCreateButton("S", 244, 20, 10, 10)
GUICtrlSetBkColor(-1, 0x00ff00)

;dwa nowe przyciski
$hPlus = GUICtrlCreateButton("+", 244, 40, 10, 10)
GUICtrlSetBkColor(-1, 0xaaff00)
$hMinus = GUICtrlCreateButton("-", 244, 60, 10, 10)
GUICtrlSetBkColor(-1, 0xaaff00)

GUISetState()

Do
   $iH = @HOUR     ;odczyt godziny
   $iM = @MIN      ;odczyt minuty
   $iS = @SEC      ;odczyt sekundy
   Switch $msg
      Case $hStyle   ;obsługa przełącznika stylu okna
      GUISetStyle(0x80000000 * $fWSK + (0xc00000 * (Not $fWSK)))
      $fWSK = Not $fWSK
      Case $hPlus
	     $iTrans = min($iTrans+20, 255)
	     WinSetTrans($hGUI, "", $iTrans) ;zmniejszenie przezroczystości
	  Case $hMinus
		 $iTrans = max($iTrans-20, 30)
	     WinSetTrans($hGUI, "", $iTrans) ;zwiększenie przezroczystości
   EndSwitch
   If $iS <> $iS1 Then ;zmiana ustawień gdy zmieniły się sekundy
      GUICtrlSetData($hGodziny, $iH) ;ustawienie suwaka godzin
      GUICtrlSetData($hMinuty, $iM)  ;ustawienie suwaka minut
      GUICtrlSetData($hSekundy, $iS) ;ustawienie suwaka sekund
      GUICtrlSetData($hZegar, $iH & " : " & $iM&" : " & $iS) ;wyświetlacz cyfrowy
      $iS1 = $iS
   EndIf
   $msg = GUIGetMsg()
 Until $msg = $GUI_EVENT_CLOSE Or $msg = $hEnd

;funkcje pomocnicze
Func min($a, $b)
   If $a<=$b Then Return $a
   Return $b
EndFunc

Func max($a, $b)
   If $a<=$b Then Return $b
   Return $a
EndFunc


Tworzenie bibliotek[edytuj]

1. Napisać pozostałą część biblioteki matematycznej, oraz prosty skrypt testujący jej działanie.

Przykładowe rozwiązanie (zwróćmy uwagę, że funkcje _am(), _gm() i _permutation() są polimorficzne):

#include-once

; #INDEX# ====================================================================
; Nazwa .........: Mathematic function
; AutoIt Version : 3.3.8.1
; Language ......: Polish
; Description ...: Dodatkowe funkcje matematyczne (Additional math functions)
; Author(s) .....: Wasta (2012)
; ============================================================================

; #CURRENT# ==================================================================
;Const $_PI
;_max
;_min
;_sign
;_am
;_gm
;_log10
;_logA
;_sinh
;_cosh
;_QRoots
;_factorial
;_combination
;_combinationWR
;_variation
;_variationWR
;_permutation
;_Bin
;_BinToDec
; =============================================================================
Global Const $_PI = 3.14159265358979323846264338328

; #FUNCTION# ==================================================================
; Name...........: _max
; Description ...: Większy z dwóch parametrów (The larger of the two parameters)
; Syntax.........: _max($var1, $var2)
; Parameters ....: Dwie liczby rzeczywiste (Two real numbers)
; Return values .: Większy z dwóch parametrów (The larger of the two parameters)
Func _max ($iVar1, $iVar2)
   Return $iVar1>=$iVar2 ? $iVar1 : $iVar2
EndFunc

; #FUNCTION# ==================================================================
; Name...........: _min
; Description ...: Mniejszy z dwóch parametrów (The smaller of the two parameters)
; Syntax.........: _max($var1, $var2)
; Parameters ....: Dwie liczby rzeczywiste (Two real numbers)
; Return values .: Większy z dwóch parametrów (The smaller of the two parameters)
Func _min ($iVar1, $iVar2)
   Return $iVar1>=$iVar2 ? $iVar2 : $iVar1
EndFunc

; #FUNCTION# ==================================================================
; Name...........: _sign
; Description ...: Znak liczby (The sign of number)
; Syntax.........: _sign($var)
; Parameters ....: liczba rzeczywista (Real number)
; Return values .: -1 - $var<0
;                   0 - $var=0
;                   1 - $var>0
Func _sign ($iVar)
   Return ($iVar>0)-($iVar<0)
EndFunc

; #FUNCTION# ==================================================================
; Name...........: _am
; Description ...: Średnia arytmetyczna (The arithmetic mean)
; Syntax.........: _am($var1[, $var2])
;                : _am($array)
; Parameters ....: Dwie liczby rzeczywiste (Two real numbers)
;                : Jednowymiarowa tablica (One-dimensional array)
; Return values .: Success - Średnia arytmetyczna dwu liczb, lub elementów tablicy.
;                        (The arithmetic mean of two numbers, or elements of the array)
;                  Failure - "-1.#IND"
;                            @error=1
Func _am ($vVar1, $vVar2=False)
   Local $i, $iSum=0
   If @NumParams=2 Then Return ($vVar1+$vVar2)/2
   If @NumParams=1 Then
      If IsArray($vVar1) Then
         If UBound($vVar1,0)>1 Then
            SetError(1)
            Return "-1.#IND"
         EndIf
         $n=UBound($vVar1)
         For $i=0 To $n-1
            $iSum+=$vVar1[$i]
         Next
         Return $iSum/$n
      Else
         Return $vVar1
      EndIf
   EndIf
EndFunc

; #FUNCTION# ==================================================================
; Name...........: _gm
; Description ...: Średnia geometryczna (The geometric mean)
; Syntax.........: _gm($var1[, $var2])
;                : _gm($array)
; Parameters ....: Dwie liczby rzeczywiste dodatnie (Two positive real numbers)
;                : Jednowymiarowa tablica liczb dodatnich
;                  (One-dimensional array of positive numbers)
; Return values .: Success - Średnia geometryczna dwu liczb, lub elementów tablicy
;                            (The geometric mean of two numbers, or elements of the array)
;                  Failure - "-1.#IND" - tablica wielowymiarowa, lub występuje liczba <=0
;                            @error=1  - tablica wielowymiarowa (multidimensional array)
;                            @error=2  - występuje liczba <=0 (by a number <= 0)
Func _gm ($vVar1, $vVar2=False)
   Local $i, $n, $il=1
   If @NumParams=2 Then
      If $vVar1>0 And $vVar2>0 Then
         Return Sqrt($vVar1*$vVar2)
      Else
         SetError(2)
         Return "-1.#IND"
      EndIf
   EndIf
   If @NumParams=1 Then
      If IsArray($vVar1) Then
         If UBound($vVar1,0)<>1 Then
            SetError(1)
            Return "-1.#IND"
         EndIf
         $n=UBound($vVar1)
         For $i=0 To $n-1
            If $vVar1[$i]<=0 Then
               SetError(2)
               Return "-1.#IND"
            Else
               $il*=$vVar1[$i]
            EndIf
         Next
         Return $il^(1/$n)
      Else
         If $vVar1>0 Then
            Return $vVar1
         Else
            SetError(2)
            Return "-1.#IND"
         EndIf
      EndIf
   EndIf
EndFunc

; #FUNCTION# ==================================================================
; Name...........: _log10
; Description ...: Logarytm dziesiętny (Decimal logarithm)
; Syntax.........: _log10($var)
; Parameters ....: Liczba rzeczywista dodatnia (Positive real number)
; Return values .: Success - Logarytm dziesiętny (Decimal logarithm)
;                  Failure - "-1.#IND" - $var <= 0
;                            @error=1
Func _log10 ($iVar)
   If $iVar>0 Then Return Log($iVar)/Log(10)
   SetError(1)
   Return "-1.#IND"
EndFunc

; #FUNCTION# ==================================================================
; Name...........: _logA
; Description ...: Logarytm o dowolnej podstawie (Logarithm of any basis)
; Syntax.........: _logA($var, $base)
; Parameters ....: Liczby rzeczywiste dodatnie (Positive real numbers)
; Return values .: Success - Logarytm o dowolnej podstawie (The logarithm of any base)
;                  Failure - "-1.#IND" - $var <= 0 or $base <= 0 or $base = 1
;                  @error=1
Func _logA ($iVar, $iBase)
   If $iVar>0 And $iBase>0 And $iBase<>1 Then Return Log($iVar)/Log($iBase)
   SetError(1)
   Return "-1.#IND"
EndFunc

; #FUNCTION# ==================================================================
; Name...........: _sinh
; Description ...: Sinus hiperboliczny (Hyperbolic sine)
; Syntax.........: _sinh($var)
; Parameters ....: Liczba rzeczywista (Real number)
; Return values .: Sinus hiperboliczny (hyperbolic sine)
Func _sinh ($iVar)
   Return (Exp($iVar)- Exp(-$iVar))/2
EndFunc

; #FUNCTION# ==================================================================
; Name...........: _cosh
; Description ...: Cosinus hiperboliczny (Hyperbolic cosine)
; Syntax.........: _cosh($var)
; Parameters ....: Liczba rzeczywista (Real number)
; Return values .: Cosinus hiperboliczny (hyperbolic cosine)
Func _cosh ($iVar)
   Return (Exp($iVar)+ Exp(-$iVar))/2
EndFunc

; #FUNCTION# ==================================================================
; Name...........: _QRoots
; Description ...: Pierwiastki równania kwadratowego a*x^2 + b*x + c
;                  (Roots of a quadratic equation)
; Syntax.........: _QRoots($a, $b, $c)
; Parameters ....: Liczbay rzeczywiste (Real numbers)
; Return values .: 3-elementawa tablica wyników (Three-element array results)
;                  $res[0] - ilość pierwiastków (Number of roots)
;                  $res[1] - wartość 1 pierwiastka lub "-1.#IND" gdy nie ma pierwiastków
;                  $res[2] - wartość 2 pierwiastka lub "-1.#IND" gdy nie ma pierwiastków
;                  $res[2]=$res[1] if $res[0]=1
Func _QRoots ($iA, $iB, $iC)
   Local $iDelta, $aRes[3]=[0,"-1.#IND","-1.#IND"]
   $iDelta=$iB^2-4*$iA*$iC
   Select
      Case $iDelta=0
         $aRes[0]=1
         $aRes[1]=-$iB/(2*$iA)
         $aRes[2]=$aRes[1]
      Case $iDelta>0
         $aRes[0]=2
         $aRes[1]=(-$iB-Sqrt($iDelta))/(2*$iA)
         $aRes[2]=(-$iB+Sqrt($IDelta))/(2*$iA)
   EndSelect
   Return $aRes
EndFunc

; #FUNCTION# ==================================================================
; Name...........: _factorial
; Description ...: Silnia (Factorial)
; Syntax.........: _factorial($var)
; Parameters ....: Liczba naturalna 0-170 (Natural number)
; Return values .: Success - Silnia (Factorial)
;                  Failure - "-1.#IND"
;                  @error=1 - zły parametr (bad parameter)
;                  @error=2 - przekroczony zakres (range exceeded)
Func _factorial($iVar)
   If $iVar<0 Or (Not IsInt($iVar)) Then
      SetError(1)
      Return "-1.#IND"
   EndIf
   If $iVar>170 Then
      SetError(2)
      Return "-1.#IND"
   EndIf
   If $iVar=0 Then Return 1.0
   Return $iVar*_factorial($iVar-1)
EndFunc

; #FUNCTION# ==================================================================
; Name...........: _combination
; Description ...: Kombinacja (Combination)
; Syntax.........: _combination($k, $n)
; Parameters ....: Liczby naturalne 0-170 (Natural numbers)
; Return values .: Success - Kombinacja (Combination)
;                  Failure - "-1.#IND"
;                            @error=1
Func _combination($iK, $iN)
   Local $iFk=_factorial($iK), $iFn=_factorial($iN), $iFnk=_factorial($iN-$iK)
   If $iFk="-1.#IND" Or $iFn="-1.#IND" Or $iFnk="-1.#IND" Then
      SetError(1)
      Return "-1.#IND"
   EndIf
   Return $iFn/($iFk*$iFnk)
EndFunc

; #FUNCTION# ==================================================================
; Name...........: _combinationWR
; Description ...: Kombinacja z powtórzeniami (Combination with repetition)
; Syntax.........: _combinationWR($k, $n)
; Parameters ....: Liczby naturalne 0-170 (Natural numbers)
; Return values .: Success - Kombinacja (Combination)
;                  Failure - "-1.#IND"
;                            @error=1
Func _combinationWR($iK, $iN)
   Local $iFk=_factorial($iK), $iFkn1=_factorial($iK+$iN-1), $iFn1=_factorial($iN-1)
   If $iFk="-1.#IND" Or $iFkn1="-1.#IND" Or $iFn1="-1.#IND" Then
      SetError(1)
      Return "-1.#IND"
   EndIf
   Return $iFkn1/($iFk*$iFn1)
EndFunc

; #FUNCTION# ==================================================================
; Name...........: _variation
; Description ...: Wariacja (Variation)
; Syntax.........: _variation($k, $n)
; Parameters ....: Liczby naturalne 0-170 (Natural numbers)
; Return values .: Success - Wariacja (Variation)
;                  Failure - "-1.#IND"
;                  @error=1
Func _variation($iK, $iN)
   Local $iFn=_factorial($iN), $iFnk=_factorial($iN-$iK)
   If $iFn="-1.#IND" Or $iFnk="-1.#IND" Then
      SetError(1)
      Return "-1.#IND"
   EndIf
   Return $iFn/$iFnk
EndFunc

; #FUNCTION# ==================================================================
; Name...........: _variationWR
; Description ...: Wariacja z powtórzeniami (Variation with repetition)
; Syntax.........: _variationWR($k, $n)
; Parameters ....: Liczby naturalne 0-170 (Natural numbers)
; Return values .: Success - Wariacja z powtórzeniami (Variation with repetition)
;                  Failure - "-1.#IND"
;                            @error=1
Func _variationWR($iK, $iN)
   If $iK<0 Or (Not IsInt($iK)) Or $iN<0 Or (Not IsInt($iN)) Then
      SetError(1)
      Return "-1.#IND"
   EndIf
   Return $iN^$iK
EndFunc

; #FUNCTION# ==================================================================
; Name...........: _permutation
; Description ...: Permutacja (Permutation)
; Syntax.........: _permutation($n)
;                : _permutation($array) - permutacja z powtórzeniami
;                                         (Permutation with repetition)
; Parameters ....: Liczba naturalna 0-170 (Natural number)
;                : Jednowymiarowa tablica liczb naturalnych
;                  (One-dimensional array of natural numbers)
; Return values .: Success - Permutacja (Permutation)
;                  Failure - "-1.#IND"
;                            @error=1
Func _permutation($vVar)
   Local $iPer, $a, $f, $i, $m=1, $s=0
   If IsArray($vVar) Then
      $a=UBound($vVar)
      If UBound($vVar,0)>1 Then
         SetError(1)
         Return "-1.#IND"
      EndIf
      If UBound($vVar)>1 Then
         For $i=1 To $a-1
            $f=_factorial($vVar[$i])
            If $f="-1.#IND" Then
               SetError(1)
               Return "-1.#IND"
            EndIf
            $m*=$f
            $s+=$vVar[$i]
         Next
         If $s>$vVar[0] Then
            SetError(1)
            Return "-1.#IND"
         EndIf
         $f=_factorial($vVar[0])
         If $f="-1.#IND" Then
            SetError(1)
            Return "-1.#IND"
         EndIf
         $iPer=$f/$m
      Else
         $iPer=_factorial($vVar[0])
      EndIf
   Else
      $iPer=_factorial($vVar)
   EndIf
   If $iPer="-1.#IND" Then
      SetError(1)
   EndIf
   Return $iPer
EndFunc

; #FUNCTION# ==================================================================
; Name...........: _Bin
; Description ...: Zamiana wyrażenia na string liczby binarnej
;                  (Replacing the expression for the string of binary number)
; Syntax.........: _Bin($var, $len)
; Parameters ....: $var - liczba naturalna (Natural number)
; Return values .: Success - string liczby binarnej (string of binary number)
;                  Failure - "-1.#IND" - parametr ujemny (negative parameter)
;							 @error=1
Func _Bin($iVar)
   Local $sBin=""
   If $iVar<0 Then
      SetError(1)
      Return "-1.#IND"
   EndIf
   Do
      If Mod($iVar,2)=0 Then
         $iVar/=2
         $sBin="0"&$sBin
      Else
         $iVar=($iVar-1)/2
         $sBin="1"&$sBin
      EndIf
   Until $iVar=0
   Return $sBin
EndFunc

; #FUNCTION# ==================================================================
; Name...........: _BinToDec
; Description ...: Zamienia string liczby binarnej na liczbę dziesiętną
;                  (Converts binary number string to a decimal number)
; Syntax.........: _BinToDec($bin)
; Parameters ....: $bin - string liczby binarnej (string of binary number)
; Return values .: Success - liczba dziesiętna
;                  Failure - "-1.#IND" - zawiera znak inny niż 0 lub 1
;                                        (contains a character other than 0 or 1)
;                            @error=1
Func _BinToDec($sBin)
   Local $iLen=StringLen($sBin), $iDec=0, $i, $j, $a
   For $i=$iLen to 1 Step -1
      $j=$iLen-$i
      $a=StringMid($sBin,$i,1)
      If $a<>"0" And $a<>1 Then
         SetError(1)
         Return "-1.#IND"
      EndIf
      $iDec+=Number($a)*2^$j
   Next
   Return $iDec
EndFunc


Przykład programu testującego bibliotekę UDF (bibliteka powinna mieć nazwę math+.au3):

#include"Math+.au3"

MsgBox (0,"Max:",_max(1,2.2))
MsgBox (0,"Min:",_min(1,2.2))
MsgBox (0,"Sign",_sign(-17.4))
MsgBox (0,"Średnia arytmetyczna:",_am(1,2))
MsgBox (0,"Średnia arytmetyczna:",_am(1))
Dim $array[5]=[1,2,-3,4,-5.9]
MsgBox (0,"Średnia arytmetyczna:",_am($array)&@LF&@error)
Dim $array[2][2]=[[1,2],[3,4]]
MsgBox (0,"Średnia arytmetyczna:",_am($array)&@LF&@error)
Dim $array[5]=[1,2,3,4,5]
MsgBox (0,"Średnia geometyczna:",_gm($array)&@LF&@error)
MsgBox (0,"Średnia geometyczna:",_gm(2)&@LF&@error)
MsgBox (0,"Średnia geometyczna:",_gm(-1)&@LF&@error)
MsgBox (0,"Średnia geometyczna:",_gm(2, 3)&@LF&@error)
MsgBox (0,"Logarytm dziesiętny:",_log10(100))
MsgBox (0,"Logarytm o dowolnej podstawie:",_logA(8, 2))
MsgBox (0,"Sinus hiperboliczny:",_sinh(-2))
$t=_QRoots(1,2,1)
MsgBox (0,"Pierwiastki równania kwadratowego",$t[0]&@LF&$t[1]&@LF&$t[2])
MsgBox (0,"Silnia:",_factorial(10)&@LF&@error)
MsgBox (0,"Kombinacja:",_combination(6, 49)&@LF&@error)
MsgBox (0,"Kombinacja z powtórzeniami:",_combinationWR(6, 49)&@LF&@error)
MsgBox (0,"Permutacja:",_permutation(4)&@LF&@error)
Dim $array[3]=[4,2,2]
MsgBox (0,"Permutacja:",_permutation($array)&@LF&@error)
MsgBox (0,"Liczba binarna:",_Bin(666)&@LF&@error)
MsgBox (0,"Liczba binarna:",_Bin(-2)&@LF&@error)
MsgBox (0,"BIN>DEC:",_BinToDec(10)&@LF&@error)
MsgBox (0,"BIN>DEC:",_BinToDec(12)&@LF&@error)


Korzystanie z bibliotek DLL[edytuj]

1. W oparciu o funkcję GUICtrlCreateInput napisać funkcję umożliwiającą wprowadzanie stringów określonego typu, np.:liczby rzeczywiste i całkowite, szesnastkowe, ósemkowe, dwójkowe, itp.

Ponadto używając funkcji systemowych wywoływanych przez DllCall(), umożliwić nawigację między polami INPUT klawiszami ENTER oraz strzałka w górę i w dół.

Stworzoną funkcję użyj w prostym skrypcie demonstracyjnym.

Zadanie jest rozwinięciem zadania z rozdziału GUI. Została zmieniona i rozbudowana składnie funkcji, ponadto dodano część obsługującą klawisze nawigacyjne.

Rozpoznanie użycia dodatkowych klawiszy nawigacyjnych uzyskano za pomocą funkcji systemowej GetAsyncKeyState z biblioteki "user32.dll".

Jej składnia wygląda następująco:

SHORT WINAPI GetAsyncKeyState(
 __in  int vKey
);

Funkcja przyjmuje jeden parametr typu int, który jest kodem sprawdzanego klawisza.

Wartość zwracana jest >0 gdy klawisz został wciśnięty.

Kody sprawdzanych klawiszy to (szesnastkowo):

ENTER - 0x0d

strzałka w dół - 0x28

strzałka w górę - 0x26

Przykładowe rozwiązanie:

#include <GUIConstantsEx.au3>

$HWin = GUICreate("Wprowadź znaki:",380,200,-1,250)
GUICtrlCreateLabel("Dowolne znaki:", 10, 5)
$hF1  = GUICtrlCreateInput("", 155, 5, 200, 20,0)
GUICtrlCreateLabel("Liczba rzeczywista:", 10, 35)
$hF2  = GUICtrlCreateInput("", 155, 35, 200, 20,2)
GUICtrlCreateLabel("Liczba całkowita dodatnia i 0:", 10, 65)
$hF3  = GUICtrlCreateInput("", 155, 65, 200, 20,2)
GUICtrlCreateLabel("Liczbe szesnastkowa:", 10, 95)
$hF4  = GUICtrlCreateInput("", 155, 95, 200, 20,2)
$hBtn = GUICtrlCreateButton("Ok", 170, 160, 60, 20)
GUISetState()

Do
   $msg=GUIGetMsg()
   $sL1 = _GUICtrlInputRead($hF1, "", "", "begin", $hF4)
   $sL2 = _GUICtrlInputRead($hF2, "", "R")
   $sL3 = _GUICtrlInputRead($hF3, "", "I+")
   $sL4 = _GUICtrlInputRead($hF4, "", "X", "end", $hF1)
Until $msg = $GUI_EVENT_CLOSE Or $msg = $hBtn

MsgBox(0, "Test:", "Wprowadziłeś: "&@LF&@LF&$sL1&@LF&$sL2&@LF&$sL3&@LF&$sL4, 5)

#cs=====================================================================
Funkcja umożliwia określenie jakiego typu string ma być
akceptowany przez okienko INPUT. Umożliwia wprowadzanie tylko takich
znaków, które pasują do zadanego typu stringu.
Ponadto umożliwia przemieszczanie się po okienkach INPUT za pomocą
klawiszów ENTER, strzalka w górę i w dół

Wartosć zwracana - prawidłowy wprowadzony w okienku łańcuch.

Składnia:
---------
_GUICtrlInputRead ( $hIDCtrl, [ $hWin [, $sOp [, $sPos [, $hJump ]]]] )

Parametry:
----------
$hIDCtrl - ID kontrolki (zwracane przez GUICtrlCreateInput)

$hWin - uchwyt do okna GUI, lub jego nazwa,
		domyślna wartość "" oznacza to samo co "[ACTIVE]"

$sOp - rodzaj wprowadzanego stringu
--------------------------------------------------------------
""   - dowolne znaki (wartość domyślna)
"R"  - liczba rzeczywista
"R+" - liczby rzeczywiste dodatnie i 0
"I"  - liczby całkowite
"I+" - liczby całkowite dodatnie i 0
"X"  - liczba heksadecymalna
"O"  - liczba ósemkowa
"B"  - liczba dwójkowa
"A"  - tylko litery (także polskie)
"A+" - tylko wielkie litery
"A-" - tylko małe litery
dowolna inna wartość jest traktowana jako wyrazenie regularne

$sPos - pozycja kontrolki
--------------------------------------------------------------
""       - wewnętrzne, wartość domyślna
"begin"  - początkowe
"end"    - końcowe

$hJump - ID kontrolki do której należy przeskoczyć po wyjści poza początek
		lub koniec, tylko dla $sPos="begin" i $sPos="end"
#ce;===================================================================

Func _GUICtrlInputRead($hIDCtrl, $hWin="", $sOp="", $sPos="", $hJump=0)
   Local $sStr, $sWR, $hCtrl
   Static $aStr1[99]
   Switch $sOp
      Case Default, ""
         $sWR=".*"
      Case "R", "r"
         $sWR="^-?\d*\.?\d*$"
      Case "R+","r+"
         $sWR="^\d*\.?\d*$"
      Case "I","i"
         $sWR="^-?\d*$"
      Case "I+","i+"
         $sWR="^\d*$"
      Case "X","x"
         $sWR="^[0-9a-fA-F]*$"
      Case "O","o"
         $sWR="^[0-7]*$"
      Case "B","b"
         $sWR="^[01]*$"
      Case "A","a"
         $sWR="^(?i)[a-ząęćłńóśżźĄĆĘŁŃÓŚŻŹ ]*$"
      Case "A+","a+"
         $sWR="^[A-ZĄĆĘŁŃÓŚŻŹ ]*$"
      Case "A-","a-"
         $sWR="^[a-ząęćłńóśżź ]*$"
      Case Else
         $sWR=$sOp
   EndSwitch
   $sStr = GUICtrlRead($hIDCtrl)
   If StringRegExp($sStr, $sWR) Then
      $aStr1[$hIDCtrl] = $sStr
   Else
      GUICtrlSetData($hIDCtrl, $aStr1[$hIDCtrl])
   EndIf
;---------obsłga klawiszy nawigacyjnych----------
   If $hWin = "" Or $hWin = Default Then $hWin = "[ACTIVE]"
   $hCtrl = ControlGetHandle($hWin,"", $hIDCtrl)
   If ControlGetHandle($hWin, "", ControlGetFocus($hWin)) = $hCtrl Then
      If DllCall("user32.dll", "short", "GetAsyncKeyState", "int", 0x0d)[0] Then
         Send("{TAB}")
         Sleep(300)
      EndIf
      If DllCall("user32.dll", "short", "GetAsyncKeyState", "int", 0x28)[0] Then
         Send("{TAB}")
         If $hJump>0 And $sPos = "end" Then ControlFocus($HWin, "", $hJump)
         Sleep(300)
      EndIf
      If DllCall("user32.dll", "short", "GetAsyncKeyState", "int", 0x26)[0] Then
         Send("+{TAB}")
         If $hJump>0 And $sPos = "begin" Then ControlFocus($hWin, "", $hJump)
         Sleep(300)
      EndIf
   EndIf
;-----------------------------------------------
   Return $sStr
EndFunc


Konsola tekstowa[edytuj]

1. Napisać skrypt umożliwiający uruchamiane w trybie interakcji poleceń i skryptów napisanych w języku interpretera poleceń "cmd.exe". Wyświetlanie wyników i komunikatów błędów w MsgBox.

Przykładowe rozwiązanie:

#include <Constants.au3>
#include <GUIConstantsEx.au3>

GUICreate("Edytor", 300, 600, 800, 250)
$hEdit  = GUICtrlCreateEdit("", 10, 10, 280, 500)
$hStart = GUICtrlCreateButton("Wykonać", 10, 560, 100)
$hExit  = GUICtrlCreateButton("Rezygnacja", 190, 560, 100)
GUISetState()

Do
   Do
      $msg = GUIGetMsg()
      If $msg = $GUI_EVENT_CLOSE Or $msg=$hExit Then Exit
   Until $msg = $hStart

   $hID = Run("cmd.exe ", "", "", $STDERR_CHILD + $STDOUT_CHILD + $STDIN_CHILD)
   $sMes = ""
   $sErrmes = ""
   $sCode = GUICtrlRead($hEdit)
   If StringRight($sCode, 1) <> @LF Then $sCode &= @LF
   StdinWrite($hID,$sCode)
   StdinWrite($hID)

   Do
      $sMes &= StdoutRead($hID)
   Until @error

   Do
      $sErrmes &= StderrRead($hID)
   Until @error

   If $sErrmes <> "" Then
	 MsgBox(0, "Błąd:", $sErrmes)
      Else
	 MsgBox(0, "Wynik:", $sMes)
   EndIf
Until False