DCL okna dialogowe dla zaawansowanych, AUTO CAD


DCL -- okna dialogowe dla zaawansowanych

Cały kurs, który napisałem, był tworzony od "zera", tak aby wraz z kolejnymi mi wzrastał ich stopień trudności. Rozwiązań, które tu umieściłem, nie spotkacie Państwo w żadnym programie na rynku. Co więcej, część przykładów powstała tylko i wyłącznie na użytek tego kursu. Na pytanie o zasadność nauki programowania z wykorzystaniem okien dialogowych odpowiedź jest prosta. DCL będzie funkcjonował tak długo, jak długo w AutoCAD-zie utrzymywana będzie możliwość pisania programów w języku AutoLisp. Co do przyszłości języka DCL, niech za odpowiedź posłuży Państwu ten odnośnik do strony www: http://www.objectdcl.com/.

Lekcja 1 -- Zagadnienie ukrywania okien dialogowych

0x01 graphic

Tematem lekcji pierwszej jest stworzenie programu obliczającego odległość między dwoma wskazanymi punktami i wyświetlenie wyniku w oknie dialogowym w okienku edycyjnym. W przykładzie tym zetkniemy się z:

  1. zagadnieniem "ukrywania okna dialogowego".

    Okna dialogowe programie AutoCAD są "modalne", tzn. nie można wywołać żadnej komendy, gdy wyświetlone jest równocześnie okno dialogowe. Dlatego na czas, gdy będziemy wskazywać dwa punkty, między którymi chcemy zmierzyć i wyświetlić odległość, musimy usunąć z pamięci AutoCAD-a (potocznie "ukryć").

  2. funkcję standardową AutoCAD-a Getorient.

    Funkcje Getangle i Getorient wstrzymują swoje działanie w oczekiwaniu na wprowadzenie przez użytkownika wartości kąta z linii poleceń AutoCAD-a lub zdefiniowanie go poprzez wskazanie punktów na ekranie. Dla funkcji Getangle kąt zerowy ma zawsze kierunek poziomy w prawo ("wschód" lub godzina 3.). Dla funkcji
    Getorient kąt zerowy wyznacza wartość zmiennej ANGBASE, która może być ustawiona na dowolny kąt. Obie funkcje zwracają wartości kąta (wartości rzeczywiste) w radianach, mierzonych od bazy (kąta zerowego) w kierunku przeciwnym do ruchu wskazówek zegara. Jako odpowiedź dla obu tych funkcji, użytkownik może podać dane w linii poleceń lub wskazać punkty na ekranie z wykorzystaniem licznika (w tym przykładzie jest nim what_next) do sterowania przebiegiem programu.

Pisanie programu rozpoczynamy od utworzenia dwóch plików tekstowych:

  • lisp_1.lsp -- jest plikiem tekstowym AutoLisp-owym zawierającym kod naszego programu,

  • lisp_1.dcl -- jest plikiem tekstowym zawierającym definicję okna dialogowego dla pliku lispowego.

Do utworzenia tych plików możemy wykorzystać dowolny edytor tekstów. Do tego celu doskonale nadaje się np. Notatnik, który standardowo znajduje się w systemie Windows. Za korzystaniem z notatnika przemawia fakt, że możemy z niego korzystać, nie opuszczając AutoCAD-a.

W linii komend wpisujemy notepad i potwierdzamy klawiszem Enter. AutoCAD wyświetla zachętę do wpisania nazwy pliku, który chcemy edytować.

0x01 graphic

Rys. 1. Widok linii komend z pisaną nazwą pliku, który chcemy edytować w notatniku Windows

Wpisujemy lisp_1.lsp i potwierdzamy, naciskając Enter. Jeżeli plik ten nie zostanie znaleziony, zostaniemy o tym poinformowani przez AutoCAD-a i zapytani, czy chcemy utworzyć nowy plik o takiej nazwie.

0x01 graphic

Rys. 2. Okno informacyjne AutoCAD-a

Klikamy przycisk Tak, co powoduje uruchomienie notatnika z nowoutworzonym przez nas plikiem.

Zapisujemy go w dowolnym katalogu znajdującym się w ścieżce przeszukiwania AutoCAD-a. W naszym przypadku niech to będzie katalog o nazwie DCL na dysku C.

Powtarzamy te same czynności dla pliku lisp_1.dcl i zapisujemy go w tym samym katalogu.

0x01 graphic

Rys. 3. Program Notatnik z utworzonym nowym plikiem

W pliku lisp_1.dcl umieszczamy definicję nowego okna dialogowego, które nazywa się Program Lisp_1 i zawiera tylko przyciski Ok i Cancel.

dialog1 : dialog {

label = "Program Lisp_1";

}

ok_cancel;

}

W pliku lisp_1.lsp umieszczamy z kolei wpis:

(defun c:lisp_1 () ;[1]

(setq dcl_id (load_dialog "lisp_1")) ;[2]

(if(not(new_dialog "dialog1" dcl_id))(exit)) ;[3]

(start_dialog) ;[4]

(unload_dialog dcl_id) ;[5]

);defun c:lisp_1 ;[6]

  1. W pierwszej linii za pomocą funkcji defun umieszczamy wywołanie programu. Wywołanie jest to ciąg znaków, po wpisaniu których, dany program zostanie uruchomiony.

  2. W linii (setq dcl_id (load_dialog "lisp_1")) przypisujemy zmiennej dcl_id wartość (load_dialog "lisp_1") czyli "podpowiadamy", że definicja okna dialogowego znajduje się w pliku lisp_1.dcl.

  3. Linia (if(not(new_dialog "dialog1" dcl_id))(exit)) powoduje, że AutoCAD przeszukuje plik lisp_1.dcl w poszukiwaniu identyfikatora okna dialogowego dialog1 (funkcja new_dialog inicjuje i wyświetla okno dialogowe).
    W jednym pliku dcl może znajdować się wiele definicji okien dialogowych np.
    dialog1, dialog2 itd. Dlatego potrzebny jest identyfikator jednoznacznie łączący plik AutoLispu z definicją okna dialogowego.

  4. start_dialog rozpoczyna pobieranie informacji od użytkownika z okna dialogowego zainicjowanego przez wywołanie funkcji new_dialog.

  5. unload_dialog dcl_id usuwa z pamięci wskazany plik DCL.

  6. nawias zamykający wywołanie funkcji lisp_1.

Po zapisaniu zmian dokonanych przez nas w obu plikach przystępujemy do sprawdzenia działania programu lisp_1). W tym celu w linii komend AutoCAD-a wpisujemy: (load lisp_1) i zatwierdzamy klawiszem Enter.

Powinniśmy zobaczyć okno dialogowe widoczne na rysunku 4.

0x01 graphic

Rys. 4. Okno dialogowe programu lisp_1.lsp

Na tym etapie warto jest zachować pliki lisp_1.lsp i lisp_1.dcl w innym katalogu i traktować je następnym razem jako szablon.

Następnym krokiem będzie dodanie do naszego okna dialogowego dwóch nowych elementów.

  • Okna edycyjnego (edit_box), w którym będziemy umieszczać wynik działania naszego programu czyli wartość zmierzonego kąta;

  • Przycisku (button).

Umieszczamy pomiędzy liniami label = "Lisp_1"; oraz ok_cancel; Następujące linie kodu:

: edit_box { -

label = "Wartość:";

key = "okno";

mnemonic = "W";

width = 25;

}

: button {

label = "Kat";

key = "kat";

mnemonic = "K";

}

gdzie:

  • label -- określa tekst wyświetlony wewnątrz wycinka,

  • Key -- określa nazwę, za pomocą której program odwołuje się do okna dialogowego,

  • Mnemonik -- określa znak służący do wywoływania elementu okna z klawiatury,

  • Width -- określa szerokość wycinka.

Zapisujemy ponownie oba pliki i wpisujemy z klawiatury (load "lisp_1"). Powinniśmy zobaczyć okno dialogowe widoczne na poniższym rysunku.

0x01 graphic

Rys. 5. Widok okna programu po dodaniu dwóch nowych elementów

Mamy gotowe okno dialogowe, które musimy teraz "oprogramować".

Za linią z wywołaniem programu umieszczamy linię (setq il " ") -- nadajemy zmiennej il wartość " " Zmienną il wykorzystamy do przechowywania wartości obliczonego kąta. Dzięki temu, że umieścimy w oknie edycyjnym spację, będzie ono sprawiało wrażenie pustego. Linia (set_tile "okno" il) ustawia wartość wycinka o kluczu "okno" na wartość, jaką w danej chwili posiada zmienna il. Do przetestowania tej fazy ćwiczenia warto na moment zamiast (setq il " ") wpisać (setq il "test"), ponieważ spacji tak czy owak byśmy nie zobaczyli, więc nie moglibyśmy stwierdzić, czy nasz program działa prawidłowo.

Listing pliku lisp_1.lsp:

(defun c:lisp_1 ()

(setq il "Test")

(setq dcl_id (load_dialog "lisp_1"))

(if(not(new_dialog "dialog1" dcl_id))(exit))

(set_tile "okno" il)

(start_dialog)

(unload_dialog dcl_id)

);defun c:lisp_1

Listing pliku lisp_1.dcl:

dialog1 : dialog {

label = "Lisp_1";

: edit_box {

label = "Wartość:";

key = "okno";

mnemonic = "W";

width = 25;

}

: button {

label = "Kat";

key = "kat";

mnemonic = "K";

}

ok_cancel;

}

Po zapisaniu obu tych plików i wpisaniu z klawiatury (load "lisp_1") oraz nacisnięciu klawisza Enter, nasz program został wczytany do AutoCAD-a. Uruchamiamy go, wpisując w linii poleceń: lisp_1 i zatwierdzając Enterem. Efekt powinien być, taki jak na rysunku poniżej.

0x01 graphic

Rys. 6. Okno dialogowe z ustawioną w oknie edycyjnym wartością "Test"

Czas na to, aby napisać to, co program ten ma robić -- w naszym przypadku mierzyć kąt. Definiuje to w całości poniższa linia.

(setq il (rtos (getorient "\nWskaz :")))

Aby przetestować działanie tego "jednolinijkowego" programu, wystarczy przepisać tą linie w linii komend AutoCAD-a i zatwierdzić Enterem.

0x01 graphic

Rys. 7. Test działania programu w linii komend AutoCAD-a

AutoCAD wyświetla w linii komend zachętę do wskazania przez użytkownika punktu na ekranie, po wskazaniu pierwszego, wyświetli zachętę do wskazania drugiego punktu, poczym przypisze wartość obliczonego kąta do zmiennej il. Wartość, jaką ma zmienna il, możemy sprawdzić, wpisując w linii komend !il. Jeśli program obliczeniowy składałby się z większej ilości linii kodu, warto do testowania go stworzyć osobny plik Autolisp-u, a dopiero po sprawdzeniu działania umieścić go w pliku programu z obsługą okna dialogowego.

Przed przystąpieniem do dalszej części ćwiczenia muszę państwu wyjaśnić, na czym polega "ukrywanie" okien dialogowych w programie AutoCAD i dlaczego to robimy. Te okna dialogowe są określane jako"modalne", tzn. nie można wywołać żadnej komendy, gdy wyświetlone jest równocześnie okno dialogowe. Dlatego na czas, gdy będziemy wskazywać dwa punkty, między którymi chcemy zmierzyć i wyświetlić odległość, musimy usunąć z pamięci AutoCAD-a (mówiąc potocznie "ukryć"). Wykorzystujemy w tym celu funkcję done_dialog, która kończy działanie i wyświetlanie bieżącego okna dialogowego.

Pierwszym krokiem jest umieszczenie wewnątrz programu lisp_1 dodatkowej funkcji -- w naszym przypadku będzie to show_dialog i przeniesienie do niej linii kodu, które odpowiadają za obsługę okna dialogowego, oraz drugiej, która odpowiada za pobieranie danych od użytkownika i oblicza na ich podstawie wartość kąta.

Listing pliku lisp_1.lsp z dokonanymi zmianami (plik lisp_1.dcl nie zmienił się):

(defun c:lisp_1 ()

(setq il " ")

(defun show_dialog ()

(setq dcl_id (load_dialog "lisp_1"))

(if(not(new_dialog "dialog1" dcl_id))(exit))

(set_tile "okno" il)

(action_tile "kat" "(done_dialog 2)")

(start_dialog)

(unload_dialog dcl_id)

);defun show_dialog

(defun get_angle ()

(setq il (rtos (getorient "\nWskaz :")))

);defun

(show_dialog)

(get_angle)

(show_dialog)

);defun c:lisp_1

Wczytujemy program lisp_1.lsp do AutoCAD-a i uruchamiamy go, wpisując z klawiatury lisp_1 i naciskając Enter. Otwarte zostało okno dialogowe programu, ponieważ linia (show_dialog) wywołała jego obsługę.

Następnie, gdy wciśniemy przycisk Kąt za pomocą funkcji done_dialog usuwamy okno dialogowe z pamięci czyli, mówiąc potocznie, "ukrywamy" je. Następna linia (get_angle) ustala na podstawie uzyskanych danych wartość obliczonego kąta. Po zakończeniu działania tej funkcji uruchamiana jest ponownie (show_dialog), która wyświetla w oknie edycyjnym wartość mierzonego kąta.

0x01 graphic

Rys. 8. Okno dialogowe z widoczną w okienku edycyjnym wartością zmierzonego kąta

Doszliśmy teraz do miejsca, w którym nasz program spełnia nasze założenia. Jednak po kilkukrotnym uruchomieniu nasuwa się oczywista konkluzja -- program ten jest "liniowy", to znaczy:
uruchamiamy program -> wyświetlone zostaje okno dialogowe -> wciskamy przycisk Kąt -> uruchamiana jest funkcja get_angle obliczająca kąt na podstawie pobranych punktów -> ponownie wyświetlone zostaje okno dialogowe z wartością obliczonego kąta umieszczoną w oknie edit_box -> zakończenie programu.

A co w sytuacji, gdy chcielibyśmy pomierzyć kilkanaście kątów na jeden raz? Musielibyśmy kilkanaście razy uruchamiać ten program. Pytanie jak go ulepszyć, aby nie było to konieczne?

Możemy umieścić w programie pętlę While, która tak długo, jak długo wciskalibyśmy przycisk Kąt, wyliczałaby nam kolejne wartości kątów, zaś zakończenie pracy z programem następowałoby po wciśnięciu klawisza Ok lub Anuluj.

Dlatego też zwróćmy uwagę na to, co dzieje się w linii (action_tile "kat" "(setq what_next 1)(done_dialog 2)"). Po wciśnięciu przycisku Kąt wartość zmiennej what_next jest równe 1, po czym znika okno dialogowe.

Dzięki temu w linii (while (> what_next 0)(get_angle)), dopóki zmienna what_next jest mniejsza od 0 (a jest bo jest równa 1) uruchamiana jest funkcja get_angle.

Co zrobić jednak, aby nasze okno dialogowe nie wyświetlało się w nieskończoność?

Problem ten rozwiązuje wpis w linii (setq what_next nil) -- nadaje on zmiennej what_next wartość nil i wyswietlone zostaje okno dialodowe. Teraz, gdy what_next = nil nie jest większe od 0, a więc warunek zwhat_next>0 nie jest spełniony, nie jest wywoływana funkcja get_angle. Dlatego naciśnięcie przycisków Ok i Cancel powoduje wyjście z programu.

Reasumując, jak długo wciskać będziemy przycisk Kąt (mamy wtedy what_next = 1 > 0), tak długo będzie się pojawiać okno dialogowe z wyświetloną w oknie edycyjnym (edit_box) wartością zmierzonego kąta w radianach.

Pozwala to użytkownikowi na kilkukrotne zmierzenie kąta bez opuszczania programu.

Listing pliku lisp_1.lsp:

(defun c:lisp_1 ()

(setq il " ")

(defun show_dialog ()

(setq dcl_id (load_dialog "lisp_1"))

(if(not(new_dialog "dialog1" dcl_id))(exit))

(set_tile "okno" il)

(action_tile "okno" "(setq il )")

(action_tile "kat" "(setq what_next 1)(done_dialog 2)")

(action_tile "accept" "(done_dialog 1)")

(action_tile "cancel" "(done_dialog 0)")

(start_dialog)

(unload_dialog dcl_id)

);defun show_dialog

(defun get_angle ()

(setq il (rtos (getorient "\nWskaz :")))

(setq what_next nil)

(show_dialog)

);defun

(show_dialog)

(while (> what_next 0)(get_angle))

(princ)

);defun c:lisp_1

Lekcja 2 -- Wyświetlanie dowolnego pliku tekstowego w oknie dialogowym

0x01 graphic

W dzisiejszej lekcji wykorzystamy okno dialogowe z polem kartotekowym do wyświetlenia dowolnego pliku tekstowego.

Założenia są następujące -- możliwe będzie edytowanie pliku o dowolnej nazwie z dowolnym rozszerzeniem.

W przykładzie tym zetkniemy się z :

  1. Funkcją AutoLispu Getfiled.

Funkcja Getfiled żąda od użytkownika podania nazwy pliku, wyświetlając standardowe okno plików AutoCAD-a, oraz zwraca tę nazwę pliku.

Składnia to: (getfiled title default ext flags).

Argument title określa nagłówek całego okna dialogowego, argument default definiuje standardową (proponowaną) nazwę pliku (może być łańcuch pusty [" "] a argument ext jest standardowym (proponowanym) rozszerzeniem nazwy pliku. Podanie łańcucha pustego [" "] jako argumentu ext jest równoważne proponowanemu rozszerzeniu * (wszystkie typy plików). Jeśli podany plik jest typu dwg, funkcja getfiled wyświetla podgląd obrazu w oknie dialogowym. Argument flags jest liczbą całkowitą, sterującą zachowaniem się okna dialogowego.

  • Flag = 1 -- powinien być ustawiony wówczas, gdy program ma domagać się od użytkownika podania nazwy nowego pliku do utworzenia,

  • Flag = 2 -- blokuje możliwość użycia przycisku napisz,

  • Flag = 4 -- pozwala użytkownikowi ustalić dowolne rozszerzenie nazwy pliku lub nawet brak rozszerzenia,

  • Flag = 8 -- jeśli jednocześnie bit 3 jest ustawiony funkcja poszukuje nazwy pliku w bibliotecznej ścieżce przeszukiwań.

Pisanie programu zwyczajowo rozpoczynamy od wykorzystania szablonów plików lisp_1.lsp i lisp_1.dcl, zapisując je pod nazwami odpowiednio:

lisp_2.dcl:

Dialog2 : dialog {

label = "Program Lisp_2";

}

ok_cancel;

}

lisp_2.lsp:

