Při tvorbě uživatelského rozhraní využívejte maximálně obrázku výsledného dialogového okna. Všímejte si hlavně hierarchického uspořádání jednotlivých prvků. Uspořádání vám pomůže při vlastní tvorbě dialogu.
Aplikaci je výhodné rozdělit na několik funkcí. Každá funkce bude plnit ucelenou činnost. Jednotlivé funkce budou plnit následující úlohu:
Další doporučení:
Pro uživatele, kteří zabloudili při tvorbě kódu uvádíme jednotlivé ucelené části kódu. Pokud si nebudete jisti funkcí některého příkazu, stačí kliknout nad příkazem a zobrazí se Vám referenční příručka se zobrazeným příkazem.
Při tvorbě dialogového okna si pozorně prostudujte obrázek výsledného dialogu!
dialogBox:dialog { // jméno dialogového boxu label = "Dialog - parametry kvádru"; // popis dialogového prvku :boxed_column { // organizováno do sloupců label = "Nastavení parametrů prvku"; // popis orámované oblasti :boxed_column { // organizace do sloupců label = "Nastavení středu"; // popis :edit_box { // prvek edit_box label = "Souřadnice x: "; // popisek key = "stredx"; // klíč edit_width = 10; // šířka prvku } :edit_box { // prvek edit_box label = "Souřadnice y: "; // popisek key = "stredy"; // klíč edit_width = 10; // šířka prvku } :edit_box { // prvek edit_box label = "Souřadnice z: "; // popisek key = "stredz"; // klíč edit_width = 10; // šířka prvku } :button { // prvek tlačítko label = "Ruční nastavení"; // popisek key = "stred_but"; // klíč fixed_width = true; // použít fixní velikost width = 10; // šířka prvku alignment = centered; // centrovat na střed } } :edit_box { // prvek edit_box label = "Délka kvádru: "; // popisek key = "delka"; // klíč edit_width = 10; // šířka prvku } :edit_box { label = "Šířka kvádru: "; // popisek key = "sirka"; // klíč edit_width = 10; // šířka prvku } :edit_box { label = "Výška kvádru: "; // popisek key = "vyska"; // klíč edit_width = 10; // šířka prvku } } ok_cancel; // tlačítka OK a Cancel }
Funkce výsledné aplikace uvádíme v pořadí, v jakém je nutné uvést funkce v souboru. V jiném pořadí uložení funkcí by mohlo dojít k výskytu chyb.
Na začátku souboru musíme aktivovat podporu funkcí ActiveX a reaktorů:
(vl-load-com) ;;; nahrání podpory reaktorů
První funkcí uvedenou v souboru je obslužná funkce reaktoru. Reaktor bude typu
object reaktor. Hlavička funkce musí obsahovat:
V těle funkce musíme pro jistotu otestovat
(pomocí funkce vlax-property-available-p)
zda objekt předaný reaktorem (volajObj) obsahuje vlastnost, kterou potřebujeme
využívat. Pokud objekt vlastnost obsahuje určíme objem nového a původního objektu.
Původní objem máme uložený v paměti reaktoru reactorObj. Nakonec funkce
vypočítá kolikrát je nový objekt menší nebo větší než objekt původní. Výsledek
zobrazí pomocí jednoduchého dialogového prvku.
(defun rb:infoBox(volajObj reactorObj paramList / objemNovy objemStary) ;;; obslužná funkce reaktoru, reagující na změnu rozměrů ;;; kvádru (if (vlax-property-available-p volajObj "Volume") ;;; kontrola, zda objekt, který způsobil vyvolání ;;; obslužné fce. obsahuje vlastnost obsah (progn (setq objemNovy (vla-get-volume volajObj)) ;;; zjistí se nový obsah (setq objemStary (vlr-data reactorObj)) ;;; zjistí se starý obsah (if (> objemNovy objemStary) ;;; určí se zda jde o zvětšení/zmenšení (alert ;;; zobrazí se zpráva (strcat "Objem krychle se zvětšil " (rtos (/ objemNovy objemStary)) " krát." ) ) (alert (strcat "Objem krychle se zmenšil " (rtos (/ objemStary objemNovy)) " krát." ) ) ) (vlr-data-set reactorObj objemNovy) ;;; nakonec se aktualizuje hodnota v datech reaktoru ;;; pro další použití ) ) )
Hlavní funkce musí být deklarovaná s prefixem c: (c:reaktorBox). Prefix zajistí možnost spuštění funkce v prostředí AutoCADu jako příkazu (nemusí se uvádět závorky). Ve funkci c:reactorBox() deklarujeme globální proměnnou gl_pam_hodnoty typu asociační seznam. Do globální proměnné uložíme inicializační hodnoty dialogových prvků. Dále otestujeme jestli byly hodnoty v dialogovém boxu zadány korektně. Jestli ano (funkce rb:dialog vrací true) zavolá se funkce rb:kresli_box. Jakmile funkce dokončí činnost, zobrazí informaci o aktivaci reaktoru.
(defun c:reaktorBox () ;;; definice nové funkce spustitelné jako příkaz AutoCADu ;;; funkce vykreslí kvádr a přidruží k němu reaktor ;;; odchytávající změnu velikosti kvádru (setq gl_pam_hodnoty ;;; globální proměnná uchovávající ;;; jednotlivá nastavení, proměnná ;;; je typu asociační seznam (list (cons "stredx" "0.0") ;;; x-ova souřadnice středu kvádru (cons "stredy" "0.0") ;;; y-ova souřadnice středu kvádru (cons "stredz" "0.0") ;;; z-ova souřadnice středu kvádru (cons "delka" "1") ;;; délka kvádru (cons "sirka" "1") ;;; sirka kvádru (cons "vyska" "1") ;;; vyska kvádru ) ) (if (= (rb:dialog) T) ;;; je-li dialogový box řádně ukončen, (rb:kresli_box) ;;; zavolej funkci pro vykreslení ;;; požadovaného objektu ) (princ "Funkce dokončila činnost, reaktor je aktivní.") (princ) ;;; výpis informací o ukončení funkce )
Funkce rb:dialog nejprve načte dialog ze souboru dialogBox.dcl. Ukazatel na dialog si uloží do proměnné id. Dále je funkcí nastavena proměnná co_delat na hodnotu 2 (znamená setrvej ve smyčce). Program vstoupí do smyčky while, otestuje zda načtený soubor obsahuje dialog se jménem "dialogBox". Pokud ne program skončí. Dále jsou v programu nastaveny pomocí funkce set_tile všechny prvky dialogového panelu. Získání hodnot z dialogových prvků zajišťují funkce action_tile vyvolané při akci na dialogovém prvku. Při stisku tlačítka je zavolán příkaz done_dialog s parametrem určujícím další činnost. Příkaz star_dialog je zastaven a do proměnné co_dělat vrátí hodnotu, s kterou byl vyvolán příkaz done_dialog. Podle hodnoty uložené v proměnné co_dělat se určí další činnost.
Dále je testována podmínka cond . Spustí se přiřazená funkce . Po jejím skončení se běh programu vrátí na začátek smyčky, je zkontrolována správnost načteného dialogu a dialog je opět zobrazen příkazem start_dialog. Tato činnost se opakuje do té doby než je vyvolána funkce done_dialog s parametrem < 2. Dialog je odstraněn z paměti a je vrácena návratová hodnota.
(defun rb:dialog (/ id co_delat vysledek) ;;; funkce pro obsluhu dialogového boxu (setq id (load_dialog "D:/dialogBox.dcl")) ;;; předání jména dialogového boxu ;;; CESTU K UMÍSTĚNÍ DIALOGU JE NUTNO AKTUALIZOVAT PODLE ;;; AKTUALNÍHO UMÍSTĚNÍ (setq co_delat 2) (while (>= co_delat 2) ;;; opakuj pokud nenastane zmena (if (not (new_dialog "dialogBox" id)) (exit) ;;; není-li jméno dialogu vyber tak skonči ) ;;; nastavení hodnot dialogových prvků (set_tile "delka" (cdr (assoc "delka" gl_pam_hodnoty))) (set_tile "sirka" (cdr (assoc "sirka" gl_pam_hodnoty))) (set_tile "vyska" (cdr (assoc "vyska" gl_pam_hodnoty))) (set_tile "stredx" (cdr (assoc "stredx" gl_pam_hodnoty))) (set_tile "stredy" (cdr (assoc "stredy" gl_pam_hodnoty))) (set_tile "stredz" (cdr (assoc "stredz" gl_pam_hodnoty))) ;;; získání hodnot z dialogových prvků a ;;; jejich uložení do globální proměnné gl_pam_hodnoty (action_tile "stredx" "(setq gl_pam_hodnoty (subst (cons \"stredx\" $value) (assoc \"stredx\" gl_pam_hodnoty) gl_pam_hodnoty ) )" ) (action_tile "stredy" "(setq gl_pam_hodnoty (subst (cons \"stredy\" $value) (assoc \"stredy\" gl_pam_hodnoty) gl_pam_hodnoty ) )" ) (action_tile "stredz" "(setq gl_pam_hodnoty (subst (cons \"stredz\" $value) (assoc \"stredz\" gl_pam_hodnoty) gl_pam_hodnoty ) )" ) (action_tile "delka" "(setq gl_pam_hodnoty (subst (cons \"delka\" $value) (assoc \"delka\" gl_pam_hodnoty) gl_pam_hodnoty ) )" ) (action_tile "sirka" "(setq gl_pam_hodnoty (subst (cons \"sirka\" $value) (assoc \"sirka\" gl_pam_hodnoty) gl_pam_hodnoty ) )" ) (action_tile "vyska" "(setq gl_pam_hodnoty (subst (cons \"vyska\" $value) (assoc \"vyska\" gl_pam_hodnoty) gl_pam_hodnoty ) )" ) (action_tile "stred_but" "(done_dialog 4)") ;;; je-li zmáčknuto tlačítko "stred_but" zavolej ;;; funkci done_dialog s hodnotou 4 (action_tile "accept" "(done_dialog 1)") ;;; je-li zmáčknuto tlačítko "accept" ;;; zavolej funkci done_dialog s hodnotou 1 (action_tile "cancel" "(done_dialog 0)") ;;; je-li zmáčknuto tlačítko "cancel" ;;; zavolej funkci done_dialog s hodnotou 0 (setq co_delat (start_dialog)) ;;; nastaví proměnnou na hodnotu získanou ;;; od funkce start_dialog (hodnota s kterou ;;; končí funkce done_dialog) (cond ;;; určení další činnosti ((= co_delat 0) (setq vysledek nil)) ;;; uživatel stornoval dialog, ;;; ukonči funkci s hodnotou nil ((= co_delat 1) (setq vysledek T)) ;;; uživatel potvrdil dialog, ;;; ukonči funki s hodnotou T ((= co_delat 4) (rb:nastav_stred (getpoint "\nVýběr bodu:") ) ) ;;; uživatel zmáčkl tlačítko pro zadání ;;; souřadnic středu zavolej funkci ;;; rb:nastav_stred ) ) (unload_dialog id) ;;; odstraň dialog id z paměti vysledek ;;; návratová hodnota funkce (T = uživatel zadal ;;; hodnoty a potvrdil dialog, jinak se vrací nil) )
Funkce rb:nastav_stred zajistí nastavení hodnot souřadnic středu tělesa po zadání středu pomocí tlačítka Ruční nastavení. Nejprve jsou získány hodnoty jednotlivých souřadnic z proměnné stred. Každá souřadnice je převedena na řetězec a uložena do globální proměnné gl_pam_hodnoty.
(defun rb:nastav_stred (stred / stredx stredy stredz) ;;; funkce nastavující hodnoty jednotlivých ;;; souřadnic při stisku tlačítka pro zadání ;;; středu do globální proměnné gl_pam_hodnoty (setq stredx (strcat (vl-princ-to-string (car stred)))) (setq stredy (strcat (vl-princ-to-string (cadr stred)))) (setq stredz (strcat (vl-princ-to-string (caddr stred)))) (setq gl_pam_hodnoty (subst (cons "stredx" stredx) (assoc "stredx" gl_pam_hodnoty) gl_pam_hodnoty ) ) (setq gl_pam_hodnoty (subst (cons "stredy" stredy) (assoc "stredy" gl_pam_hodnoty) gl_pam_hodnoty ) ) (setq gl_pam_hodnoty (subst (cons "stredz" stredz) (assoc "stredz" gl_pam_hodnoty) gl_pam_hodnoty ) ) )
Funkce rb:kresli_box
zajišťuje vykreslení kvádru a vytvoření objektu reaktoru, který reaguje na změny
velikosti kvádru. Ve funkci nejdříve zjistíme pointr
na objekt application AutoCAD. Abychom mohli přidávat do modelového prostoru
výkresu objekty, musíme nejprve zjistit pointer na aktivní
dokument a poté pointer do modelového prostoru. Před vytvořením objektu
kvádr musíme zjistit všechny potřebné parametry (stred, delka, sirka a vyska).
Všechny parametry
zjistíme z globální proměnné gl_pam_hodnoty. Vytvoříme nový objekt kvádru
a pointer na vytvořený
objekt přiřadíme do proměnné objBox. Pomocí pointru na nový objekt
zjistíme objem nového
kvádru. Vykreslený objekt (kvádr) zvětšíme,
aby byl dobře viditelný. Nakonec funkce vytvoříme objekt
reaktoru.
(defun rb:kresli_box (/ stred delka vyska sirka objBox objemPuvodni) ;;; funkce vytvářející kvádr a objekt reaktoru (setq acadObjekt (vlax-get-acad-object)) ;;; nastavení pointru na objekt application AutoCAD (setq acadDokument (vla-get-ActiveDocument acadObjekt)) ;;; nastavení pointru na aktivní dokument (setq modelProstor (vla-get-ModelSpace acadDokument)) ;;; nastavení pointru na modelový prostor dokumentu (setq stred (list (atof (cdr (assoc "stredx" gl_pam_hodnoty))) (atof (cdr (assoc "stredy" gl_pam_hodnoty))) (atof (cdr (assoc "stredz" gl_pam_hodnoty))) ) ) ;;; převod tří řetězců reprezentujících souřadnice ;;; do proměnné stred (položky stred jsou typu float) (setq delka (atof (cdr (assoc "delka" gl_pam_hodnoty)))) ;;; získání délky krychle z asoc. seznamu gl_pam_hodnoty (setq sirka (atof (cdr (assoc "sirka" gl_pam_hodnoty)))) ;;; získání šířky krychle z asoc. seznamu gl_pam_hodnoty (setq vyska (atof (cdr (assoc "vyska" gl_pam_hodnoty)))) ;;; získání výšky krychle z asoc. seznamu gl_pam_hodnoty (command) ;;; ukončení všech předchozích příkazů (setq objBox (vla-addBox modelProstor (vlax-3d-point stred) delka sirka vyska ) ) ;;; vykreslení kvádru v modelovém prostoru (setq objemPuvodni (vla-get-volume objBox)) ;;; získání objemu kvádru, objem je následně ;;; uložen do reaktoru jako doplňková data (command "_zoom" "M") ;;; zvětšení výkresu (setq boxReaktor (vlr-object-reactor (list objBox) objemPuvodni '((:vlr-modified . rb:infoBox))) ) ;;; vytvoření objektu reaktoru, reagujícího ;;; na modifikaci kvádru )
Na konci souboru, který je nahrán jako poslední, je výhodné uvést informaci,
jak spustit aplikaci v AutoCADu. Informace se zobrazí po nahrání funkce v příkazovém
řádku.
;;; nakonec zobrazíme informaci pro uživatele (princ "\nNezapomeňte nastavit správnou cestu k dialogu ve funkci rb:dialog!!!" ) (princ "\nFunkce se spustí příkazem (c:reaktorBox) v IDE Visual LISPu" ) (princ "\nFunkce se spustí příkazem reaktorBox v AutoCADu" )