(defun c:lisp_2 ()

(setq dcl_id (load_dialog "lisp_2"))

(if(not(new_dialog "dialog1" dcl_id))(exit))

(start_dialog)

(unload_dialog dcl_id)

);defun c:lisp_2

Wczytujemy program lisp_2.lsp, wpisując w linii komend AutoCAD-a (load "lisp_2") i naciskając Enter, a następnie uruchamiamy go z klawiatury, wpisując wywołanie lisp_2 oraz naciskając Enter.

0x01 graphic

Rys. 1. Szablon okna dialogowego z widocznymi jedynie przyciskami Ok i Anuluj

Dodajemy do naszego szablonu okna potrzebne elementy wg schematu widocznego na rysunku poniżej.

0x01 graphic

Rys. 2. Struktura okna dialogowego

Po ich dodaniu nasze okno powinno wyglądać w sposób następujący:

0x01 graphic

Rys. 3. Wygląd okna dialogowego

Widok pliku lisp_2.dcl po umieszczeniu w nim wszystkich wycinków.

dialog2: dialog {

label = " Podgląd plików tekstowych";

:list_box {

key = "txt_view";

label = " ";

width = 80;

height = 25;

}

ok_cancel;

}

Przystępujemy do "oprogramowania" elementów okna dialogowego poprzez dodanie w pliku lisp_2.lsp lini kodu do obsługi poszczególnych elementów okna dialogowego.

W pliku lisp_2.lsp umieszczamy z kolei:

  1. (defun C:lisp_2 (/ nazwa_pliku wiersz)

za pomocą funkcji defun umieszczamy wywołanie programu Lisp_2. Wywołanie to jest ciągiem znaków, po wpisaniu których, dany program zostanie uruchomiony. Program Lisp_2 został wywołany z dwoma argumentami: nazwa_pliku i wiersz,

  1. (setq nazwa_pliku (open

  2. (getfiled "Podgląd pliku tekstowego" "" "" 0) "r"))

0x01 graphic

Rys. 4.

  1. (setq dcl_id (load_dialog "lisp_2"))

przypisujemy zmiennej dcl_id wartość (load_dialog "lisp_2"), czyli "podpowiadamy", że definicja okna dialogowego znajduje się w pliku lisp_2.dcl,

  1. (if(not(new_dialog "dialog2" dcl_id))(exit))

AutoCAD przeszukuje plik lisp_2.dcl w poszukiwaniu identyfikatora okna dialogowego dialog2 (funkcja new_dialog inicjuje i wyświetla okno dialogowe),

  1. (start_list "txt_view")

przetwarzanie nowej listy autolispu w polu listy DCL,

  1. (while (setq wiersz (read-line nazwa_pliku))(add_list wiersz));

czytanie pliku wiersz po wierszu. Przypisujemy zmiennej wiersz linię tekstu pobieraną z pliku nazwa_pliku i tak długo jak długo istnieją kolejne wiersze w pliku, są one przypisywane do zmiennej wiersz, ta z kolei jest dodawana do listy DCL,

  1. (end_list)

koniec przetwarzania pliku (gdy funkcja read-line napotka koniec pliku),

  1. (close nazwa_pliku)

zamknięcie pliku,

  1. (start_dialog)

rozpoczyna pobieranie informacji od użytkownika z okna dialogowego zainicjowanego przez wywołanie funkcji new_dialog,

  1. (term_dialog)

kończy działanie wszystkich bieżących okien dialogowych, tak, jak by użytkownik je anulował,

  1. (Load_dialog dcl_id)

wczytuje wskazany plik DCL,

  1. (princ)

czysczenie linii komend,

  1. )

koniec funkcji Lisp_2.

Lekcja 3 - Wyświetlanie napisu w polu tekstowym cz.1

0x01 graphic

Tematem trzeciej lekcji jest stworzenie funkcji sterującej wyświetlaniem napisu w polu tekstowym za pomocą dwóch przycisków.

Zakładamy, że po wciśnięciu przycisku Jest napis w polu tekstowym pojawią się słowa "Wydawnictwo Helion". Po wciśnięciu przycisku Nie ma napisu pole tekstowe zostanie wyczyszczone. Przy pisaniu tego programu wykorzystamy szablony plików lisp_1.lsp i lisp_1.dcl, zapisując je pod nazwami odpowiednio:

lisp_3.dcl:

Dialog3 : dialog {

label = "Program Lisp_3";

}

ok_cancel;

}

lisp_3.lsp:

(defun c:lisp_3 ()

(setq dcl_id (load_dialog "lisp_3"))

(if(not(new_dialog "dialog1" dcl_id))(exit))

(start_dialog)

(unload_dialog dcl_id)

);defun c:lisp_3

Wczytujemy program lisp_3.lsp, wpisując w linii komend AutoCAD-a (load "lisp_3") i naciskając Enter, a następnie uruchamiamy go z klawiatury, wpisując wywołanie lisp_3 oraz Enter.

Zakładamy, że okno dialogowe będzie podzielone na dwie pionowe części. Po lewej stronie umieścimy pole tekstowe. Po prawej stronie znajdą się dwa przyciski. Wszystkie elementy okna, dla lepszego efektu wizualnego, umieścimy w elementach boxed_kolumn. Docelowo nasze okno dialogowe powinno wyglądać następująco:

0x01 graphic

Rys. 1. Okno dialogowe programu lisp_3.lsp

Aby osiągnąć ten efekt, w pliku dcl umieszczamy pozostałe elementy zgodnie ze schematem:

0x01 graphic

Po dodaniu do pliku lisp_3.dcl pola tekstowego i dwóch przycisków nasz plik dcl powinien przybrać postać:

dialog3 : dialog {

label = " Helion";

: row {

: boxed_column {

: text {

key = "txt_1";

width = 24;

}

}

: boxed_column {

: button {

label = "Jest napis";

key = "b_1";

mnemonic = "J";

}

: button {

label = "Nie ma napisu";

key = "b_2";

mnemonic = "N";

}

}

}

ok_only;

}

W pliku lisp_3.lsp umieszczamy z kolei:

(defun c:lisp_3 () ;[1]

(setq dcl_id (load_dialog "lisp_3")) ;[2]

(if(not(new_dialog "dialog3" dcl_id))(exit)) ;[3]

  1. W pierwszej linii, za pomocą funkcji defun, umieszczamy wywołanie programu. Wywołanie jest to ciąg znaków, po wpisaniu których dany program zostanie uruchomiony.

  2. W linii (setq dcl_id (load_dialog "lisp_3")) przypisujemy zmiennej dcl_id wartość (load_dialog "lisp_3") czyli "podpowiadamy", że definicja okna dialogowego znajduje się w pliku lisp_3.dcl.

  3. Użycie linii (if(not(new_dialog "dialog3" dcl_id))(exit)) powoduje, że AutoCAD przegląda plik lisp_3.dcl w poszukiwaniu identyfikatora okna dialogowego dialog3(funkcja new_dialog inicjuje i wyświetla okno dialogowe).

(action_tile "txt_1" "(setq napis $value") ;[4]

(action_tile "b_1" "(jest)") ;[5]

(action_tile "b_2" "(nie_ma)") ;[6]

  1. Przypisanie akcji do pola typu tekst -- przypisanie zmiennej napis wartości, jaką w danej chwili posiada element tekst.

  2. Przypisanie akcji do pola typu przycisk -- po wciśnięciu przycisku o parametrze "b_1" -- zostanie uruchomiona funkcja (jest).

  3. Przypisanie akcji do pola typu przycisk -- po wciśnięciu przycisku o parametrze "b_2" -- zostanie uruchomiona funkcja (nie_ma).

Omówienie funkcji wykorzystywanych do sterowania napisem w polu tekstowym.

(defun jest () ;[7]

(setq napis "Wydawnictwo Helion") ;[8]

(set_tile "txt_1" napis) ;[9]

);defun ;[10]

(defun nie_ma () ;[11]

(setq napis " ") ;[12]

(set_tile "txt_1" napis) ;[13]

);defun ;[14]

  1. Umieszczenie za pomocą funkcji defun wywołania progamu jest.

  2. Przypisanie zmiennej napis wartości "Wydawnictwo Helion".

  3. Ustawienie w elemencie okna dialogowego typu text o kluczu key=txt_1 wartości zmiennej napis.

  4. Koniec wywołania (jest).

  5. Umieszczenie za pomocą funkcji defun wywołania progamu nie_ma.

  6. Przypisanie zmiennej napis wartości " " (pusta spacja).

  7. Ustawienie w elemencie okna dialogowego typu text o kluczu key=txt_1 wartości zmiennej napis.

  8. Koniec wywołania (nie_ma).

(start_dialog) ;[15]

(unload_dialog dcl_id) ;[16]

(princ) ;[17]

);defun ;[18]

  1. start_dialog rozpoczyna pobieranie informacji od użytkownika z okna dialogowego zainicjowanego przez wywołanie funkcji new_dialog.

  2. unload_dialog dcl_id usuwa z pamięci wskazany plik DCL.

  3. czyszczenie lini poleceń za pomocą funkcji princ.

  4. nawias zamykający wywołanie funkcji lisp_3.

W linii następującej po linii (defun c:lisp_3 () wstawiamy linię (setq napis " "), która zmiennej napis przypisuje wartość " " (pusta spacja), co powoduje, że podczas pierwszego uruchomienia programu w polu tekstowym nie zobaczymy wartości, ponieważ pusta spacja nie będzie widoczna.

Plik lisp_3.lsp powinien ostatecznie wyglądać następująco:

(defun c:lisp_3 ()

(setq napis " ")

(setq dcl_id (load_dialog "lisp_3"))

(if(not(new_dialog "dialog3" dcl_id))(exit))

(action_tile "txt_1" "(setq napis ")

(action_tile "b_1" "(jest)")

(action_tile "b_2" "(nie_ma)")

(defun jest ()

(setq napis "Wydawnictwo Helion")

(set_tile "txt_1" napis)

);defun

(defun nie_ma ()

(setq napis " ")

(set_tile "txt_1" napis)

);defun

(start_dialog)

(unload_dialog dcl_id)

(princ)

);defun

Po zapisaniu obu tych plików i wpisaniu z klawiatury (load "lisp_3") oraz naciśnięciu klawisza Enter nasz program został wczytany do AutoCAD-a. Uruchamiamy go, wpisując: w linii poleceń: lisp_1 i zatwierdzając Enterem. Efekt powinien być taki, jak na rysunku poniżej.

0x01 graphic

Rys. 2. Okno dialogowe z "niewidoczną" spacją w polu tekstowym

Kliknięcie przycisku Jest napis spowoduje wyświetlenie napisu w polu tekstowym. Użycie przycisku umieszczonego poniżej spowoduje usunięcie napisu z pola tekstowego.

Lekcja 4 -- Wyświetlanie napisu w polu tekstowym cz.2

0x01 graphic

Tematem bieżącej lekcji jest stworzenie programu sterującego -- za pomocą jednego przycisku -- wyświetlaniem napisu w polu tekstowym.

Zakładamy, że po wciśnięciu przycisku Napis w polu tekstowym pojawią się słowa "Wydawnictwo Helion". Po ponownym wciśnięciu tego przycisku pole tekstowe zostanie wyczyszczone. Przy pisaniu tego programu wykorzystamy szablony plików lisp_1.lsp i lisp_1.dcl, zapisując je odpowiednio:

lisp_4.dcl:

Dialog4 : dialog {

label = "Lisp_4";

}

ok_cancel;

}

lisp_4.lsp:

(defun c:lisp_4 ()

(setq dcl_id (load_dialog "lisp_4"))

(if(not(new_dialog "dialog1" dcl_id))(exit))

(start_dialog)

(unload_dialog dcl_id)

);defun c:lisp_4

Wczytujemy program lisp_4.lsp, wpisując w linii komend AutoCAD-a (load "lisp_4") i naciskając klawisz Enter, a następnie uruchamiamy go z klawiatury, wpisując wywołanie lisp_4 oraz potwierdzając klawiszem Enter.

0x01 graphic

Rys. 1. Szablon okna dialogowego z widocznymi jedynie przyciskami Ok. i Anuluj

Zakładamy, że okno dialogowe będzie podzielone na dwie pionowe części. Po lewej stronie umieścimy pole tekstowe. Po prawej stronie znajdzie się przycisk. Wszystkie elementy okna, dla lepszego efektu wizualnego, umieścimy w elementach boxed_kolumn. Docelowo nasze okno dialogowe powinno wyglądać następująco:

0x01 graphic

Rys. 2. Rysunek okna dialogowego programu do sterowania napisem w polu tekstowym

Uzupełniamy definicję okna tak, jak zostało to pokazane na schemacie poniżej.

0x01 graphic

Dodajemy do definicji okna elementy pole tekstowe oraz przycisk (oba dla lepszego efektu umieszczone wewnątrz obiektów typu boxed_column). Całość umieszczamy wewnątrz elementu row dzięki czemu pole tekstowe i przycisk są umieszczone obok siebie w wierszu.

: row {

: boxed_column {

: text {

key = "txt_1";

width = 20;

}

}

: boxed_column {

: button {

label = "Napis";

key = "b_1";

mnemonic = "N";

}

}

}

Po dodaniu nowych elementów do definicji okna dialogowego plik lisp_4.dcl powinien wyglądać następująco:

dialog4 : dialog {

label = " Lisp 4";

: row {

: boxed_column {

: text {

key = "txt_1";

width = 20;

}

}

: boxed_column {

: button {

label = "Napis";

key = "b_1";

mnemonic = "N";

}

}

}

ok_cancel;

}

Przystępujemy do "oprogramowania" elementów okna dialogowego poprzez dodanie w pliku lisp_4.lsp lini kodu do obsługi poszczególnych elementów okna dialogowego.

W pliku lisp_4.lsp umieszczamy z kolei:

(defun c:lisp_4 () ;[1]

(setq dcl_id (load_dialog "lisp_4")) ;[2]

(if(not(new_dialog "dialog4" dcl_id))(exit)) ;[3]

  1. W pierwszej linii za pomocą funkcji defun umieszczamy wywołanie programu. Wywołanie jest to ciąg znaków, po wpisaniu których dany program zostanie uruchomiony.

  2. W linii (setq dcl_id (load_dialog "lisp_4")) przypisujemy zmiennej dcl_id wartość (load_dialog "lisp_4") czyli "podpowiadamy", że definicja okna dialogowego znajduje się w pliku lisp_4.dcl.

  3. Wpisanie linii (if(not(new_dialog "dialog4" dcl_id))(exit)) sprawia, że AutoCAD przeszukuje plik lisp_4.dcl w poszukiwaniu identyfikatora okna dialogowego dialog1 (funkcja new_dialog inicjuje i wyświetla okno dialogowe).

(action_tile "txt_1" "(setq napis $value") ;[4]

(action_tile "b_1" "(jest_i_nie_ma)") ;[5]

  1. Przypisanie akcji do pola typu tekst -- przypisanie zmiennej napis wartości, jaką w danej chwili posiada element tekst.

  2. Przypisanie akcji do pola typu przycisk -- po wciśnięciu przycisku o parametrze "b_1" zostanie uruchomiona funkcja (jest_i_nie_ma).

Analogicznie do przykładu z lekcji trzeciej do sterowania napisami w polu tekstowym posłużymy się przyciskiem (button), ale w odróżnieniu od sytuacji z wcześniejszego przykładu jeden przycisk posłuży nam do wyświetlania i do usuwania tekstu z pola tekstowego.

Bezpośrednio za linią (defun c:lisp_4 () umieszczamy linię (setq napis " ") -- sprawia ona nadanie zmiennej napis wartości " " (pojedyncza spacja). Funkcja zdefiniowana porzez wywołanie jest_i_nie_ma do przechowywania tekstu korzysta z tej zmiennej. Aby za pomocą jednego przycisku kontrolować pojawianie się tekstu lub jego usunięcie z pola tekstowego, wykorzystamy do tego celu mechanizm instrukcji warunkowej If:

  • (defun jest_i_nie_ma () -- zdefiniowanie wywołania funkcji.

  • (if (= napis " ") -- funkcja if sprawdza, czy prawdziwy jest warunek, że zmienna napis = " "

  • (setq napis "Wydawnictwo Helion") -- jeżeli Prawda, to zmiennej napis przypisana zostaje wartość w postaci łańcucha tekstowego "Wydawnictwo Helion".

  • (setq napis " ") -- jeżeli Fałsz, to zmiennej napis przypisana zostaje wartość w postaci łańcucha tekstowego " "

  • );if

  • (set_tile "txt_1" napis) -- ustawienie w elemencie okna dialogowego typu text o kluczu key=txt_1 wartości zmiennej napis

  • );defun -- koniec funkcji

(start_dialog) rozpoczyna pobieranie informacji od użytkownika z okna dialogowego zainicjowanego przez wywołanie funkcji (new_dialog); (unload_dialog dcl_id) usuwa z pamięci wskazany plik DCL. Czyszczenie linii poleceń następuje za pomocą funkcji (princ) a zakończenie kodu programu lisp_4 nawiasem zamykającym.

Listing programu lisp_4.lsp:

(defun c:lisp_4 ()

(setq napis " ")

(setq dcl_id (load_dialog "lisp_4"))

(if(not(new_dialog "dialog4" dcl_id))(exit))

(action_tile "txt_1" "(setq napis $value")

(action_tile "b_1" "(jest_i_nie_ma)")

(defun jest_i_nie_ma ()

(if (= napis " ")

(setq napis "Wydawnictwo Helion")

(setq napis " ")

);if

(set_tile "txt_1" napis)

);defun

(start_dialog)

(unload_dialog dcl_id)

(princ)

);defun

Listing programu lisp_4.dcl:

dialog4 : dialog {

label = " Lisp 4";

: row {

: boxed_column {

: text {

key = "txt_1";

width = 20;

}

}

: boxed_column {

: button {

label = "Napis";

key = "b_1";

mnemonic = "N";

}

}

}

ok_cancel;

}

Lekcja 5 -- Okna kartotekowe dla zaawansowanych cz.1

0x01 graphic

Tematem lekcji piątej będzie współpraca elementów: przycisk (button) i lista rozwijalna (list_box) w programie do zarządzania listami elementów. Zagadnienia, które będą poruszane w bieżącej lekcji:

  1. Zagadnienie tworzenia list w AutoLisp-ie.

  2. Zagadnienia tworzenia list wyświetlanych w oknach kartotekach i kartotekach rozwijanych.

Zakładamy sobie, że mamy dwie kilkunastoelementowe listy kształtowników stalowych i chcemy napisać program, w którym powiążemy ze sobą elementy: przycisk i lista. Po wciśnięciu przycisku Ceowniki normalne w polu listy w oknie dialogowym zostanie umieszczona lista ceowników normalnych.

0x01 graphic

Rys. 1. Okno dialogowe z listą ceowników normalnych

Po wciśnięciu przycisku Ceowniki ekonomiczne w polu listy zostanie umieszczona odpowiadająca lista elementów.

0x01 graphic

Rys. 2. Okno dialogowe z listą ceowników ekonomicznych

Przy pisaniu tego programu wykorzystamy szablony plików lisp_1.lsp i lisp_1.dcl, zapisując je pod nazwami odpowiednio:

lisp_5.dcl :

Dialog5 : dialog {

label = "Lisp_5";

}

ok_cancel;

}

lisp_5.lsp:

(defun c:lisp_5 () [1]

(setq dcl_id (load_dialog "lisp_5")) [2]

(if(not(new_dialog "dialog1" dcl_id))(exit)) [3]

(start_dialog) [4]

(unload_dialog dcl_id) [5]

);defun c:lisp_5 [6]

  1. W pierwszej linii za pomocą funkcji defun umieszczamy wywołanie programu lisp_5. Wywołanie jest to ciąg znaków, po wpisaniu których dany program zostanie uruchomiony.

  2. W linii (setq dcl_id (load_dialog "lisp_5")) przypisujemy zmiennej dcl_id wartość (load_dialog "lisp_5") czyli "podpowiadamy", że definicja okna dialogowego znajduje się w pliku lisp_5.dcl.

  3. Linia (if(not(new_dialog "dialog5" dcl_id))(exit)) powoduje, że AutoCAD przeszukuje plik lisp_5.dcl w poszukiwaniu identyfikatora okna dialogowego dialog1 (funkcja (new_dialog) inicjuje i wyświetla okno dialogowe).
    W jednym pliku dcl może znajdować się wiele definicji okien dialogowych np.
    dialog1, dialog2, itd. Dlatego potrzebny jest identyfikator, jednoznacznie łączący plik AutoLispu z definicją okna dialogowego.

  4. start_dialog<.TT> rozpoczyna pobieranie informacji od użytkownika z okna dialogowego zainicjowanego przez wywołanie funkcji new_dialog.

  5. unload_dialog dcl_id usuwa z pamięci wskazany plik DCL.

  6. nawias zamykający wywołanie funkcji lisp_5

Po zapisaniu zmian dokonanych przez nas w obu plikach przystępujemy do sprawdzenia działania programu lisp_5).

Wczytujemy program lisp_5.lsp wpisując w linii poleceń AutoCAD-a (load "lisp_5") i Enter, a następnie uruchamiamy go z klawiatury, wpisując wywołanie lisp_5 oraz Enter.

Na ekranie powinno się pojawić okno, widoczne na rysunku poniżej.

0x01 graphic

Rys. 3. Widok szablonu okna dialogowego z widocznymi jedynie przyciskami OK i Anuluj

Jeżeli powyższy szablon wyświetlił się poprawnie, następnym krokiem jest dodanie do naszego okna dialogowego trzech nowych elementów, umieszczonych dla lepszego efektu wizualnego wewnątrz elementów (boxed_row). Dodawane przez nas elementy to:

  • Okno listy (list_box), w którym będziemy umieszczać listę elementów

  • Przycisk (button) o etykiecie "Ceowniki ekonomiczne"

  • Przycisk (button) o etykiecie "Ceowniki normalne"

Definicję tych elementów umieszczamy pomiędzy liniami label = " Lisp_5"; oraz ok_cancel;

0x01 graphic

Rys. 4. Schemat struktury pliku dcl

Listing uzupełnionego pliku lisp_5.dcl:

dialog5 : dialog {

label = " Lisp 5";

: boxed_column {

: list_box {

label = "Lista Ceowników";

key = "list_elem";

mnemonic = "L";

}

}

: boxed_column {

: button {

label = "Ceowniki ekonomiczne";

key = "c_e";

mnemonic = "C";

alignment = centered;

}

: button {

label = "Kątowniki normalne";

key = "c_n";

mnemonic = "K";

alignment = centered;

}

}

Przystępujemy do dodania do pliku lisp_5.lsp funkcji obsługi listy i przycisków okna dialogowego.

lisp_5.lsp:

(defun c:lisp_5 ()

; na początku pliku umieszczamy dwie listy z nazwami elementów, które będą

; wyświetlane w oknie listy i przypisujemy ich wartości do zmiennych listc

; i liste

(setq listc (list " 35 C" " 40 C" " 45 C" " 50 C" " 65 C" " 80 C"

" 100 C" " 120 C" " 140 C" " 160 C" " 180 C" " 200 C" ))

(setq liste (list " 30 E" " 40 E" " 50 E" " 60 E" " 70 E" " 80 E"

" 100 E" " 120 E" " 140 E" " 160 E" " 180 E" " 200 E" ))

(setq dcl_id (load_dialog "lisp_5"))

(if(not(new_dialog "dialog1" dcl_id))(exit))

(action_tile "c_n" "(list_c)") ;definiujemy reakcję jaka nastąpi po

;wybraniu przez użytkownika przycisku który posiada

;zdefiniowany w pliku dclatrtrybut "c_n"

; - zostanie uruchomiona funkcja (list_c) .

(action_tile "c_e" "(list_e)") ; ;definiujemy reakcję jaka nastąpi po

;wybraniu przez użytkownika przycisku który posiada

;zdefiniowany w pliku dclatrtrybut "c_e"

; - zostanie uruchomiona funkcja (list_e) .

(action_tile "list_elem" "(setq symbol )");zdefiniowanie akcji

; przypisanej do zdażenia wybrania dowolnego elementu z listy w oknie

; dialogowym -- tutaj jest to przypisanie wartości zmiennej symbol

; wartości elementu wskazanego na liście.

(defun list_c () ; definiujemy wywołanie funkcji lict_c

(start_list "list_elem") ; określenie nazwy elementu okna kartotekowego

(mapcar 'add_list listc) ; określenie listy AutoLispu -- lista listc

(end_list) ; zamknięcie uzupełnianej listy

)

(defun list_e (); definiujemy wywołanie funkcji lict_c

(start_list "list_elem")"); określenie nazwy elementu okna kartotekowego

(mapcar 'add_list liste) ; określenie listy AutoLispu -- lista liste

(end_list) ; zamknięcie uzupełnianej listy

)

(start_dialog)

(unload_dialog dcl_id

);defun c:lisp_5

Po zapisaniu zmian dokonanych przez nas w obu plikach przystępujemy do sprawdzenia działania programu lisp_5. W tym celu w linii poleceń AutoCAD-a wpisujemy: (load "lisp_5") i zatwierdzamy przyciskiem Enter.

Wyświetlone zostaje nasze okno dialogowe, które powinno wyglądać identycznie, jak to widoczne na rysunku poniżej.

0x01 graphic

Rys. 5. Okno dialogowe programu lisp_5.lsp

dcl_settings : default_dcl_settings { audit_level = 3; }

dialog5 : dialog {

label = " Lisp 5";

: boxed_column {

: list_box {

label = "Lista Ceowników";

key = "list_elem";

mnemonic = "L";

}

}

: boxed_column {

: button {

label = "Ceowniki ekonomiczne";

key = "c_e";

mnemonic = "C";

alignment = centered;

}

: button {

label = "Kątowniki normalne";

key = "c_n";

mnemonic = "K";

alignment = centered;

}

}

spacer_1;

ok_cancel;

}

(defun c:lisp_5 ()

(setq listc (list " 35 C" " 40 C" " 45 C" " 50 C" " 65 C" " 80 C"

" 100 C" " 120 C" " 140 C" " 160 C" " 180 C" " 200 C" ))

(setq liste (list " 30 E" " 40 E" " 50 E" " 60 E" " 70 E" " 80 E"

" 100 E" " 120 E" " 140 E" " 160 E" " 180 E" " 200 E" ))

(setq dcl_id (load_dialog "lisp_5"))

(if(not(new_dialog "dialog5" dcl_id))(exit))

(action_tile "c_n" "(list_c)")

(action_tile "c_e" "(list_e)")

(action_tile "list_elem" "(setq symbol )")

(defun list_c ()

(start_list "list_elem")

(mapcar 'add_list listc)

(end_list)

)

(defun list_e ()

(start_list "list_elem")

(mapcar 'add_list liste)

(end_list)

)

(start_dialog)

(unload_dialog dcl_id)

(princ)

);defun

Lekcja 6 -- Wzajemne powiązanie między sobą wycinków okna edycyjnego (edit_box), pola tekstowego (text) i suwaka (slider)

0x01 graphic

W dzisiejszej lekcji zostanie omówione zagadnienie wzajemnego przekazywania sobie wartości przez różne elementy okna dialogowego na przykładzie okna do pobierania od użytkownika wartości temperatury. Będzie się ono składało z trzech elementów: okna edycyjnego, pola tekstowego i suwaka.

Założenia: użytkownik może podać wartość temperatury poprzez wpisanie jej w okienku edycyjnym lub za pomocą suwaka. Każda zmiana wartości w którymkolwiek oknie zmienia wartość w pozostałym oknie i wyświetla na bieżąco sformatowaną wartość w polu tekstowym.

W przykładzie tym zetkniemy się z:

  • Zagadnieniem wzajemnego powiązania ze sobą dwóch elementów okna w taki sposób, że przekazują sobie nawzajem swoje wartości. Innym słowem "akcja" w jednym z okien wywołuje natychmiastową "reakcję" w drugim oknie.

  • Nowym elementem okien dialogowych – suwakiem.

Pisanie programu zwyczajowo rozpoczynamy od wykorzystania szablonów plików lisp_1.lsp i lisp_1.dcl, zapisując je pod nazwami odpowiednio:

lisp_6.dcl:

Dialog6 : dialog {

label = "Program Lisp_6";

}

ok_cancel;

}

lisp_6.lsp:

(defun c:lisp_6 ()

(setq dcl_id (load_dialog "lisp_6"))

(if(not(new_dialog "dialog1" dcl_id))(exit))

(start_dialog)

(unload_dialog dcl_id)

);defun c:lisp_6

Wczytujemy program lisp_6.lsp wpisując w linii komend AutoCAD-a (load "lisp_6") i wciskając Enter, a następnie uruchamiamy go z klawiatury, wpisując wywołanie lisp_6 oraz Enter. Zakładamy, że okno dialogowe podzielone będzie na dwie poziome części. W górnej części po lewej stronie umieścimy okno edycyjne, po prawej suwak, a w dolnej części pole tekstowe. Efekt "rozgraniczenia" obszarów uzyskamy umieszczając okno edycyjne i suwak w środku elementu (boxed_row), a pole tekstowe (text) w środku elementu (boxed_column).

Docelowo nasze okno dialogowe powinno wyglądać następująco:

0x01 graphic

Rys. 1. Okno dialogowe programu lisp_6.lsp

Aby osiągnąć ten efekt w pliku dcl umieszczamy pozostałe elementy zgodnie ze schematem:

0x01 graphic

Rys. 2.

Po dodaniu do pliku lisp_6.dcl pola tekstowego i dwóch przycisków nasz plik dcl powinien mieć postać:

dialog6 : dialog {

label = " Temperatura";

: boxed_row {

: edit_box {

label = "(0 - 100)";

key = "temp";

mnemonic = "(";

}

: slider {

key = "suwak";

min_value = 0;

max_value = 100;

small_increment = "1";

big_increment = "5";

width = 20;

}

}

: spacer {

}

: boxed_column {

: text {

key = "txt_3";

width = 20;

}

}

ok_cancel;

}

W pliku lisp_3.lsp umieszczamy z kolei:

(defun c:lisp_6 () ;[1]

(setq dcl_id (load_dialog "lisp_6")) ;[2]

(if(not(new_dialog "dialog6" dcl_id))(exit)) ;[3]

W pierwszej linii za pomocą funkcji defun umieszczamy wywołanie programu. Wywołanie jest to ciąg znaków, po wpisaniu których dany program zostanie uruchomiony.

W linii (setq dcl_id (load_dialog "lisp_6")) przypisujemy zmiennej dcl_id wartość (load_dialog "lisp_6") czyli "podpowiadamy", że definicja okna dialogowego znajduje się w pliku lisp_6.dcl.

Linia (if(not(new_dialog "dialog6" dcl_id))(exit)) powoduje, że AutoCAD przeszukuje plik lisp_6.dcl w poszukiwaniu identyfikatora okna dialogowego dialog6 (funkcja (new_dialog) inicjuje i wyświetla okno dialogowe).

(set_tile "temp" ")

Ustawienie w elemencie okna dialogowego typu edit_box o kluczu key= temp wartości 0.

0x01 graphic

Rys. 3.

(action_tile "suwak" "(setq temp )(do_temp)")

Przypisanie akcji do pola typu suwak -- po zmianie pozycji suwaka następuje przypisanie zmiennej temp wartości, jaką ma w danej chwili element suwak (pozycja, w jakiej go zostawiliśmy, np. 46, jak na rysunku powyżej). W dalszej kolejności następuje wywołanie funkcji (do_temp)

(defun do_temp ()

Zmiennej temp1 przypisujemy "wartość" suwaka odczytaną za pomocą funkcji Get_tile.

(setq temp1 (get_tile "suwak"))

(set_tile "temp" temp1)

i "wysyłamy" tę wartość do edit_box za pomocą funkcji set.

Reszta funkcji do_temp tworzy ładny "komunikat pogodowy":

(setq a "Temperatura = ")

(setq temp (get_tile "temp"))

(setq b " stopni Celsjusza")

(setq c (strcat a temp b) )

po czym tak sformatowany tekst "wysyła" do pola tekstowego:

(set_tile "txt_3" c) [10] );defun

Do zdarzenia wciśnięcia przycisków OK i Anuluj zostaje przypisana akcja wyjścia z okna dialogowego.

(action_tile "accept" "(done_dialog 1)")

(action_tile "cancel" "(done_dialog 0)")

Jeżeli cokolwiek zostanie wpisane w oknie edycyjnym, to reakcją na to zdarzenie jest wywołanie funkcji get_temp

(action_tile "temp" "(get_temp)")

Definiujemy nazwę nowej funkcji.

(defun do_temp ()

Zmiennej temp1 przypisujemy wartość pobraną z suwaka.

(setq temp1 (get_tile "suwak"))

i wysyłamy tę wartość do okienka edycyjnego.

(set_tile "temp" temp1)

Zmiennej a przypisujemy łańcuch "Temperatura = ".

(setq a "Temperatura = ")

Zmiennej temp przypisujemy wartość pobraną z edit_box.

(setq temp (get_tile "temp"))

Formatujemy napis potrzebny do wyświetlenia w polu tekstowym wartości temperatury.

(setq c " stopni Celsjusza")

(setq a (strcat a temp c) )

Wyświetlamy nasz napis:

(set_tile "txt_3" a)

);defun

(defun get_temp ()

(setq a "Temperatura = ")

(setq temp (get_tile "temp"))

(setq c " stopni Celsjusza")

(setq a (strcat a temp c) )

(set_tile "txt_3" a)

(set_tile "suwak" temp)

);defun

(start_dialog)

(unload_dialog dcl_id)

);defun

Lekcja 7 -- Przygotowanie listy elementów poprzez wybranie i dodanie ich do listy wynikowej na podstawie obranego przez nas kryterium

0x01 graphic

Tematem bieżącej lekcji jest stworzenie programu do przygotowania listy elementów poprzez wybranie i dodanie ich przez nas do listy wynikowej na podstawie obranego przez nas kryterium.

Założenia: zakładamy, że po kliknięciu elementu pierwszej listy nazwa tego elementu powinna się pojawić w okienku edycyjnym nad przyciskiem. Jeśli wciśniemy przycisk, gdy w okienku edycyjnym będzie widoczna nazwa elementu, to zostanie on dodany do listy wynikowej.

Zakładamy, że podzielimy nasze okno dialogowe na trzy równe pionowe części.

W przykładzie tym:

  1. Zetkniemy się z zagadnieniami umieszczania i zarządzania listami w oknach dialogowych.

  2. Poznamy funkcję, dzięki której będziemy w stanie odczytywać z listy nazwę elementu, który się na tej warstwie znajduje.

Pisanie programu zwyczajowo rozpoczynamy od wykorzystania szablonów plików lisp_1.lsp i lisp_1.dcl, zapisując je pod nazwami odpowiednio:

lisp_7.dcl:

Dialog7 : dialog {

label = "Program Lisp_7";

}

ok_cancel;

}

lisp_7.lsp:

(defun c:lisp_7 ()

(setq dcl_id (load_dialog "lisp_7"))

(if(not(new_dialog "dialog1" dcl_id))(exit))

(start_dialog)

(unload_dialog dcl_id)

);defun c:lisp_7

Wczytujemy program lisp_7.lsp wpisując w linii komend AutoCAD-a (load "lisp_7") i wciskając Enter, a następnie uruchamiamy go z klawiatury, wpisując wywołanie lisp_7 oraz wciskając Enter.

0x01 graphic

Rys. 1. Szablon okna dialogowego z widocznymi jedynie przyciskami OK i Anuluj

Dodajemy do naszego szablonu okna potrzebne elementy według schematu widocznego na rysunku poniżej.

0x01 graphic

Rys. 2. Struktura okna dialogowego

Po ich dodaniu nasze okno powinno wyglądać w sposób następujący:

0x01 graphic

Rys. 3. Wygląd okna dialogowego

Widok pliku lisp_7.dcl po umieszczeniu w nim wszystkich wycinków:

dialog7 : dialog {

label = " Operacje na listach";

: row {

: boxed_column {

label = "Lista 1";

mnemonic = "L";

: list_box {

key = "lista_1";

}

}

: boxed_column {

: edit_box {

key = "txt_1";

}

: button {

label = "Dodaj";

key = "add";

mnemonic = "D";

}

spacer_1;

spacer_1;

spacer_1;

}

: boxed_column {

label = "Lista 2";

mnemonic = "L";

: list_box {

key = "lista_2";

}

}

}

ok_cancel;

}

Przystępujemy do "oprogramowania" elementów okna dialogowego poprzez dodanie w pliku lisp_7.lsp linii kodu do obsługi poszczególnych elementów okna dialogowego.

W pliku lisp_7.lsp umieszczamy z kolei:

(defun c:lisp_7 ()

(setq licznik 1)

(setq dcl_id (load_dialog "lisp_7"))

(if(not(new_dialog "dialog7" dcl_id))(exit))

W pierwszej linii za pomocą funkcji defun umieszczamy wywołanie programu. Wywołanie jest to ciąg znaków, po wpisaniu których dany program zostanie uruchomiony.

Następnie przypisujemy zmiennej licznik wartość 1 -- mówiąc potocznie "ustawiamy licznik".

W linii (setq dcl_id (load_dialog "lisp_7")) przypisujemy zmiennej dcl_id wartość (load_dialog "lisp_7") , czyli "podpowiadamy", że definicja okna dialogowego znajduje się w pliku lisp_7.dcl.

Linia (if(not(new_dialog "dialog7" dcl_id))(exit)) powoduje, że AutoCAD przeszukuje plik lisp_7.dcl w poszukiwaniu identyfikatora okna dialogowego dialog7 (funkcja (new_dialog) inicjuje i wyświetla okno dialogowe).

tworzymy nową listę i przypisujemy jej wartość zmiennej listc.

(setq listc (list " 35 C" " 40 C" " 45 C" " 50 C"

" 65 C" " 80 C" " 100 C" " 120 C"

" 140 C" " 160 C" " 180 C" " 200 C" ))

(start_list "lista_1")

(mapcar 'add_list listc)

(end_list)

Przypisanie akcji do zdarzenia związanego z wybraniem jakiegokolwiek elementu z listy lista_1: (action_tile "lista_1" "(get_name )") , czyli wskazanie elementu na liście powoduje wywołanie funkcji get_name (item) . Funkcja ta wywołana z argumentem item zwraca nazwę elementu który został wskazany na tej liście. Np. konstrukcja (action_tile "lista_1" "(setq lname )") zwraca tylko pozycję, jaką na liście ma dany obiekt, licząc od indeksu zerowego.

Przykład:

Mamy listę 7 elementów:

Numeracja

1

2

3

4

5

6

7

Element  listy

" 35 C"

" 40 C"

" 45 C"

" 50 C"

" 65 C"

" 80 C"

" 100 C"

I tak, jeśli wybraliśmy czwarty element listy, to:

  • (action_tile "lista_1" "(setq lname )") zwróci nam lname = "3"

  • (action_tile "lista_1" "(get_name )") zwróci nam "50 C"

Funkcja, której przykładowe wywołanie z listą elementów objaśniałem powyżej, kolosalnie skraca czas i wielkość kodu w porównaniu do standardowego sposobu, który zamiast nazwy elementu zwraca nam jego pozycję na tej liście w indeksach liczonych od 0.

;Funkcja get_name (item)

(defun get_name (item)

; definicja wywołania funkcji z argumenten item

(setq lnom (nth (atoi item)listc))

; przypisanie zmiennej lnom n-tego elementu

);defun ; listy, item jako argument funkcji musi być

;przekonwertowny z łańcucha na liczbę całkowitą.

Przypisanie akcji do zdarzenia związanego z wciśnięciem przycisku dodaj. (action_tile "add" "(do_list)") – następuje uruchomienie funkcji do_list

;Funkcja get_name (item)

(defun do_list () ; definicja wywołania funkcji

(if (= licznik 1) (setq ln lnom)(setq ln (append ln lnom)))

; jeżeli licznik jest równy 1, to znaczy,

; że funkcja do_list jest uruchomiona po raz

; pierwszy, więc przypisuje zmiennej ln wartość

; lnom, a następnie przetwarzana jest lista_2.

; Jeżeli licznik jest "większy" od 1, to znaczy,

; że funkcja była już uruchomiona co najmniej

; raz, dlatego nie tworzymy nowej listy, ale

; dodajemy nowy element do istniejącej listy.

; Następnie lista_2 jest przetwarzana.

(start_list "lista_2") ; przetwarzanie nowej listy AutoLisp-u

; w polu listy DCL

(mapcar 'add_list ln) ; określenie listy AutoLisp-u

(end_list) ; kończymy przetwarzanie listy

(setq licznik (+ 1 licznik)) ; powiększamy licznik o 1

);defun

Przypisanie akcji do zdarzenia związanego z wciśnięciem przycisku OK.. Ukrycie okna dialogowego.

(action_tile "accept" "(done_dialog 1)")

Przypisanie akcji do zdarzenia związanego z wciśnięciem przycisku Anuluj. Ukrycie okna dialogowego.

(action_tile "cancel" "(done_dialog 0)")

Przypisanie zmiennej listc wartości listy

(start_dialog) ; rozpoczyna pobieranie informacji od użytkownika

; z okna dialogowego zainicjowanego przez

; wywołanie funkcji new_dialog.

(unload_dialog dcl_id) ;usuwa z pamięci wskazany plik DCL.

);defun kończy wywołanie funkcji

Lekcja 8 -- Przygotowanie listy elementów poprzez wybranie i dodanie ich do listy wynikowej poprzez kliknięcie na liście

0x01 graphic

To już ósma lekcja zawierająca przykład ilustrujący zaawansowane techniki... (Pan z końca sali mówi, że to raczej tricki. No cóż, nie będę się z Państwem spierał, w końcu zawsze końcowy użytkownik pokaże, kto miał rację!) Programowanie AutoCAD-a i to niekoniecznie za pomocą AutoLispa niesie ze sobą pewne niebezpieczeństwo. Otóż pojawia się wiele programów spełniających te same zadania projektowe, ale jeden z nich szybko osiąga popularność, a drugi równie szybko "ginie w mroku dziejów". Często trudno jest znaleźć powód tego faktu. Musimy sobie uświadomić, że powodem może być np. to, że w jednej z tych aplikacji, aby osiągnąć ten sam efekt, trzeba w tym celu o jeden raz więcej kliknąć myszą. Niech mi Państwo wierzą, często to właśnie stanowi o sukcesie lub porażce rynkowej naszej aplikacji. Dlatego warto czasem dobrze przemyśleć sposób podejścia do projektowania, lub przeprowadzić dobrze znany wszystkim CAD-owcom tzw. test na "Ciocię i kota". Zasada testu jest bardzo prosta. Trzeba po prostu podnieść głowę znad komputera i powiedzieć: "Kochana Ciociu, czy mogłabyś na chwilę położyć tego kota na podłodze i powiedzieć, które z tych okien dialogowych jest Twoim zdaniem lepsze?" Niech mi Państwo wierzą, ten test jest bardzo miarodajny...

OK, koniec z ciocią, a tak na poważnie, musimy zawsze starać się postawić na miejscu użytkownika końcowego i próbować przewidzieć jego wymagania, związane z działaniem naszej aplikacji. Dlatego na kolejną lekcję o programowalnych oknach dialogowych ponownie wybrałem przykład, dotyczący wzajemnego powiązania między sobą dwóch elementów typu okno kartotekowe. Zagadnienia wykorzystane w tym przykładzie mogą mieć np. zastosowanie przy wyborze z listy wszystkich widoków na rysunku listy widoków, które chcemy wydrukować.

Tematem bieżącej lekcji jest stworzenie programu do przygotowania listy elementów poprzez wybranie i dodanie ich przez nas do listy wynikowej poprzez kliknięcie na liście.

Zakładamy, że podzielimy nasze okno dialogowe na połowę w pionie. Schemat definicji okna dialogowego.

W przykładzie tym:

  1. Zetkniemy się z zagadnieniami umieszczania i zarządzania listami w oknach dialogowych.

  2. Poznamy funkcję, dzięki której będziemy w stanie odczytywać z listy nazwę elementu, który znajduje się na tej warstwie.

Pisanie programu zwyczajowo rozpoczynamy od wykorzystania szablonów plików lisp_1.lsp i lisp_1.dcl, zapisując je pod nazwami odpowiednio:

lisp_8.dcl:

Dialog8 : dialog {

label = "Program Lisp_8";

}

ok_cancel;

}

lisp_8.lsp:

(defun c:lisp_8 ()

(setq dcl_id (load_dialog "lisp_8"))

(if(not(new_dialog "dialog8" dcl_id))(exit))

(start_dialog)

(unload_dialog dcl_id)

);defun c:lisp_8

Wczytujemy program lisp_8.lsp wpisując w linii komend AutoCAD-a (load "lisp_8") i wciskając Enter, a następnie uruchamiamy go z klawiatury, wpisując wywołanie lisp_8 oraz wciskając Enter.

0x01 graphic

Rys. 1. Szablon okna dialogowego z widocznymi jedynie przyciskami OK i Anuluj

Dodajemy do naszego szablonu okna potrzebne elementy według schematu widocznego na rysunku poniżej.

0x01 graphic

Rys. 2. Struktura okna dialogowego

Po ich dodaniu nasze okno powinno wyglądać w sposób następujący:

0x01 graphic

Rys. 3. Wygląd okna dialogowego

Widok pliku lisp_8.dcl po umieszczeniu w nim wszystkich wycinków.

dialog8 : dialog {

label = " Lisp_8";

: row {

: boxed_column {

label = "Lista 1";

mnemonic = "L";

: list_box {

key = "lista_1";

}

}

: boxed_column {

label = "Lista 2";

mnemonic = "L";

: list_box {

key = "lista_2";

}

}

}

ok_cancel;

}

Przystępujemy do "oprogramowania" elementów okna dialogowego poprzez dodanie w pliku lisp_8.lsp linii kodu do obsługi poszczególnych elementów okna dialogowego.

W pliku lisp_8.lsp umieszczamy z kolei:

(defun c:lisp_8 ()

(setq licznik 1)

(setq dcl_id (load_dialog "lisp_8"))

(if(not(new_dialog "dialog8" dcl_id))(exit))

W pierwszej linii za pomocą funkcji defun umieszczamy wywołanie programu. Wywołanie jest to ciąg znaków, po wpisaniu których dany program zostanie uruchomiony.

Nastepnie przypisujemy zmiennej licznik wartość 1 - potocznie "ustawiamy licznik".

W linii (setq dcl_id (load_dialog "lisp_8")) przypisujemy zmiennej dcl_id wartość (load_dialog "lisp_8"), czyli "podpowiadamy", że definicja okna dialogowego znajduje się w pliku lisp_8.dcl.

Wiersz (if(not(new_dialog "dialog8" dcl_id))(exit)) powoduje, że AutoCAD przeszukuje plik lisp_8.dcl w poszukiwaniu identyfikatora okna dialogowego dialog8 (funkcja (new_dialog) inicjuje i wyświetla okno dialogowe).

(action_tile "lista_1" "(get_name )") Przypisanie akcji do zdarzenia związanego ze wskazaniem dowolnego elementu z listy lista_1, co spowoduje wywołanie funkcji get_name.

Przypisanie akcji do zdarzenia związanego z wciśnięciem przycisku OK. Ukrycie okna dialogowego.

(action_tile "accept" "(done_dialog 1)")

Przypisanie akcji do zdarzenia związanego z wciśnięciem przycisku Anuluj. Ukrycie okna dialogowego.

(action_tile "cancel" "(done_dialog 0)")

Tworzymy nową listę i przypisujemy jej wartość zmiennej listc.

(setq listc (list " 35 C" " 40 C" " 45 C" " 50 C"

" 65 C" " 80 C" " 100 C" " 120 C"

" 140 C" " 160 C" " 180 C" " 200 C" ))

(defun get_name (item) ; definicja wywołania funkcji z argumenten item

(setq lnom (nth (atoi item)listc)) ; przypisanie zmiennej lnom n-tego

; elementu listy, item jako argument funkcji musi być

; przekonwertowny z łańcucha na liczbę całkowitą.

(setq lnom (list lnom)) ; zamiana zmiennej lnom na listę jeżeli

; spełniony jest warunek licznik = 1, przypisz zmiennej

; ln wartość zmiennej ;lnom, jeżeli nie jest spełniony,

; przypisz zmiennej ln wartość listy ln ;powiększonej

; o zmiennę lnom. Chodzi o to, że gdy funkcja jest

; wywołana po raz;pierwszy, lista elementów składa się

; z tylko jednego elementu, natomiast gdy ;wywołana

; jest więcej razy, lista jest uzupełniana za pomocą

; funkcji append o kolejne elementy.

(if (= licznik 1) (setq ln lnom)(setq ln (append ln lnom)))

(start_list "lista_2")

; przetwarzanie nowej listy autolispu w polu listy DCL

(mapcar 'add_list ln) ; określenie listy AutoLisp-u

(end_list) ; kończymy przetwarzanie listy

(setq licznik (+ 1 licznik)) ; powiększamy licznik o 1

);defun ; kończy wywołanie funkcji get_name

(start_dialog) ; rozpoczyna pobieranie informacji od użytkownika

; z okna dialogowego zainicjowanego przez wywołanie

; funkcji new_dialog.

(unload_dialog dcl_id) ; usuwa z pamięci wskazany plik DCL.

);defun ; kończy wywołanie funkcji lisp_8

Lekcja 9 -- Program do wielowariantowego wyboru wartości kąta

0x01 graphic

Tematem bieżącej lekcji jest poznanie sposobu zmiany trybu pracy wycinka na podstawie programu do wielowariantowego wyboru wartości kąta.

Założenia: zakładamy, że podawanie wartości kąta może się odbywać na wiele sposobów. Dla wartości 0, 90, 180, 270 wykorzystamy przyciski opcji. Wskazana wartość kąta w przyciskach opcji automatycznie pojawi się w okienku edycyjnym (edit_box). Jeżeli chcemy podać inną wartość kąta, to po kliknięciu przycisku opcji inny, w okienku edycyjnym w sposób automatyczny zostaje ustawiony focus w oczekiwaniu na wprowadzenie w nim wartości kąta. Trzecią możliwością, jaką mamy, aby wskazać wartość kąta, jest wciśnięcie przycisku pick, co powoduje ukrycie bieżącego okna i wywołanie funkcji pomiaru kąta na podstawie punktów wskazanych na ekranie graficznym AutoCAD-a.

Zakładamy, że podzielimy nasze okno dialogowe na dwie równe poziome części. W górnej części znajduje się wiersz z przyciskami opcji, a w dolnej okienko edycyjne oraz przycisk.

W przykładzie tym zetkniemy się z funkcją AutoLisp mode_tile do ustawiania trybu pracy wycinka.

Tryb

Znaczenie

0

Odblokowanie wycinka

1

Odblokowanie wycinka

2

Ustawienie focus dla wycinka

3

Wybranie zawartości okienka edycyjnego

4

Zmiana podświetlania obrazu (image) z tak na nie

Pisanie programu zwyczajowo rozpoczynamy od wykorzystania szablonów plików lisp_1.lsp i lisp_1.dcl, zapisując je pod nazwami odpowiednio:

lisp_9.dcl:

Dialog9 : dialog {

label = "Program Lisp_9";

}

ok_cancel;

}

lisp_9.lsp:

(defun c:lisp_9 ()

(setq dcl_id (load_dialog "lisp_9"))

(if(not(new_dialog "dialog1" dcl_id))(exit))

(start_dialog)

(unload_dialog dcl_id)

);defun c:lisp_9

Wczytujemy program lisp_9.lsp wpisując w linii poleceń AutoCAD-a (load "lisp_9") i wciskając Enter, a następnie uruchamiamy go z klawiatury, wpisując wywołanie lisp_9 oraz wciskając Enter.

0x01 graphic

Rys. 1. Szablon okna dialogowego z widocznymi jedynie przyciskami OK i Anuluj

Dodajemy do naszego szablonu okna potrzebne elementy według schematu widocznego na rysunku poniżej.

0x01 graphic

Rys. 2. Struktura okna dialogowego

Po ich dodaniu nasze okno powinno wyglądać w sposób następujący:

0x01 graphic

Rys. 3. Wygląd okna dialogowego

Widok pliku lisp_9.dcl po umieszczeniu w nim wszystkich wycinków:

dialog9 : dialog {

label = " Lisp_9";

: boxed_column {

: radio_row {

: radio_button {

label = "0.0";

key = "k_0";

mnemonic = "0";

}

: radio_button {

label = "90.0";

key = "k_90";

mnemonic = "9";

}

: radio_button {

label = "180.0";

key = "k_180";

mnemonic = "1";

}

: radio_button {

label = "270.0";

key = "k_270";

mnemonic = "2";

}

: radio_button {

label = "inny:";

key = "k_inny";

mnemonic = "i";

}

}

: row {

: edit_box {

label = "Kąt :";

key = "kat";

mnemonic = "K";

}

: button {

label = "Pick <";

key = "pick_ra";

mnemonic = "P";

}

}

}

ok_cancel;

}

Przystępujemy do "oprogramowania" elementów okna dialogowego poprzez dodanie w pliku lisp_9.lsp linii kodu do obsługi poszczególnych elementów okna dialogowego.

W pliku lisp_9.lsp umieszczamy z kolei:

(defun c:lisp_9 () ;[1]

(defun show_dialog () ;[2]

(setq dcl_id (load_dialog "lisp_9")) ;[3]

(if(not(new_dialog "dialog9" dcl_id))(exit)) ;[4]

W pierwszej linii za pomocą funkcji defun umieszczamy wywołanie programu Lisp_9. Wywołanie jest to ciąg znaków, po wpisaniu których dany program zostanie uruchomiony.

W drugiej linii za pomocą funkcji defun umieszczamy wywołanie programu show_dialog.

W linii (setq dcl_id (load_dialog "lisp_9")) przypisujemy zmiennej dcl_id wartość (load_dialog "lisp_9") czyli "podpowiadamy", że definicja okna dialogowego znajduje się w pliku lisp_9.dcl.

Linia (if(not(new_dialog "dialog9" dcl_id))(exit)) powoduje, że AutoCAD przeszukuje plik lisp_9.dcl w poszukiwaniu identyfikatora okna dialogowego dialog9 (funkcja (new_dialog) inicjuje i wyświetla okno dialogowe).

(if(/= il nil)(set_tile "kat" il)); jeżeli wartość zmiennej il jest różna od nil, w okienku dialogowym zostanie wyświetlona wartość zmiennej il.

Przypisanie akcji do zdarzenia związanego z wciśnięciem przycisku OK..

(action_tile "accept" "(setq what_next 0)(done_dialog 1)")

(action_tile "cancel" "(setq what_next 0)(done_dialog 0)")

Wciśnięcie przycisku OK powoduje przypisanie zmiennej what_next wartości 0, a następnie ukrycie okna dialogowego

Przypisanie akcji do zdarzenia związanego z wciśnięciem przycisku Anuluj. Wciśnięcie przycisku Anuluj powoduje przypisanie zmiennej what_next wartości 0, a następnie ukrycie okna dialogowego.

(setq radius (get_tile "kat"));

Przypisanie zmiennej radius wartości pobranej za pomocą funkcji get_tile z pola okienka edycyjnego (edit_box) o kluczu kat.

(action_tile "pick_ra" "(setq what_next 1)(done_dialog 2)");

Przypisanie akcji związanej z wciśnięciem przycisku "pick_ra". Wciśnięcie tego przycisku powoduje przypisanie zmiennej what_next wartości 1, a następnie ukrycie okna dialogowego.

(action_tile "k_0" "(setq w_n 0)(akcja)")

Przypisanie akcji do przycisku opcji o kluczu "k_0". Wciśnięcie tego przycisku opcji powoduje przypisanie zmiennej w_n wartości 0, a następnie wywołanie funkcji akcja.

(action_tile "k_90" "(setq w_n 90)(akcja)")

Przypisanie akcji do przycisku opcji o kluczu "k_90". Wciśnięcie tego przycisku opcji powoduje przypisanie zmiennej w_n wartości 90, a następnie wywołanie funkcji akcja.

(action_tile "k_180" "(setq w_n 180)(akcja)")

Przypisanie akcji do przycisku opcji o kluczu "k_180". Wciśnięcie tego przycisku opcji powoduje przypisanie zmiennej w_n wartości 180, a następnie wywołanie funkcji akcja.

(action_tile "k_270" "(setq w_n 270)(akcja)")

Przypisanie akcji do przycisku opcji o kluczu "k_270". Wciśnięcie tego przycisku opcji powoduje przypisanie zmiennej w_n wartości 270, a następnie wywołanie funkcji akcja.

(action_tile "k_inny" "(setq w_n 1)(akcja)(mode_tile \"kat\" 2)")

Przypisanie akcji do przycisku opcji o kluczu "k_inny". Wciśnięcie tego przycisku opcji powoduje przypisanie zmiennej w_n wartości 1, a następnie wywołanie funkcji akcja. Po wywołaniu funkcji akcja ustawiony zostaje tryb pracy wycinka na 2.

(defun akcja () ; zdefiniowanie wywołania funkcji

; akcja za pomocą funkcji defun.

(setq il nil) ; przypisanie do zmiennej il wartości nil

(setq kat (itoa w_n)) ; przypisanie zmiennej kat wartości

; zmiennej w_n przekonwertowanej z liczby typu

; integer na łańcuch cyfr np. (itoa 12) = "12"

(if(= w_n 1)(setq kat "inny")) ;jeżeli zmienna w_n ma wartość

; 1, to przypisujemy zmiennej kat wartość "inny"

(set_tile "kat" kat) ; ustawiamy w okienku edycyjnym

; wartości zmiennej kat

(setq kat w_n) ; przypisujemy zmiennej kat wartość zmiennej w_n

);defun ; kończy wywołanie funkcji akcja

(action_tile "kat" "(try)")

Przypisanie akcji do okienka edycyjnego. Zmiana wartości w okienku edycyjnym powoduje wywołanie funkcji try.

(defun try ()

Zdefiniowanie wywołania funkcji try za pomocą funkcji defun.

(setq kat (get_tile "kat"))

Przypisanie zmiennej kat wartości pobranej z wycinka okienko edycyjne.

(setq kat (atof kat))

Przypisanie zmiennej kat wartości zmiennej kat po dokonanej konwesji z łańcucha tekstowego na liczbę typu real.

);defun ; kończy wywołanie funkcji try

(start_dialog) ; rozpoczyna pobieranie informacji od

; użytkownika z okna dialogowego zainicjowanego

; przez wywołanie funkcji new_dialog.

(unload_dialog dcl_id) ; usuwa z pamięci wskazany plik DCL.

);end_defun_show_dialog ; kończy wywołanie funkcji show_dialog

(setq what_next 0) ; przypisanie zmiennej what_next wartości 0

(show_dialog) ; wywołanie funkcji show_dialog

(defun get_angle () ; zdefiniowanie wywołania funkcji get_angle

(setq il (rtos (getorient "\nWskaz :"))) ; pobranie od użytkownika

; wartości kąta poprzez wskazanie dwóch punktów na ekranie

; graficznym AutoCAD-a

(setq kat (atof il)) ; przypisanie zmiennej kat wartości

; zmiennej kat przekonwertowanej za pomocą funkcji

; AutoLispu atof z łańcucha tekstowego na wartość typu real.

(setq what_next 0) ; przypisanie zmiennej what_next wartości 0.

(show_dialog) ; wywołanie funkcji show_dialog

) ; koniec funkcji get angle

(while (> what_next 0)(get_angle))

tak długo, jak długo prawdziwy będzie warunek what_next > 0, uruchamiana będzie funkcja get_angle.

(princ) ; czyszczenie linii poleceń

Formowanie komunikatu do podawania wartości kąta

(setq a "Kąt wynosi : ") ; przypisanie zmiennej a

; łańcucha tekstowego "Kąt wynosi :"

(setq b (rtos kat)) ; przypisanie zmiennej b wartości

; zmiennej kat przekonwertowanej za pomocą

; funkcji rtos na łańcuch alfanumeryczny (tekst).

(prompt (strcat a b)) ; wyświetlenie w linii poleceń

; tekstu powstałego z połączenia dwóch łańcuchów

; tekstu (a I b)

(princ) ; czyszczenie linii poleceń

);end_defun_lisp_9 ; koniec funkcji lisp_9

Lekcja 10 -- Wybieramy element z listy elementów, ale tym razem, o dziwo, niekoniecznie z listy

0x01 graphic

Tematem bieżącej lekcji jest poznanie sposobu zmiany trybu pracy wycinka na podstawie programu do wyboru elementu z listy dostępnych elementów.

Zakładamy, że wyboru można dokonać na dwa sposoby.

Dwa przyciski opcji posłużą nam do ustawiania odpowiednich wycinków jako nieaktywne, dzięki czemu:

  • Wyboru elementu możemy dokonać poprzez wskazanie danego elementu na liście (list_box) -- w tym wypadku automatycznie blokowana jest możliwość wyboru poprzez wpisanie nazwy elementu w oknie edycyjnym (edit_box).

  • Wyboru elementu możemy dokonać poprzez wpisanie nazwy elementu w oknie edycyjnym -- w tym wypadku automatycznie blokowana jest możliwość wyboru poprzez wskazanie nazwy elementu na liście (list_box).

Zakładamy, że elementy okna dialogowego rozmieścimy w dwóch wierszach, przy czym w górnym wierszu znajdują się wycinki: przyciski opcji (radio_button), które będą sterować trybem pracy pozostałych wycinków oraz okno kartotekowe (list_box), w którym wyświetlimy listę dostępnych elementów.

W dolnym wierszu umieścimy okno edycyjne (edit_box), które umożliwi nam wybór elementu poprzez wpisanie jego nazwy.

W przykładzie tym zetkniemy się z funkcją mode_tile do ustawiania trybu pracy wycinka

Pisanie programu zwyczajowo rozpoczynamy od wykorzystania szablonów plików lisp_1.lsp i lisp_1.dcl, zapisując je pod nazwami odpowiednio

:

lisp_10.dcl:

Dialog9 : dialog {

label = "Program Lisp_10";

}

ok_cancel;

}

lisp_10.lsp:

(defun c:lisp_10 ()

(setq dcl_id (load_dialog "lisp_10"))

(if(not(new_dialog "dialog1" dcl_id))(exit))

(start_dialog)

(unload_dialog dcl_id)

);defun c:lisp_10

Wczytujemy program lisp_9.lsp, wpisując w linii poleceń AutoCAD-a (load "lisp_10") i wciskając Enter, a następnie uruchamiamy go z klawiatury, wpisując wywołanie lisp_10 oraz wciskając Enter.

0x01 graphic

Rys. 1. Szablon okna dialogowego z widocznymi jedynie przyciskami OK i Anuluj

Dodajemy do naszego szablonu okna potrzebne elementy według schematu widocznego na rysunku poniżej.

0x01 graphic

Rys. 2. Struktura okna dialogowego

Po ich dodaniu nasze okno powinno wyglądać w sposób następujący:

0x01 graphic

Rys. 3. Wygląd okna dialogowego

Widok pliku lisp_10.dcl po umieszczeniu w nim wszystkich wycinków:

dialog10 : dialog {

label = " Zmiana trybu pracy wycinka";

: row {

: boxed_radio_column {

spacer_1;

: radio_button {

label = "Wybiorę z listy";

key = "r_1";

mnemonic = "W";

width = 1;

}

: radio_button {

label = "Wpiszę z klawiatury";

key = "r_2";

mnemonic = "W";

width = 3;

}

spacer_1;

spacer_1;

}

: boxed_column {

label = "Lista :";

mnemonic = "L";

: list_box {

key = "l_1";

width = 10;

}

}

}

: boxed_column {

: edit_box {

label = "Nazwa elem.";

key = "box_1";

mnemonic = "N";

width = 6;

}

}

spacer_1;

ok_cancel;

}

Przystępujemy do "oprogramowania" elementów okna dialogowego poprzez dodanie w pliku lisp_10.lsp linii kodu do obsługi poszczególnych elementów okna dialogowego.

W pliku lisp_10.lsp umieszczamy z kolei:

(defun c:lisp_10 ()

(setq dcl_id (load_dialog "lisp_10"))

(if(not(new_dialog "dialog10" dcl_id))(exit))

W pierwszej linii za pomocą funkcji defun umieszczamy wywołanie programu Lisp_10. Wywołanie jest to ciąg znaków, po wpisaniu których dany program zostanie uruchomiony.

W linii (setq dcl_id (load_dialog "lisp_10")) przypisujemy zmiennej dcl_id wartość (load_dialog "lisp_10"), czyli "podpowiadamy", że definicja okna dialogowego znajduje się w pliku lisp_10.dcl.

Trzecia linia: (if(not(new_dialog "dialog10" dcl_id))(exit)) powoduje, że AutoCAD przeszukuje plik lisp_10.dcl w poszukiwaniu identyfikatora okna dialogowego dialog10 (funkcja (new_dialog) inicjuje i wyświetla okno dialogowe).

Przypisujemy akcję do przycisku opcji o kluczu "r_1" -- wybranie tego przycisku powoduje, że wycinek "okno edycyjne" (edit_box) staje się nieaktywny i wyboru możemy dokonać tylko poprzez wskazanie elementu na liście.

(action_tile "r_1"

"(mode_tile \"l_1\" 0)(mode_tile \"box_1\" 1)(list_c)")

Przypisujemy akcję do przycisku opcji o kluczu "r_2" -- wybranie tego przycisku powoduje, że wycinek "okno kartotekowe" (list_box) staje się nieaktywny i wyboru możemy dokonać tylko poprzez wpisanie nazwy elementu w oknie edycyjnym.

(action_tile "r_2" "(list_a)(mode_tile \"box_1\" 0)

(mode_tile \"l_1\"1)(mode_tile ->\"box_1\" 2)")

Poniżej znajduje się przypisanie akcji do zdarzenia związanego z wciśnięciem przycisku OK. Wciśnięcie przycisku OK powoduje wyświetlenie, a następnie ukrycie okna dialogowego. Następnie przypisujemy akcję do zdarzenia związanego z wciśnięciem przycisku Anuluj. Wciśnięcie przycisku Anuluj powoduje ukrycie okna dialogowego.

(action_tile "accept" "(done_dialog 1)")

(action_tile "cancel" "(done_dialog 0)")

Tworzymy nową listę i przypisujemy jej wartość zmiennej listc

(setq listc (list " 35 C" " 40 C" " 45 C" " 50 C" " 65 C" " 80 C"

" 100 C" " 120 C" " 140 C" " 160 C" " 180 C" " 200 C" ))

Tworzymy nową listę (pustą) i przypisujemy jej wartość zmiennej lista:

(setq lista (list ""))

W wierszu (defun list_c () zaczynamy definicję nowej funkcji list_c

(start_list "l_1") ; przetwarzanie nowej listy autolispu

; w polu listy DCL

(mapcar 'add_list listc) ; wykorzystujemy funkcję mapcar

; w celu dodania listy AutoLISP-u; (lista listc) do

; listy DCL (lista "l_1")

(end_list) ; kończymy przetwarzanie listy

) ; koniec funkcji list_c

(defun list_a () ; umieszczamy wywołanie nowej funkcji list_a

(start_list "l_1") ; rozpoczynamy przetwarzanie listy DCL "l_1"

(mapcar 'add_list lista) ; wykorzystujemy funkcję mapcar w celu dodania

; listy AutoLISP-u (lista lista) do listy DCL (lista "l_1")

(end_list) ; kończymy przetwarzanie listy "l_1"

) ; koniec funkcji list_a

(start_dialog) ; rozpoczyna pobieranie informacji od

; użytkownika z okna dialogowego zainicjowanego

; przez wywołanie funkcji new_dialog.

(unload_dialog dcl_id) ;usuwa z pamięci wskazany plik DCL.

(princ) ;czyszczenie linii poleceń

);koniec funkcji lisp_10

Lekcja 11 -- Okno informacyjne, czyli o tym jak się chwalić i jak stworzyć okno z wyświetlonym w nim plikiem graficznym

0x01 graphic

Podczas dzisiejszej lekcji stworzymy okno informacyjne o programie.

Założenia:

  • po pierwsze zakładamy, że jest się czym chwalić;

  • po drugie, będzie o tym, jak się chwalić, czyli jak stworzyć okno z wyświetlonym w nim plikiem graficznym,

  • "jeden slajd, szczypta tekstu, wolno mieszając czekać, aż stężeje",

  • zakładamy też, że nie musimy robić żadnych założeń.

W przykładzie tym zetkniemy się z funkcjami do obsługi piktogramów: dimx tile i dimy tile -- mierzącymi szerokość i wysokość

Pisanie programu zwyczajowo rozpoczynamy od wykorzystania szablonów plików lisp_1.lsp i lisp_1.dcl, zapisując je pod nazwami odpowiednio:

lisp_11.dcl:

Dialog6 : dialog {

label = "Program Lisp_6";

}

ok_cancel;

}

lisp_11.lsp:

(defun c:lisp_11 ()

(setq dcl_id (load_dialog "lisp_11"))

(if(not(new_dialog "dialog1" dcl_id))(exit))

(start_dialog)

(unload_dialog dcl_id)

);defun c:lisp_11

Wczytujemy program lisp_11.lsp, wpisując w linii poleceń AutoCAD-a (load "lisp_11") i wciskając Enter, a następnie uruchamiamy go z klawiatury, wpisując wywołanie lisp_11 oraz wciskamy Enter.

0x01 graphic

Rys. 1. Szablon okna dialogowego z widocznymi jedynie przyciskami OK i Anuluj

Dodajemy do naszego szablonu okna potrzebne elementy.

0x01 graphic

Rys. 2. Wygląd okna dialogowego

Widok pliku lisp_10.dcl po umieszczeniu w nim wszystkich wycinków:

inf : dialog {

label = " INFORMACJA";

: row {

: column {

: spacer {

}

: image {

key = "logos";

color = dialog_background;

width = 40;

fixed_width = true;

height = 10;

fixed_height = true;

}

}

}

spacer_1;

: text {

label = "Wydawnictwo Helion";

fixed_width = true;

alignment = centered;

}

: text {

label = "__________________________________________";

alignment = centered;

}

spacer_1;

: text {

label = "Copright (c) 2001 Wydawnictwo Helion";

alignment = centered;

}

: text {

label = "Ul. Chopina 6 44 - 100 Gliwice";

alignment = centered;

}

: text {

label = "TEL. (032) 230 98 63";

alignment = centered;

}

: text {

label = "e-mail: helion@helion.pl";

alignment = centered;

}

: text {

label = "http://www.helion.pl";

alignment = centered;

}

: spacer {

}

ok_only;

}

Przystępujemy do "oprogramowania" elementów okna dialogowego poprzez dodanie w pliku lisp_11.lsplinii kodu do obsługi poszczególnych elementów okna dialogowego.

W pliku lisp_11.lsp umieszczamy z kolei:

W pierwszej linii za pomocą funkcji defun umieszczamy wywołanie programu Lisp_11. Wywołanie jest to ciąg znaków, po wpisaniu których dany program zostanie uruchomiony.

(defun c:inf ()

W drugim wierszu przypisujemy zmiennej dcl_id wartość (load_dialog "lisp_11"), czyli "podpowiadamy", że definicja okna dialogowego znajduje się w pliku lisp_11.dcl.

(setq dcl_id(load_dialog "lisp_11"))

AutoCAD przeszukuje plik lisp_11.dcl w poszukiwaniu identyfikatora okna dialogowego inf (funkcja (new_dialog) inicjuje i wyświetla okno dialogowe).

(if(not(new_dialog"inf" dcl_id))

jeśli go nie znajdzie (progn wyświetla nam komunikat o błędzie

(alert "Nie znaleziono pliku lisp_11.dcl")

po czym wychodzi z programu

(exit)

a jeśli go znajdzie, to nie robi nic

) ;koniec progn

) ; koniec if

(setq x11 (dimx_tile "logos") y11 (dimy_tile "logos"))

Wywołujemy funkcje dimx_tile oraz dimy_tile w celu odczytania wysokości i

szerokości wybranego wycinka. Punkt początkowy wycinka (0,0) znajduje się zawsze

w jego lewym górnym narożniku.

(start_image "logos")

Funkcja start_image rozpoczyna tworzenie piktogramu.

(slide_image 0 0 x11 y11 "helion")

Rysujemy slajd AutoCAD-a w piktogramie (w tym przypadku jest to

helion.sld)

(end_image)

Funkcja ta kończy tworzenie piktogramu

(action_tile "accept" "(done_dialog 1)") ; przypisanie akcji

; do zdarzenia związanego z przyciskiem OK.

; Wciśnięcie przycisku OK powoduje ukrycie

; okna dialogowego.

(action_tile "cancel" "(done_dialog 0)") ; przypisanie akcji

; do zdarzenia związanego z przyciskiem Anuluj.

; Wciśnięcie przycisku Anuluj powoduje ukrycie

;okna dialogowego

(start_dialog) ; rozpoczyna pobieranie informacji od

; użytkownika z okna dialogowego, zainicjowanego

; przez wywołanie funkcji new_dialog.

(unload_dialog dcl_id) ;usuwa z pamięci wskazany

; plik DCL.

) ; koniec funkcji Lisp_11

Lekcja 12 -- Free Style, czyli lekcja na temat sztuczek wykorzystywanych podczas pisania okien dialogowych

0x01 graphic

Tematem bieżącej lekcji jest poznanie sztuczek wykorzystywanych podczas pisania okien dialogowych.

Zakładamy, że każdy sposób na to, aby zwiększyć komfort użytkownika podczas pracy z programem, jest dobry. Zakładamy, że każdy sposób, który doda naszemu programowi "to coś", co będzie go odróżniać od innych podobnych programów, jest dobry. Oczywiście, jeżeli "to coś" jest w zgodzie z założeniem pierwszym.

Zakładamy, że użytkownikowi nie zgubi się plik DCL z definicją okna dla naszego programu lispowego. Jeżeli jednak tak się stanie, co z tym fantem począć? To właśnie będzie tematem naszych dzisiejszych rozważań.

Pisanie programu zwyczajowo rozpoczynamy od wykorzystania szablonów plików lisp_1.lsp i lisp_1.dcl, zapisując je pod nazwami odpowiednio:

lisp_12.dcl:

Dialog12 : dialog {

label = "Program Lisp_12";

}

ok_cancel;

}

lisp_12.lsp:

(defun c:lisp_12 ()

(setq dcl_id (load_dialog "lisp_12"))

(if(not(new_dialog "dialog2" dcl_id))

(progn

(alert "Nie znaleziono pliku lisp_12.dcl")

(exit)

);progn

);if

(start_dialog)

(unload_dialog dcl_id)

);defun c:lisp_12

Wczytujemy program lisp_11.lsp wpisując w linii poleceń AutoCAD-a (load "lisp_12") i wciskając Enter, a następnie uruchamiamy go z klawiatury, wpisując wywołanie lisp_12 oraz wciskając Enter.

0x01 graphic

Rys. 1. Szablon okna dialogowego z widocznymi jedynie przyciskami OK i Anuluj

Dodajemy do naszego szablonu okna potrzebne elementy według schematu widocznego na rysunku poniżej.

0x01 graphic

Rys. 2. Struktura okna dialogowego

Po ich dodaniu nasze okno powinno wyglądać w sposób następujący:

0x01 graphic

Rys. 3. Wygląd okna dialogowego

Widok pliku lisp_12.dcl po umieszczeniu w nim wszystkich wycinków:

dialog12 : dialog {

label = " lisp_12";

: boxed_column {

: text {

key = "txt_1";

width = 31;

}

}

: button {

label = "Pomiar kąta";

key = "kat";

mnemonic = "K";

alignment = centered;

fixed_width = true;

}

ok_cancel;

}

Użytkownicy dość często gubią pliki, które są niezbędne do prawidłowego działania naszego programu, napisanego w AutoLISP-ie. A jeśli nawet ich nie zgubią, to często trzymają je poza ścieżką przeszukiwania AutoCAD-a, co prawie na jedno wychodzi, a efekt pozostaje ten sam. Istnieje prosty wybieg, dzięki któremu nie będziemy musieli się przejmować tym problemem.

Poniżej znajduje się listing programu lispowego, na przykładzie którego omówimy to zagadnienie.

Lisp_12 sposobem działania bardzo przypomina lisp_1 z pierwszej lekcji. On również służy do obliczania odległości między dwoma wskazanymi punktami. Różnica polega na tym, że wartość kąta nie jest wyświetlana w oknie dialogowym w okienku edycyjnym, lecz w polu tekstowym.

Przechodzimy do omówienia poszczególnych linii kodu.

Definiujemy nową funkcję o nazwie lisp_12:

(defun c:lisp_12 ()

Przypisujemy zmiennej il wartość pustą (łańcuch pusty " " ):

(setq il " ")

Sprawdzamy warunek logiczny – czy plik o nazwie lisp_12.dcl został znaleziony:

(if(not(findfile "lisp_12.dcl"))

Blok instrukcji wykonywanych, jeżeli test logiczny zwraca PRAWDA.

(progn

Przypisujemy zmiennej plik wartość – otwórz plik lisp_12.dcl do zapisu:

(setq plik (open "lisp_12.dcl" "w"))

Kolejne wiersze zapisują łańcuchy tekstu do pliku lisp_12.dcl (plik ten otworzyliśmy do zapisu). W pliku tym linia po linii zapisywana jest definicja naszego okna dialogowego.

(WRITE-LINE " dialog12 : dialog {" plik)

(WRITE-LINE " label = \" lisp_12\"; " plik)

(WRITE-LINE " : boxed_column { " plik)

(WRITE-LINE " : text { " plik)

(WRITE-LINE " key = \"txt_1\"; " plik)

(WRITE-LINE " width = 31; " plik)

(WRITE-LINE " } " plik)

(WRITE-LINE " } " plik)

(WRITE-LINE " : button { " plik)

(WRITE-LINE " label = \"Pomiar kąta\"; " plik)

(WRITE-LINE " key = \"kat\"; " plik)

(WRITE-LINE " mnemonic = \"K\"; " plik)

(WRITE-LINE " alignment = centered; " plik)

(WRITE-LINE " fixed_width = true; " plik)

(WRITE-LINE " } " plik)

(WRITE-LINE " ok_cancel; " plik)

(WRITE-LINE " } " plik)

(close plik) ; zamykamy plik

);progn ; koniec bloku instrukcji wykonywanych,

; jeżeli test logiczny zwraca wartość PRAWDA

);if ; koniec funkcji if

Definiujemy nową funkcję o nazwie show_dialog.

(defun show_dialog ()

Przypisujemy zmiennej dcl_id wartość (load_dialog "lisp_12") czyli "podpowiadamy", że definicja okna dialogowego znajduje się w pliku lisp_12.dcl.

(setq dcl_id(load_dialog "lisp_12"))

AutoCAD przeszukuje plik lisp_12.dcl w poszukiwaniu identyfikatora okna dialogowego dialog12 (funkcja (new_dialog) inicjuje i wyświetla okno dialogowe).

(if(not(new_dialog"dialog12" dcl_id))

Blok instrukcji wykonywanych, jeżeli test logiczny ma wartość PRAWDA, czyli nie została odnaleziona definicja okna dialogowego.

(progn

wyświetlamy komunikat informujący użytkownika, że plik lisp_12.dcl nie został znaleziony.

(alert "Nie znaleziono pliku lisp_12.dcl")

Opuszczenie programu.

(exit)

);progn ;

) ; koniec if

(set_tile "txt_1" il) ; przypisujemy wycinkowi

; o kluczu "txt_1" wartość zmiennej il

(action_tile "kat" "(setq what_next 1)(done_dialog 2)")

; przypisanie akcji do zdarzenia związanego

; z przyciśnięciem przycisku (button) o kluczu "kat".

; wciśnięcie tego przycisku powoduje przypisanie

; zmiennej what_next wartości 1, a następnie ukrycie

; okna dialogowego.

Do zdarzenia wciśnięcia przycisków OK i Anuluj zostaje przypisana akcja wyjścia z okna dialogowego.

(action_tile "accept" "(done_dialog 1)")

(action_tile "cancel" "(done_dialog 0)")

(start_dialog) ; rozpoczyna pobieranie informacji

; od użytkownika z okna dialogowego zainicjowanego

; przez wywołanie funkcji (new_dialog)

(unload_dialog dcl_id) ; usuwa z pamięci wskazany plik DCL.

) ;defun show_dialog ; koniec procedury show_dialog

(defun get_angle () ; za pomocą funkcji defun

; definiujemy nową procedurę o nazwie get_angle

(setq il (rtos (getorient "\nWskaz :"))) ; pobranie

; od użytkownika wartości kąta poprzez

; wskazanie dwóch punktów na ekranie

; graficznym AutoCAD-a i przypisanie

; zmiennej il wartości odczytanego kąta

(setq il (strcat "Kąt wynosi : " il " radianów"))

; przypisanie zmiennej il wartości powstałej

; przez połączenie łańcucha "Kąt wynosi :

; " wartości zmiennej il oraz łańcucha

; " radianów"

(setq what_next nil) ; przypisujemy zmiennej what_next wartość nil

(show_dialog) ; wywołujemy funkcję show_dialog

);defun ; koniec procedury get_angle

Wywołujemy funkcję show_dialog.

(show_dialog)

Wchodzimy w pętlę while i pozostajemy w tej pętli tak długo, jak długo prawdziwy jest warunek what_next > 0. Jeżeli warunek logiczny test ma wartość PRAWDA, to wywoływana jest funkcja get_angle.

(while (> what_next 0)(get_angle))

(princ) ; czyszczenie ekranu

);defun c:lisp_12 ; koniec definicji programu lisp_12

Lekcja 13 -- Free Style 2 -- czyli o tym, jak programy z własnymi oknami dialogowymi umieścić w oddzielnym programie z własnym oknem i co z tego wynika

0x01 graphic

Tematem bieżącej lekcji jest stworzenie programu z oknem dialogowym, w którym umieścimy wszystkie programy stworzone przez nas podczas tego kursu.

Zakładamy, że po kliknięciu nazwy programu na liście w lewej części okna, automatycznie nazwa ta pojawi się w okienku edycyjnym (edit_box). Równocześnie z pojawieniem się nazwy programu, w okienku edycyjnym po lewej stronie w oknie listy umieszczony zostanie opis tego programu. Listę programów oraz ich opisy otrzymamy poprzez wczytanie ich z pliku pad.inf.

W przykładzie tym zetkniemy się z:

  • zagadnieniami umieszczania i zarządzania listami w oknach dialogowych.

  • zagadnieniem wczytywania danych z pliku tekstowego i umieszczania tych danych w oknie dialogowym.

Pisanie programu zwyczajowo rozpoczynamy od wykorzystania szablonów plików lisp_1.lsp i lisp_1.dcl zapisując je pod nazwami odpowiednio:

lisp_13.dcl:

Dialog13 : dialog {

label = "Program Lisp_13";

}

ok_cancel;

}

lisp_13.lsp:

(defun c:lisp_13 ()

(setq dcl_id (load_dialog "lisp_13"))

(if(not(new_dialog "dialog13" dcl_id))(exit))

(start_dialog)

(unload_dialog dcl_id)

);defun c:lisp_13

Wczytujemy program lisp_13.lsp, wpisując w linii poleceń AutoCAD-a (load "lisp_13") i wciskając Enter, a następnie uruchamiamy go z klawiatury, wpisując wywołanie lisp_13 oraz Enter.

0x01 graphic

Rys. 1. Szablon okna dialogowego z widocznymi jedynie przyciskami OK i Anuluj

Dodajemy do naszego szablonu okna potrzebne elementy według schematu widocznego na rysunku poniżej.

0x01 graphic

Rys. 2. Struktura okna dialogowego

Po ich dodaniu nasze okno powinno wyglądać w sposób następujący:

0x01 graphic

Rys. 3. Wygląd okna dialogowego

Widok pliku lisp_13.dcl po umieszczeniu w nim wszystkich wycinków:

Lisp_13 : dialog {

label = " Control pad";

: boxed_column {

label = "Lista rozdziałów";

mnemonic = "L";

: popup_list {

key = "pop_1";

width = 54;

}

}

: row {

: boxed_column {

label = "Lista aplikacji:";

mnemonic = "L";

: list_box {

key = "lb_name";

width = 17;

}

}

: column {

: boxed_column {

label = "Nazwa";

mnemonic = "N";

: edit_box {

key = "eb_name";

}

spacer_1;

}

: boxed_column {

: button {

label = "Uruchom";

key = "b_uruchom";

mnemonic = "U";

fixed_width = true;

alignment = centered;

}

: spacer {

}

}

: boxed_column {

: image_button {

key = "img_logo";

color = green;

width = 6;

height = 3;

}

: spacer {

}

}

}

: boxed_column {

label = "Opis aplikacji";

mnemonic = "O";

: list_box {

key = "lb_opis";

width = 17;

}

}

}

ok_cancel;

}

Przystępujemy do "oprogramowania" elementów okna dialogowego poprzez dodanie w pliku lisp_13.lsp linii kodu do obsługi poszczególnych elementów okna dialogowego.

W tej lekcji odejdę trochę od schematu używanego przeze mnie podczas poprzednich lekcji. Tutorial ten jest o tyle odmienny, że zawiera wiele funkcji, które mogą być z powodzeniem przedmiotem kilku oddzielnych lekcji, dlatego, aby zbytnio nie rozmywać tematu, postanowiłem potraktować go całościowo. Każda linia kodu została ponumerowana i wyjaśniona. Na ewentualne pytania, które się Państwu nasuną, chętnie odpowiem na liście dyskusyjnej Forum CAD, pod warunkiem, że podacie Państwo w tym pytaniu numer linii kodu, którego to pytanie będzie dotyczyło.

Przechodzimy teraz do wyjaśnienia krok po kroku zawartości pliku lisp_13.lsp.

Pierwsze trzy linijki zaczynające się średnikiem (w pliku DCL to, co znajduje się za średnikiem, stanowi komentarz) kryją nazwę programu głównego.

;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

;////// PAD ///////

;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

Kolejne wiersze kryją nagłówek funkcji do czytania nazw plików w poszczególnych rozdziałach.

;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

;;; Funkcja do czytania nazw plikow w poszczegolnych rozdziałach

;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

Za pomocą funkcji defun umieszczamy wywołanie funkcji czytaj_lispy. Wywołanie jest to ciąg znaków, po wpisaniu których dana funkcja zostanie uruchomiona.

(defun czytaj_lispy ()

(setq txt '()) ; przypisujemy zmiennej txt wartość

; listy (wartość pustą)

(setq ff (open "pad.inf" "r")) ; przypisanie wartości

; zmiennej ff. Wartość zmiennej ff = "otwórz

; plik pad.inf do odczytu".

(setq item (read-line ff)) ; wartość przypisana do

; zmiennej item = czytaj linię tekstu

(while item ; dopóki istnieje linia tekstu

(if (= item rn) ; sprawdzamy warunek, czy pobrana z

; pliku linia tekstu ma wartość rn

(progn ; jeżeli warunek ma wartość TRUE (jest prawdziwy)

(setq data (read-line ff)); przypisujemy zmiennej

; data wartość – zawartość sczytanej z pliku

; linii tekstu

(setq txt (append txt (list data))) ; przypisujemy

; zmiennej txt (na razie wartością zmiennej txt

; jest linia pusta – patrz linia [8]) wartość

; listy powstałej poprzez dodanie do tej listy

; linii tekstu (wartość zmiennej data [14])

(while data ; jak długo z pliku pobierana będzie kolejna

; linia tekstu

(if (= data "") ; sprawdzamy warunek, czy linia, którą

; pobraliśmy z pliku 6, jest "pustą linią"

(progn ; jeżeli tak, to:

(setq data nil) ; przypisujemy zmiennej data wartość nil

);progn

(progn ; jeżeli nie, to:

(setq data (read-line ff)) ; odczytujemy kolejną linię

(setq txt (append txt (list data))) ; i dodajemy tę linię

; do listy txt

);progn ; koniec progn

);if ; koniec warunku if

);while_data ; koniec pętli while data

(setq item nil) ; przypisujemy zmiennej item wartość nil

);progn ; koniec progn item

(progn

(setq item (read-line ff)) ; przypisujemy zmiennej item

; wartość linii odczytanej z pliku

);progn ; koniec progn item

);if ; koniec warunku if

);while_item ; koniec pętli while item

(close ff) ; zamknięcie pliku

); ; koniec funkcji czytaj_lispy

Trochę problemów może sprawić Państwu zrozumienie zasady działania powyższej funkcji z powodu umieszczenia "pętli w pętli", ale bądź co bądź jest to kurs DCL dla zaawansowanych i dotarliśmy już do trzynastej lekcji. Łatwiej będzie Państwu zrozumieć, jak ta funkcja działa, obserwując efekty jej działania.

(defun c:pad () ; za pomocą funkcji defun umieszczamy

; wywołanie procedury pad

(setq ok nil) ; przypisujemy zmiennej ok wartość nil

(defun c:co () ; za pomocą funkcji defun umieszczamy

; wywołanie procedury co

(if(= rn nil) ; sprawdzamy warunek rn = nil

(progn ; blok instrukcji wykonywanych, jeżeli

; warunek zwraca PRAWDA

(setq ff (open "pad.inf" "r")) ; przypisujemy zmiennej ff

; wartość – otwarcie pliku pad.inf do odczytu

(setq data (read-line ff)) ; przypisujemy zmiennej data

; wartość – odczytana linia tekstu

(setq rn (read-line ff)) ; przypisujemy zmiennej rn

; wartość, którą jest odczytana linia tekstu

(close ff) ; zamykamy plik pad.inf

(setq rn (strcat "*" rn)) ; przypisujemy zmiennej

; rn wartość powstałą z połączenia dwóch

; łańcuchów, 1) "*" oraz łańcucha będącego

;linią tekstu odczytaną z pliku pad.inf

);progn ; koniec bloku instrukcji wykonywanych,

; jeżeli warunek if zwraca wartość PRAWDA

(progn ; początek bloku instrukcji, jeżeli warunek

; if zwraca wartość FAŁSZ

(princ ; czyszczenie ekranu – jeżeli warunek if

; zwraca fałsz. Aby się nie pogubić podczas

; pisania programów, tworzę szablon pętli,

; w której umieszczam warunek if i pomiędzy

; blok progn wstawiam funkcje (princ prawda)

; oraz (princ fałsz). Dzięki temu wiem, czy

; przebieg procedury odbywa się zgodnie

; z moimi założeniami. Na koniec usuwam to,

; co niepotrzebne. Mógłbym oczywiście usunąć

; całą funkcję princ, bo to i tak nic by nie

; zmieniło, ale dzięki temu, że samo princ

; i tak generalnie nic w tej procedurze nie

; robi, mogę skojarzyć, jak przebiegało

; dodawanie przeze mnie linii kodu do tej

; procedury.

);progn ; koniec bloku instrukcji wykonywanych,

; jeżeli warunek if zwraca wartość FAŁSZ

);if ; koniec sprawdzania przez funkcję if warunku

; rn = nil

Uruchamiamy funkcję czytaj lispy.

(czytaj_lispy)

Kolejne wiersze kryją nagłówek funkcji czytającej rozdziały z pliku pad.inf. Linie te nie wnoszą nic do programu, ponieważ są poprzedzone średnikiem, co powoduje, że są one traktowane jako komentarz.

;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

;//////funkcja czytająca rozdziały książki z pliku pad.inf///////

;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

(defun czytaj_roz () ; za pomocą funkcji defun umieszczamy

; wywołanie procedury czytaj_roz

(setq l_rozdziałów '()) ; przypisujemy zmiennej l_rozdziałów

; wartość pustej listy – wykorzystamy tę

; zmienną do przechowywania listy rozdziałów

(setq ff (open "pad.inf" "r")); przypisujemy zmiennej ff

; wartość "otwórz plik pad.inf do odczytu"

(setq data (read-line ff)) ; przypisujemy zmiennej data wartość

; będącą linią tekstu odczytaną z pliku pad.inf

(setq data (read-line ff)) ; powtarzamy tę linię, co powoduje,

; że nie jest brana pod uwagę pierwsza linia

; tekstu z pliku pad.inf (pierwszą linię

; umieściłem po to, aby plik tekstowy z

; informacją był bardziej czytelny dla

; użytkownika).

(setq l_rozdziałów (append l_rozdziałów (list data)))

; przypisujemy zmiennej l_rozdziałów wartość

; zmiennej lista rozdziałów po dodaniu do tej

; listy za pomocą funkcji append linii tekstu

; odczytanego z pliku pad.inf

(while data ; wchodzimy w pętlę while, w której będziemy

; tak długo, jak długo wartością zmiennej data

; będzie niepusta linia tekstu odczytana z pliku

; pad.inf (nie nil)

(if (= data "") ; sprawdzamy warunek data = ""

(progn ; blok instrukcji wykonywanych, jeżeli warunek

; zwraca PRAWDA ( linia odczytana z pliku

; pad.inf jest linią pustą " " )

(setq data nil) ; jeżeli PRAWDA, to zmiennej data

; przypisujemy wartość nil

);progn ; koniec bloku instrukcji wykonywanych, jeżeli

; warunek if zwraca PRAWDA

(progn ; początek bloku instrukcji zwracanych,

; jeżeli warunek if zwraca FAŁSZ

(setq data (read-line ff)) ; przypisujemy zmiennej data

; wartość, którą jest zawartość linii tekstu

; odczytana z pliku pad.inf

(setq l_rozdziałów (append l_rozdziałów (list data)))

; przypisujemy liście l_rozdziałów wartość

; powstałą przez powiększenie tej listy o

; linię tekstu odczytanego z pliku pad.inf

);progn ; koniec bloku instrukcji wykonywanych, jeżeli warunek

; if zwraca FAŁSZ

);if ; koniec bloku instrukcji warunkowej jeżeli (if),

; sprawdzającej warunek data = " "

);while_data ; wychodzimy z pętli while (zmienna data

; na wartość nil)

(close ff) ; zamykamy plik pad.inf

);defun czytaj_roz ; koniec procedury czytającej nazwy rozdziałów

(if (= l_rozdziałów nil) ; sprawdzamy warunek l_rozdziałów = nil

(czytaj_roz)(princ)) ; jeżeli zmienna l_rozdziałów ma wartość

; nil (warunek logiczny ma wartość prawda),

; to wywołana zostaje funkcja czytaj_roz.

(defun koniec () ; za pomocą funkcji defun umieszczamy wywołanie

; procedury koniec

(setq dd (get_tile "pop_1")) ; przypisujemy zmiennej dd wartość

; pobraną z listy rozwijanej, która służy nam do

; wyświetlania nazw rozdziałów

) ; kończymy procedurę koniec

W kolejnym wierszu umieszczamy komentarz, który informuje nas o przeznaczeniu funkcji czytaj_opis -- funkcja ta będzie wykorzystywana przez nas do czytania z pliku pad.inf opisów lispów.

;\\\\\\\\\\\\\\\\\\\\\\Funkcja czytająca opis////////////////

(defun czytaj_opis () ; za pomocą funkcji defun umieszczamy

; wywołanie procedury czytaj_opis

(setq top '()) ; przypisujemy zmiennej top wartość listy pustej

(setq fop (open "pad.inf" "r")) ; przypisujemy zmiennej fop

; wartość – otwarcie pliku pad.inf do odczytu

(setq itop (read-line fop)) ; przypisanie zmiennej itop

; wartości, która jest linią tekstu odczytaną

; z pliku pad.inf

(while itop ; wchodzimy w pętlę while i przetwarzamy instrukcje

; wewnątrz pętli tak długo, jak długo zmienna

; itop ma wartość różną od nil

(if (= itop opis) ; sprawdzamy warunek itop = opis

(progn ; rozpoczynamy blok instrukcji wykonywanych,

; jeżeli warunek logiczny zwraca PRAWDA

(setq dataop (read-line fop)) ; przypisujemy zmiennej dataop

; wartość linii tekstu odczytanego z pliku pad.inf

(setq top (append top (list dataop))) ; przypisujemy zmiennej

; top wartość powstałą poprzez dodanie do listy

; top elementu będącego linią tekstu odczytaną

; z pliku pad.inf

(while dataop ; wchodzimy w pętlę while i przetwarzamy linie kodu

; wewnątrz tej pętli tak długo, jak długo

; zmienna dataop będzie miała wartość różną od nil

(if (= dataop "") ; sprawdzamy warunek dataop = "" (czy linia

; tekstu odczytana z pliku pad.inf jest linią pustą)

(progn ; blok instrukcji wykonywanych, jeżeli warunek logiczny

;ma wartość PRAWDA

(setq dataop nil) ; przypisujemy zmiennej dataop wartość nil

);progn ; koniec bloku instrukcji wykonywanych, jeżeli warunek

; logiczny ma wartość PRAWDA

(progn ; rozpoczynamy blok instrukcji wykonywanych, jeżeli warunek

; logiczny zwraca FAŁSZ

(setq dataop (read-line fop)) ; przypisanie zmiennej dataop wartości

; w postaci linii tekstu odczytanej z pliku pad.inf

(setq top (append top (list dataop))) ; przypisanie zmiennej

; top wartości powstałej poprzez powiększenie

; tej zmiennej o linię tekstu odczytaną z pliku

; pad.inf

);progn ; koniec bloku instrukcji wykonywanych, jeżeli warunek

; logiczny ma wartość FAŁSZ

);if ; koniec instrukcji warunkowej if

);while_data ; koniec pętli while

(setq itop nil) ; przypisanie zmiennej itop wartości nil

);progn ; koniec bloku instrukcji wykonywanych, jeżeli warunek

; logiczny itop = opis zwraca PRAWDA

(progn ; blok instrukcji wykonywanych, jeżeli warunek logiczny

; itop = opis zwraca FAŁSZ

(setq itop (read-line fop)) ; przypisujemy zmiennej itop wartość,

; którą jest linia tekstu odczytana z pliku pad.inf

);progn ; koniec bloku instrukcji wykonywanych, jeżeli wartość

; logiczna warunku itop = opis jest równa FAŁSZ

);if ; koniec instrukcji warunkowej if itop

);while_item ; koniec pętli logicznej (wychodzimy z pętli while

; item, ponieważ zmienna item ma wartość nil)

(close fop) ; zamykamy plik pad.inf

(defun do_opis () ; za pomocą funkcji defun umieszczamy wywołanie

; procedury do_opis.

(start_list "lb_opis") ; rozpoczynamy przetwarzanie listy DCL lb_opis

(mapcar 'add_list top) ; do listy lb_opis dodajemy za pomocą funkcji

; AutoLISP-u mapcar elementy listy top

(end_list) ; kończymy przetwarzanie listy lb_opis

);defun ; koniec procedury do_opis

);defun koniec procedury czytaj_opis

;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

(defun do_lista () ; definiujemy nową procedurę o nazwie do_lista

(start_list "lb_name") ; rozpoczynamy przetwarzanie listy lb_name

(mapcar 'add_list txt) ; dodajemy do tej listy elementy listy txt

(end_list) ; kończymy przetwarzanie listy lb_name

);defun ; koniec procedury do_lista

;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\

W kolejnym wierszu przypisujemy zmiennej dcl_id wartość (load_dialog "lisp_13"), czyli "podpowiadamy", że definicja okna dialogowego znajduje się w pliku lisp_13.dcl.

(setq dcl_id (load_dialog "lisp_13"))

AutoCAD przeszukuje plik lisp_13.dcl w poszukiwaniu identyfikatora okna dialogowego lisp_13 (funkcja (new_dialog) inicjuje i wyświetla okno dialogowe). Jeżeli identyfikator nie zostanie znaleziony, wywołana zostanie funkcja exit.

(if(not(new_dialog "lisp_13" dcl_id))(exit))

(czytaj_lispy) ; wywołanie procedury czytaj_lispy

(do_lista) ; wywołanie procedury do_lista

(if (= dd nil)(princ)(set_tile "pop_1" dd)) ; jeżeli zmienna

; dd ma wartość różną od nil, to elementowi okna

; dialogowego o kluczu pop_1 nadajemy wartość

; równą wartości zmiennej dd

Przypisanie akcji do zdarzenia związanego z przyciskiem OK. Wciśnięcie przycisku OK powoduje przypisanie zmiennej ok wartości równej 15, następnie uruchomiona zostaje funkcja koniec, po czym następuje ukrycie (usunięcie z pamięci) okna dialogowego.

(action_tile "accept" "(setq ok 15)(koniec)(done_dialog 1)")

Przypisanie akcji do zdarzenia związanego z przyciśnięciem przycisku Anuluj. Wciśnięcie tego przycisku powoduje przypisanie zmiennej ok. wartości 15, a następnie ukrycie okna dialogowego.

(action_tile "cancel" "(setq ok 15)(done_dialog 0)")

Przypisanie akcji do zdarzenia związanego z wybraniem jakiegokolwiek elementu z listy rozwijanej (popup_list) powiązanej kluczem pop_1. Wybranie przez użytkownika jakiegokolwiek elementu z listy powoduje uruchomienie procedury nazwa_rozdziału z parametrem item. Następnie zostaje uruchomiona procedura czytaj_lispy, a po niej uruchomienie procedury do_lista.

(action_tile "pop_1" "(nazwa_rozdzialu

)(czytaj_lispy)(do_lista)")

Przypisanie zdarzenia związanego z wskazaniem któregokolwiek elementu na liście o kluczu lb_name (na liście tej znajdują się nazwy lispów). Wskazanie elementu na liście powoduje uruchomienie funkcji nazwa_lispu z parametrem item. Następnie uruchamiana jest funkcja czytaj_opis, której zadaniem jest pobranie z pliku pad.inf opisu lisp-a. Na koniec uruchomiona zostaje funkcja do_opis, której zadaniem jest umieszczenie opisu lisp-a w oknie dialogowym.

(action_tile "l0b_name" "(nazwa_lispu

)(czytaj_opis)(do_opis)")

Przypisanie akcji do zdarzenia związanego z wciśnięciem przycisku (button) powiązanego kluczem b_uruchom. Wciśnięcie tego przycisku powoduje przypisanie zmiennej ok wartości równej 4, a następnie ukrycie okna dialogowego.

(action_tile "b_uruchom" "(setq ok 4)(done_dialog 2)")

(start_list "pop_1") ; rozpoczynamy przetwarzanie listy DCL o

; kluczu pop_1

(mapcar 'add_list l_rozdziałów) ; dodajemy do przetwarzanej

; listy elementy listy l_rozdziałów

(end_list) ; kończymy przetwarzanie listy

(defun nazwa_rozdzialu (item) ; definiujemy nową funkcję o

; nazwie nazwa_rozdziału.

(setq rn (nth (atoi item)l_rozdziałów)) ; przypisujemy

; zmiennej rn wartość n-tego elementu lisy

; l_rozdziałów przekonwertowanego za pomocą

; funkcji standardowej AutoLisp-u atoi (atoi

; zwraca wynik konwersji łańcucha tekstowego

; na liczbę całkowitą typu integer.

(setq rn (strcat "*" rn)) ; przypisujemy zmiennej rn wartość

; powstałą z połączenia za pomocą funkcji strcat

; łańcucha "*" oraz wartości zmiennej rn.

);defun ; koniec procedury nazwa_rozdziału

(defun nazwa_lispu (item) ; definiujemy nową procedurę o nazwie

; nazwa_lispu.

(setq ln (nth (atoi item)txt)) ; przypisujemy zmiennej ln wartość

; n-tego elementu listy txt przekonwertowanego

; za pomocą funkcji standardowej AutoLisp-u atoi

; (atoi zwraca wynik konwersji łańcucha tekstowego

; na liczbę całkowitą typu integer).

(set_tile "eb_name" ln) ; wyświetlamy w okienku edycyjnym

; (edit_box) o kluczu eb_name wartość zmiennej

; ln

(setq opis ln) ; przypisujemy zmiennej opis wartość zmiennej ln

(setq opis (strcat "*" opis)) ; przypisujemy zmiennej opis wartość

; powstałą z połączenia łańcucha "*" oraz

; zmiennej opis

);defun ; koniec procedury nazwa lispu

(start_dialog) ; rozpoczyna pobieranie informacji od użytkownika

; z okna dialogowego zainicjowanego przez wywołanie

; funkcji new_dialog.

(unload_dialog dcl_id) ; usuwa z pamięci wskazany plik DCL.

);end_defun_co ; koniec funkcji o nazwie co

(defun loader () ; definiujemy nową funkcję o nazwie loader

(if (= ok 15) ; sprawdzamy warunek logiczny ok = 15

(progn ; blok instrukcji przetwarzany, jeżeli wartość

; logiczna test jest równa PRAWDA

(setq ln nil) ; przypisujemy zmiennej ln wartość nil

);progn ; koniec bloku instrukcji wykonywanych, jeżeli wartość

; logiczna test jest równa PRAWDA

(progn ; blok instrukcji przetwarzany, jeżeli wartość logiczna

; test jest równa FAŁSZ

(load ln) ; wczytanie do AutoCAD-a pliku Lispowego o nazwie,

; przechowywanej przez zmienną ln

(setq nl (strcat "(c:" ln ")" )) ; przypisanie zmiennej nl wartości

; powstałej poprzez połączenie łańcucha "(c:"

; zmiennej ln oraz łańcucha ")"

; ln = "(c:" + ln + ")"

(eval (read nl)) ; wykorzystujemy standardowe funkcje AutoLISP-u

; eval i read do uruchomienia programu autolisp,

; którego nazwę przechowuje zmienna nl.

; przykład funkcji read: (read "(c:lisp_1)")

; zwraca atom (c:lisp_1)

; przykład funkcji eval: (setq a 11) -> (eval a)

; zwraca 11

);progn ; koniec bloku instrukcji wykonywanych, jeżeli wartość

; logiczna test jest równa FAŁSZ

);if ; koniec testu logicznego if

);defun_loader ; koniec funkcji loader

(defun try () ; definiujemy nową funkcję o nazwie try.

(while (< ok 15)(c:co)(loader)(princ)) ; wchodzimy w pętlę logiczną

; while, instrukcje wewnątrz tej pętli będą wykonywane

; tak długo, jak długo wartość zmiennej ok. będzie

; mniejsza od 15

);try ; koniec funkcji try

(try) ; uruchamiamy funkcję try

);end_defun_pad ; koniec funkcji pad

Lekcja 14 -- Free Style 3 -- czyli dynamiczna zmiana wielkości okna

0x01 graphic

Tematem bieżącej lekcji jest stworzenie programu z oknem dialogowym, w którym umieścimy okienko edycyjne, służące do pobrania od użytkownika informacji. Za pomocą przycisków Zwiększ i Zmniejsz będziemy sterować wielkością okienka edycyjnego (edit_box).

Zakładamy, że naciśnięcie przycisku OK spowoduje wyjście z programu pod warunkiem, że wpisaliśmy wcześniej dowolny tekst w okienku edycyjnym. Jeżeli nie wpiszemy żadnego tekstu w okienku edycyjnym i wciśniemy przycisk OK, w wycinku errtile pojawi się komunikat o błędzie.

Wciśnięcie przycisku Zwiększ spowoduje zwiększenie szerokości okienka edycyjnego.

Wciśnięcie przycisku Zmniejsz spowoduje zmniejszenie szerokości okienka edycyjnego.

W przykładzie tym:

  1. zetkniemy się z zagadnieniami umieszczania w pliku DCL kilku definicji okien dialogowych

  2. zapoznamy się z wycinkiem errtile, służącym do wyświetlania komunikatów o błędach

  3. zapoznamy się z funkcją AutoLispu-u alert służącą do wyświetlania komunikatów

Pisanie programu zwyczajowo rozpoczynamy od wykorzystania szablonów plików lisp_1.lsp i lisp_1.dcl, zapisując je pod nazwami odpowiednio:

lisp_14.dcl:

Dialog14 : dialog {

label = "Program Lisp_14";

}

ok_cancel;

}

lisp_14.lsp:

(defun c:lisp_14 ()

(setq dcl_id (load_dialog "lisp_14"))

(if(not(new_dialog "dialog14" dcl_id))(exit))

(start_dialog)

(unload_dialog dcl_id)

);defun c:lisp_14

Wczytujemy program lisp_14.lsp, wpisując w linii poleceń AutoCAD-a (load "lisp_14") i wciskając Enter, a następnie uruchamiamy go z klawiatury, wpisując wywołanie lisp_14 oraz wciskając Enter.

0x01 graphic

Rys. 1. Szablon okna dialogowego z widocznymi jedynie przyciskami OK i Anuluj

Dodajemy do naszego szablonu okna potrzebne elementy według schematu widocznego na rysunku poniżej.

0x01 graphic

Rys. 2. Struktura okna dialogowego

Po ich dodaniu nasze okno powinno wyglądać w sposób następujący:

0x01 graphic

Rys. 3. Wygląd okna dialogowego

Widok pliku lisp_14.dcl po umieszczeniu w nim wszystkich wycinków.

dialog14 : dialog {

label = " Wycinek Error - przykład";

: boxed_column {

label = "Wpisz poniżej swoje imię :";

mnemonic = "W";

: edit_box {

key = "imie";

width = 2;

}

spacer_1;

}

errtile;

ok_cancel;

}

Chcemy, aby w naszym programie istniała możliwość zmiany wielkości elementu okna dialogowego bez opuszczania programu. Korzystając z tego, że w jednym pliku dcl możemy umieścić więcej niż jedną definicję okna dialogowego, kopiujemy dwa razy widoczne na listingu powyżej linie kodu i zmieniamy nazwy dialogów tak, jak jest to przedstawione na schemacie poniżej.

0x01 graphic

Rys. 4. Schemat struktury pliku lisp_14.dcl

(defun c:lisp_14() ; za pomocą funkcji defun umieszczamy

; wywołanie programu. Wywołanie jest

; to ciąg znaków, po wpisaniu których

; dany program zostanie uruchomiony.

(setq licznik 1) ; przypisujemy zmiennej licznik wartość 1

(setq napis " ") ; przypisujemy zmiennej napis wartość " "

; (puste spacje nie będą widoczne

; w oknie edycyjnym

(defun error_zw () ; umieszczamy wywołanie programu error_zw

(alert "Nie można bardziej powiększyć") ; wyświetlenie

; komunikatu za pomocą funkcji alert

) ; koniec funkcji error_zw

(defun error_zm () ; umieszczamy wywołanie programu error_zm

(alert "Nie można bardziej pomniejszyć") ; wyświetlenie komunikatu

; za pomocą funkcji alert

) ; koniec funkcji error_zm

(defun czytaj_napis () ; definiujemy wywołanie nowej funkcji

(setq napis (get_tile "imie")) ; przypisujemy zmiennej napis

; wartość pobraną z okienka edycyjnego

);defun ; koniec funkcji czytaj_napis

(defun show_dialog () ; definiujemy wywołanie funkcji

; show_dialog

(defun show_dialog_14_1 () ; definiujemy wywołanie funkcji

; show_dialog_14_1

(setq dcl_id (load_dialog "lisp_14")) ; przypisujemy zmiennej

; dcl_id wartość

(load_dialog "lisp_14_1") ; czyli "podpowiadamy", że definicja

; okna dialogowego znajduje się w pliku

; lisp_14.dcl.

Linia (if(not(new_dialog "dialog14_1" dcl_id))(exit)) powoduje, że AutoCAD przeszukuje plik lisp_14.dcl w poszukiwaniu identyfikatora okna dialogowego dialog14_1 (funkcja new_dialog inicjuje i wyświetla okno dialogowe).

Ustawiamy wartość w okienku edycyjnym (edit_box) równą wartości zmiennej napis.

(set_tile "imie" napis)

Przypisanie akcji do zdarzenia związanego z wciśnięciem przycisku OK. Wciśnięcie przycisku OK powoduje przypisanie zmiennej licznik wartości 0, a następnie wywołanie funkcji get_name.

(action_tile "accept" "(setq licznik 0)(get_name)")

Przypisanie akcji do zdarzenia związanego z wciśnięciem przycisku Anuluj. Wciśnięcie przycisku Anuluj powoduje przypisanie zmiennej licznik wartości 0, a następnie ukrycie okna dialogowego.

(action_tile "cancel" "(setq licznik 0)(done_dialog 0)")

Przypisanie akcji do zdarzenia związanego z wciśnięciem przycisku Zwiększ. Wciśnięcie przycisku Zwiększ powoduje wywołanie funkcji czytaj_napis, przypisanie zmiennej licznik wartości 2, a następnie ukrycie okna dialogowego.

(action_tile "zw" "(czytaj_napis)(setq licznik 2)(done_dialog 1)")

Przypisanie akcji do zdarzenia związanego z wciśnięciem przycisku Zmniejsz. Wciśnięcie przycisku Zmniejsz powoduje wywołanie funkcji error_zm, która wyświetla za pomocą funkcji AutoLISP-u alert okno z informacją.

action_tile "zm" "(error_zm)")

(defun get_name () ; definiujemy wywołanie nowej funkcji

; o nazwie get_name

(setq a (get_tile "imie")) ; przypisujemy zmiennej a wartość

; pobraną z wycinka edit_box za pomocą

; funkcji get_tile

Sprawdzamy za pomocą funkcji logicznej if warunek a = " " Jeżeli wartość logiczna test jest PRAWDA to wysyłamy do wycinka errtile o kluczu error informację o błędzie. Jeżeli wartością logiczną test jest FAŁSZ to ukrywamy okno dialogowe.

(if(= a " ")(set_tile "error" "Błąd : Musisz wpisać imię!")(done_dialog1))

) ;defun ; koniec funkcji get_name

(start_dialog) ; rozpoczyna pobieranie informacji od

; użytkownika z okna dialogowego

; zainicjowanego przez wywołanie funkcji

; new_dialog

(unload_dialog dcl_id) ; usuwa z pamięci wskazany plik DCL.

(princ) ; czyszczenie linii poleceń

);defun ; koniec defun show_dialog_14_1

Omówiliśmy funkcję show_dialog_14_1. Analogicznie oprogramowane zostały funkcje show_dialog_14_2

, oraz show_dialog_14_3.

Łatwiej będzie Państwu uchwycić różnice, gdy zobrazujemy je grafiką (w tym celu przyjrzyjmy się rysunkom znajdującym się na końcu lekcji).

(defun show_dialog_14_2 ()

(setq dcl_id (load_dialog "lisp_14"))

(if(not(new_dialog "dialog14_2" dcl_id))(exit))

(set_tile "imie" napis)

(action_tile "accept" "(setq licznik 0)(get_name)")

(action_tile "cancel" "(setq licznik 0)(done_dialog 0)")

(action_tile "zw" "(czytaj_napis)(setq licznik 3)

(done_dialog 1)")

(action_tile "zm" "(czytaj_napis)(setq licznik 1)

(done_dialog 1)")

(defun get_name ()

(setq a (get_tile "imie"))

(if(= a " ")(set_tile "error" "Błąd : Musisz wpisać imię!")

(done_dialog 1))

);defun

(start_dialog)

(unload_dialog dcl_id)

(princ)

); koniec defun show_dialog_14_2

(defun show_dialog_14_3 ()

(setq dcl_id (load_dialog "lisp_14"))

(if(not(new_dialog "dialog14_3" dcl_id))(exit))

(set_tile "imie" napis)

(action_tile "accept" "(setq licznik 0)(get_name)")

(action_tile "cancel" "(setq licznik 0)(done_dialog 0)")

(action_tile "zw" "(error_zw)")

(action_tile "zm" "(czytaj_napis)(setq licznik 2)

(done_dialog 1)")

(defun get_name ()

(setq a (get_tile "imie"))

(if(= a " ")(set_tile "error"

"Błąd : Musisz wpisać imię!")(done_dialog 1))

);defun

(start_dialog)

(unload_dialog dcl_id)

(princ)

); koniec defun show_dialog_14_3

(while (> licznik 0) ; wchodzimy w pętlę while i

; przetwarzamy instrukcje znajdujące

; się w tej pętli tak długo, jak długo

; spełniony będzie warunek licznik > 0

(cond ; instrukcja warunkowa

; jeżeli licznik = 1 wywołana zostanie

; funkcja show_dialog_14_1

((= licznik 1)(show_dialog_14_1))

; jeżeli licznik = 2 wywołana zostanie

; funkcja show_dialog_14_2

((= licznik 2)(show_dialog_14_2))

; jeżeli licznik = 3 wywołana zostanie

; funkcja show_dialog_14_3

((= licznik 3)(show_dialog_14_3))

);cond ; koniec instrukcji warunkowej

);while ; wyjście z pętli while (licznik = 0)

);defun ; koniec definicji funkcji show_dialog

(show_dialog) ; uruchamiamy funkcję show_dialog

);defun ; koniec definicji funkcji lisp_14

0x01 graphic

0x01 graphic

0x01 graphic

Lekcja 15 -- Formularz zamówienia na książki

0x01 graphic

Tematem bieżącej lekcji jest stworzenie programu do składania zamówień na książki wydawnictwa Helion.

Z uwagi na to, że podczas pisania tego przykładu korzystałem z tych wszystkich elementów, z którymi spotkaliśmy się już wcześniej podczas tego kursu, postanowiłem raczej pokazać, w jaki sposób podejść do tego typu zagadnienia niż omawiać cały listing po kolei.

Zakładamy, że posługiwać się będziemy dwoma oknami dialogowymi. W jednym z nich umieścimy listę książek wraz z ich opisami oraz ceną. Umieścimy w tym oknie również dwa przyciski. Pierwszy z nich posłuży nam do dodawania pozycji do koszyka. Drugi przycisk będzie powodował przejście do drugiego okna, tak aby użytkownik miał możliwość zajrzenia do swojego "koszyka".

0x01 graphic

Rys. 1. Widok okna z "ofertą"

Wciśnięcie przycisku Dodaj do koszyka powoduje stworzenie dwóch list, jeżeli jest to pierwszy element w koszyku. Przy każdym następnym wciśnięciu przycisku obie te listy będą uzupełniane o kolejne elementy.

Z chwilą, gdy użytkownik wciśnie przycisk Zobacz koszyk, okno zostanie "ukryte". Następnie zostanie wyświetlone kolejne okno dialogowe -- "zawartość" koszyka. W pliku dcl umieszczone zostały trzy definicje okien. To, które z nich zostanie wyświetlone, zależy od tego, ile elementów znajduje się w danej chwili na liście. Innymi słowy, sprawdzamy długość listy, po czym wyświetlamy odpowiednie okno.

0x01 graphic

Rys. 2. Widok okna, które zostanie wyświetlone, jeżeli liczba książek w "koszyku" będzie równa 1

0x01 graphic

Rys. 3. Widok okna, które zostanie wyświetlone, jeżeli liczba książek w "koszyku" będzie równa 2

0x01 graphic

Rys. 4. Widok okna, które zostanie wyświetlone, jeżeli liczba książek w "koszyku" będzie równa 3

Chciałbym teraz zaproponować Państwu mały test składający się z kilku prostych pytań.

  1. Jak w okienku edycyjnym wyświetlić łączną sumę książek?

  2. Co należy zrobić, żeby po dodaniu czwartej książki program nie zwrócił błędu? (A niestety, tak robi, ponieważ nie mamy definicji kolejnego okna)

Ostatnie pytanie wymaga kilku słów wprowadzenia. Cały kurs, który napisałem, był pisany od "zera", tak aby wraz z kolejnymi lekcjami wzrastał ich stopień trudności. Rozwiązań, które tu umieściłem, nie spotkacie Państwo w żadnym programie na rynku. Co więcej, część z przykładów powstała tylko i wyłącznie na użytek tego kursu, ponieważ trudno sobie wyobrazić, aby mógł "zafunkcjonować" program do zamawiania książek napisany w AutoLispie, co zmuszałoby użytkownika do uruchamiania AutoCAD-a w celu zamówienia książki.

Ostatnie pytanie więc brzmi: gdzie jeszcze można wykorzystać takie "pseudo-" dynamiczne zwiększanie okna programu?

Przejdźmy teraz do omówienia poszczególnych linii programu.

(defun c:lisp_15 () ; definiujemy nazwę nowego programu

(setq licznik 10) ; ustawiamy licznik

(defun show_dialog () ; definiujemy nazwę programu, który

; posłuży nam do wyświetlenia okna dialogowego

Definiujemy funkcję, wyświetlającą okno dialogowe widoczne na rysunku 2.

;;/////////// dialog 15_1 //////////////////

(defun show_dialog_15_1 ()

(setq dcl_id (load_dialog "lisp_15"))

(if (not (new_dialog "dialog15_1" dcl_id))

(exit)

)

(action_tile "accept" "(setq licznik 0)

(done_dialog 1)")

(action_tile "cancel" "(setq licznik 0)(done_dialog 0)")

(action_tile "katalog" "(setq licznik 10)(done_dialog 0)")

(set_tile "tyt_1" tytuł1)

(set_tile "cena_1" cena1)

(start_dialog)

(unload_dialog dcl_id)

) ;defun c:lisp_15

;;/////////// dialog 15_1 //////////////////

Definiujemy funkcję wyświetlającą okno dialogowe widoczne na rysunku 3.

;;/////////// dialog 15_2 //////////////////

(defun show_dialog_15_2 ()

(setq dcl_id (load_dialog "lisp_15"))

(if (not (new_dialog "dialog15_2" dcl_id))

(exit)

)

(action_tile "accept" "(setq licznik 0)

(done_dialog 1)")

(action_tile "cancel" "(setq licznik 0)(done_dialog 0)")

(action_tile "katalog" "(setq licznik 10)(done_dialog 0)")

(set_tile "tyt_1" tytuł1)

(set_tile "cena_1" cena1)

(set_tile "tyt_2" tytuł2)

(set_tile "cena_2" cena2)

(start_dialog)

(unload_dialog dcl_id)

) ; koniec defun show_dialog_15_2

;;/////////// dialog 15_2 //////////////////

Definiujemy funkcję wyświetlającą okno dialogowe widoczne na rysunku 4.

;;/////////// dialog 15_3 //////////////////

(defun show_dialog_15_3 ()

(setq dcl_id (load_dialog "lisp_15"))

(if (not (new_dialog "dialog15_3" dcl_id))

(exit)

)

(action_tile "accept" "(setq licznik 0)

(done_dialog 1)")

(action_tile "cancel" "(setq licznik 0)(done_dialog 0)")

(action_tile "katalog" "(setq licznik 10)(done_dialog 0)")

(set_tile "tyt_1" tytuł1)

(set_tile "cena_1" cena1)

(set_tile "tyt_2" tytuł2)

(set_tile "cena_2" cena2)

(set_tile "tyt_3" tytuł3)

(set_tile "cena_3" cena3)

(start_dialog)

(unload_dialog dcl_id)

) ; koniec defun show_dialog_15_3

;;/////////// dialog 15_3 //////////////////

Definiujemy funkcję wyświetlającą okno dialogowe widoczne na rysunku 1.

;;/////////// dialog katalog //////////////////

(defun show_dialog_katalog ()

(setq dcl_id (load_dialog "lisp_15"))

(if (not (new_dialog "katalog" dcl_id))

(exit)

)

(action_tile "accept" "(setq licznik 0)

(done_dialog 1)")

(action_tile "cancel" "(setq licznik 0)(done_dialog 0)")

(action_tile "book_list" "(tytuł_książki )")

(action_tile "bt_2" "(dodaj_do_koszyka)")

(action_tile "bt_3" "(zobacz_koszyk)(setq licznik licz)

(done_dialog 1)")

;;/////////// lista książek //////////////////

(setq lista_książek

(list "AutoCAD 2000 PL"

"AutoCAD 14 i 14 PL"

"AutoCAD 2000 - bibl. symb."

"AutoCAD 2000 3D f/x"

)

)

;;/////////// koniec listy książek //////////////////

Tworzymy opisy książek.

;;/////////// opisy książek //////////////////

Przypisujemy zmiennej op_1 wartość w postaci listy -- opisu pierwszej książki z katalogu.

(setq op_1 (list

"wycinek (edit_box)"

"(okno edycyjne)"

"umożliwia wprowa-"

"dzenie lub edycję"

" pojedynczej linii"

" tekstu "

)

)

Przypisujemy zmiennej op_2 wartość w postaci listy -- opisu drugiej książki z katalogu.

(setq op_2 (list

"xxxxxxxxxxx"

"rtyrtwr6uit"

"tryutyrt"

)

)

Przypisujemy zmiennej op_3 wartość w postaci listy -- opisu trzeciej książki z katalogu.

(setq op_3 (list

"zzzzzzzzzz"

"rtyrtwr6uit"

"tryutyrt"

)

)

Przypisujemy zmiennej op_4 wartość w postaci listy -- opisu czwartej książki z katalogu.

(setq op_4 (list

"fgfgfgfg"

"rtyrtwr6uit"

"tryutyrt"

)

)

;;/////////// koniec opisów książek //////////////////

Rozpoczynamy przetwarzanie listy book_list. Umieszczamy w oknie dialogowym listę książek z katalogu.

(start_list "book_list")

(mapcar 'add_list lista_książek)

(end_list)

Pobieramy tytuł książki, jaki został wybrany przez użytkownika w oknie dialogowym.

(defun tytuł_książki (item)

(setq ln (nth (atoi item) lista_książek))

(set_tile "b_name" ln)

Sprawdzamy, jaki tytuł został wybrany i w zależności od tego przypisujemy zmiennym cena i opis odpowiednie wartości.

(cond

((= ln "AutoCAD 2000 PL")

(setq cena "120"

opis op_1)

)

((= ln "AutoCAD 14 i 14 PL")

(setq cena "110"

opis op_2)

)

((= ln "AutoCAD 2000 - bibl. symb.")

(setq cena "100"

opis op_3)

)

((= ln "AutoCAD 2000 3D f/x")

(setq cena "90"

opis op_4)

)

) ; cond

Rozpoczynamy przetwarzanie w oknie dialogowym listy z opisem książek.

(start_list "opis")

(mapcar 'add_list opis)

(end_list)

Wyświetlamy cenę w oknie dialogowym.

(set_tile "cena_kat" cena)

) ;defun !!!

Definiujemy nową funkcję, dzięki której będziemy mogli dodawać kolejne pozycje do koszyka.

(defun dodaj_do_koszyka()

Przypisujemy wartości zmiennym tytuł i cena.

(setq tytuł (list(get_tile "b_name")))

(setq cena (list(get_tile "cena_kat")))

Sprawdzamy warunek logiczny. Jeżeli długość listy (lista tytułów) jest równa 0, to tworzymy nową listę i przypisujemy jej wartość zmiennej ltytuł. Jeżeli długość listy (lista tytułów) jest większa od 0, to dodajemy do niej kolejny element, wykorzystując w tym celu funkcję append. Analogicznie postępujemy w przypadku ceny.

(if (= (length tytuł) 0) (setq ltytuł tytuł)

(setq ltytuł (append ltytuł tytuł)))

(if (= (length cena) 0) (setq lcena cena)

(setq lcena (append lcena cena)))

)

Definiujemy zmienną, dzięki której będziemy w stanie zobaczyć, jakie elementy znajdują się w koszyku.

(defun zobacz_koszyk()

Sprawdzamy długość listy tytułów i przypisujemy ją zmiennej licz.

(setq licz (length ltytuł))

Definujemy wielkość poszczególnych koszyków.

(defun koszyk1 ()

(setq cena1 (nth 0 lcena))

(setq tytuł1 (nth 0 ltytuł))

);end_koszyk_1

(defun koszyk2 ()

(setq cena1 (nth 0 lcena))

(setq tytuł1 (nth 0 ltytuł))

(setq cena2 (nth 1 lcena))

(setq tytuł2 (nth 1 ltytuł))

);end_koszyk_2

(defun koszyk3 ()

(setq cena1 (nth 0 lcena))

(setq tytuł1 (nth 0 ltytuł))

(setq cena2 (nth 1 lcena))

(setq tytuł2 (nth 1 ltytuł))

(setq cena3 (nth 2 lcena))

(setq tytuł3 (nth 2 ltytuł))

);end_koszyk_3

Sprawdzamy warunek logiczny cond. W zależności od wartości zmiennej licz uruchamiana jest odpowiednia funkcja wyświetlająca koszyk.

(cond

((= licz 1)(koszyk1))

((= licz 2)(koszyk2))

((= licz 3)(koszyk3))

);cond

);defun zobacz_koszyk()

Uruchomienie głównego okna dialogowego:

(start_dialog)

Usunięcie definicji okna dialogowego z pamięci:

(unload_dialog dcl_id)

) ;koniec defun show_dialog_katalog

;;/////////// dialog katalog //////////////////

Na koniec umieszczamy pętlę while, która w zależności od wartości zmiennej licznik wyświetla nam odpowiednie okno dialogowe.

(while (> licznik 0)

(cond

((= licznik 1) (show_dialog_15_1))

((= licznik 2) (show_dialog_15_2))

((= licznik 3) (show_dialog_15_3))

((= licznik 10) (show_dialog_katalog))

) ;cond

) ;while

) ; koniec defun show_dialog

(show_dialog)

)



Wyszukiwarka

Podobne podstrony:
kolędy dla zaawansowanych
Trening sprawnościowy dla zaawansowanych, Trening, Plany tygodniowe
kurs AutoCAD dla zaawansowanych
ZASADY TRENINGU DLA ZAAWANSOWANYCH
Cabri Dla Zaawansowanych
AutoCAD kurs dla zaawansowanych
Apache 2 0 dla zaawansowanych
Okna dialogowe
Rzecznicy prasowi, Media dla zaawansowanych, Prawo Prasowe
auto cad 2005 nauka VWUQLMDEZTB Nieznany (2)
Cisco systemy operacyjne dla zaawansowanych
Procedura na gwiazdę Dawida, LOGO KOMENIUSZ dla zaawansowanych
Prawo prasowe, Media dla zaawansowanych, Prawo Prasowe
Apache 2 0 dla zaawansowanych
Akwarystyka dla zaawansowanych Wszystko, co musisz wiedzieć, żeby zostać ekspertem (Tetra)

więcej podobnych podstron