DelphiScript
Ta sekcja opisuje język DelphiScript używany przez Altium Designer Scripting Engine i zawiera szczegółowe informacje referencyjne dotyczące obsługiwanych instrukcji, funkcji oraz rozszerzeń. Są to specjalne procedury służące do sterowania i bezpośredniej komunikacji z Altium Designer.
Również w tym opracowaniu:
- Różnice między DelphiScript a Delphi
- Słowa kluczowe DelphiScript
- Instrukcje i operatory DelphiScript
- Funkcje DelphiScript
- Formularze i komponenty DelphiScript
Język DelphiScript
Niniejsze opracowanie DelphiScript zakłada, że znasz podstawowe koncepcje programowania, a także podstawową obsługę Altium Designer. System skryptów obsługuje język DelphiScript, który jest bardzo podobny do Embarcadero Delphi™.
Kluczowa różnica polega na tym, że DelphiScript jest językiem skryptowym bez typów (typeless/untyped), co oznacza, że nie można definiować rekordów ani klas oraz przekazywać wskaźników jako parametrów do funkcji. Zmienne nadal mogą być deklarowane w skryptach dla poprawy czytelności.
Ta strona oraz powiązane podstrony zawierają materiały referencyjne dotyczące interfejsów, komponentów, procedur globalnych, typów i zmiennych, które składają się na język skryptowy DelphiScript.
Kluczowe elementy DelphiScript
Obiekty
W DelphiScript obiekt składa się z metod, a w wielu przypadkach także z właściwości i zdarzeń. Właściwości reprezentują dane zawarte w obiekcie, metody są działaniami, które obiekt może wykonywać, a zdarzenia są warunkami, na które obiekt może reagować. Wszystkie obiekty pochodzą (i dziedziczą) z obiektu najwyższego poziomu typu TObject.
Interfejsy obiektów
Interfejs obiektu składa się z metod, a w wielu przypadkach także z właściwości, ale nie może zawierać pól danych. Interfejs reprezentuje istniejący obiekt, a każdy interfejs ma GUID, który czyni go unikatowym. Właściwości reprezentują dane zawarte w obiekcie, z którym powiązany jest interfejs. Metody są działaniami, które obiekt (z którym powiązany jest interfejs) może wykonywać.
Komponenty
Komponenty to obiekty wizualne z panelu Tool Palette, którymi można manipulować na etapie projektowania. Wszystkie komponenty pochodzą z klasy systemowej TComponent w bibliotece Embarcadero Delphi Visual Component Library (VCL).
Procedury (routines)
Procedury globalne to procedury i funkcje z systemu skryptów. Te procedury nie są częścią klasy, ale mogą być wywoływane bezpośrednio albo z poziomu metod klas w skrypcie.
Typy
Typy zmiennych są używane jako typy zwracane oraz typy parametrów dla metod i właściwości interfejsów, metod obiektów, właściwości i zdarzeń, a także dla procedur globalnych. W wielu przypadkach typy są opisane w sekcjach typów wyliczeniowych w dokumentacji API.
Altium Designer i Delphi RTL
System skryptów obsługuje podzbiór biblioteki Embarcadero Delphi Run Time Library (RTL) oraz API Altium Designer.
Pliki źródłowe DelphiScript
W Altium Designer projekt skryptów jest zorganizowany tak, aby przechowywać dokumenty skryptów (jednostki skryptów – Units oraz formularze skryptów – Forms). Skrypt można uruchomić z pozycji menu, przycisku paska narzędzi lub z okna Select Item To Run dialog, dostępnego z menu głównego Altium Designer.
Pliki PRJSCR, PAS i DFM
Skrypty są organizowane w projekty z rozszerzeniem *.PRJSCR. Każdy projekt składa się z plików z rozszerzeniem *.pas. Pliki mogą być jednostkami skryptów (script Units) lub formularzami skryptów (script Forms) — pamiętaj, że każdy formularz ma plik skryptu z rozszerzeniem *.pas oraz odpowiadający mu plik formularza z rozszerzeniem *.dfm. Formularz skryptu to graficzne okno (dialog), które działa „na wierzchu” Altium Designer i zawiera różne kontrolki dostępne dla użytkownika.
Możliwe jest dołączanie skryptów do różnych projektów i zdecydowanie zaleca się organizowanie skryptów w oddzielne projekty, aby zarządzać liczbą skryptów oraz ich procedurami/funkcjami.
Przykładowe skrypty
Zbiór przykładowych skryptów ilustruje podstawowe możliwości programowania w DelphiScript, wykorzystując proste skrypty do użycia w Altium Designer.
Poniżej wymieniono lokalizację i przeznaczenie wybranych przykładowych skryptów:
Scripts\DelphiScript Scripts\DXPfolder - Demonstruje API Client i systemoweScripts\DelphiScript Scripts\PCB folder - Demonstruje PCB APIScripts\DelphiScript Scripts\Processesfolder - Demonstruje procesy serweraScripts\DelphiScript Scripts\Generalfolder - Demonstruje słowa kluczowe DelphiScriptScripts\DelphiScript Scripts\Schfolder - Demonstruje Schematic APIScripts\DelphiScript Scripts\WSMfolder - Demonstruje Workspace Manager API
Pisanie skryptów DelphiScript
Konwencje nazewnictwa DelphiScript
Ogólnie nie ma ograniczeń co do nazw nadawanych procedurom, funkcjom, zmiennym i stałym, o ile spełniają one następujące zasady:
- Nazwa może zawierać litery A–Z, a–z, znak podkreślenia „_” oraz cyfry 0–9.
- Nazwa musi zaczynać się od litery.
- Nazwa nie może być słowem kluczowym DelphiScript, dyrektywą ani słowem zastrzeżonym.
- Nazwy nie rozróżniają wielkości liter podczas interpretacji. Przy nadawaniu nazw funkcjom, podprogramom, zmiennym lub stałym można używać zarówno wielkich, jak i małych liter, jednak interpreter nie odróżnia wielkich i małych znaków. Nazwy identyczne poza wielkością liter będą traktowane w DelphiScript jako ta sama nazwa.
W pliku DelphiScript funkcje i procedury deklaruje się za pomocą bloków Procedure-Begin-End lub Function-Begin-End. Oba te bloki instrukcji wymagają nadania nazwy procedurze lub funkcji. DelphiScript pozwala tworzyć nazwane zmienne i stałe do przechowywania wartości używanych w bieżącym skrypcie.
Dodawanie komentarzy
W skrypcie komentarze to niewykonywalne linie kodu, dodawane z myślą o programiście. Komentarze można umieszczać praktycznie w dowolnym miejscu skryptu.
Każdy tekst po // lub ujęty w (* *) albo {} jest ignorowany przez DelphiScript.
//This whole line is a comment
{This whole line is a comment}
{
These lines are comments
These lines are comments
}
(* This whole line is a comment *)
(*
These lines are comments
These lines are comments
*)
Komentarze można również umieszczać w tej samej linii co wykonywany kod. Na przykład wszystko po średniku w poniższej linii kodu jest traktowane jako komentarz.
ShowMessage ('Hello World'); //Display Message
Zmienne lokalne i globalne
Ponieważ wszystkie skrypty mają zmienne lokalne i globalne, bardzo ważne jest stosowanie unikatowych nazw zmiennych w skryptach w obrębie jednego projektu skryptów. Jeśli zmienne są zdefiniowane outside jakimikolwiek procedurami i funkcjami, są globalne i mogą być dostępne z dowolnej jednostki skryptu w tym samym projekcie.
Jeśli zmienne są zdefiniowane inside procedurą lub funkcją, wówczas te zmienne lokalne nie są dostępne poza tymi procedurami/funkcjami.
Example of Local and Global Variables in a Script:
// Note: The Uses keyword is not needed.
{ The global variable from UnitA script (see below) is available to this Script Unit,
as long UnitA is in the same project as this Script Unit. }
Const
GlobalVariableFromThisUnit='Global Variable from this unit';
Procedure TestLocal;
var
Local;
Begin
Local := 'Local Variable';
ShowMessage(Local);
End;
Procedure TestGlobal;
Begin
//ShowMessage(Local); // This line produces an error because the 'Local' variable is not global.
ShowMessage(GlobalVariableFromThisUnit);
// A variable from UnitA can be accessed without the Uses keyword.
ShowMessage(GlobalVariableFromUnitA);
End;
UnitA script:
Const
GlobalVariableFromUnitA = 'Global Variable from Unit A';
Używanie nazwanych zmiennych
W skrypcie tworzy się nazwane zmienne lub stałe, aby przechowywać wartości używane podczas wykonywania programu. Wszystkie zmienne w skrypcie są zawsze typu Variant. Rzutowanie typów nie ma zastosowania, więc typy w deklaracjach zmiennych są ignorowane i można je pominąć. W związku z tym poniższe deklaracje są poprawne:
Var a : integer;
Var b : integer;
Var c, d;
Dzielenie linii
Każda instrukcja kodu jest zakończona znakiem średnika ;, aby wskazać koniec instrukcji. DelphiScript pozwala zapisać instrukcję w kilku liniach kodu, dzieląc długą instrukcję na dwie lub więcej linii. Jedynym ograniczeniem przy dzieleniu instrukcji na różne linie jest to, że literał łańcuchowy (string) nie może obejmować kilku linii.
For example:
X.AddPoint( 25, 100);
X.AddPoint( 0, 75);
// is equivalent to:
X.AddPoint( 25, 100); X.AddPoint( 0, 75);
however...
'Hello World!'
\\is not equivalent to
'Hello
World!'
DelphiScript nie narzuca praktycznego limitu długości pojedynczej linii kodu w skrypcie, jednak ze względu na czytelność i łatwość debugowania dobrą praktyką jest ograniczanie długości linii kodu tak, aby można je było łatwo odczytać na ekranie lub w wydruku.
Jeśli linia kodu jest bardzo długa, można ją podzielić na wiele linii, a interpreter DelphiScript potraktuje ten kod tak, jakby był zapisany w jednej linii.
Unformatted code example:
If Not (PcbApi_ChooseRectangleByCorners(BoardHandle,'Choose first corner','Choose final corner',x1,y1,x2,y2)) Then Exit;
Formatted code example:
If Not (PcbApi_ChooseRectangleByCorners(BoardHandle,
'Choose first corner',
'Choose final corner',
x1,y1,x2,y2)) Then Exit;
Rozróżnianie wielkości liter
Język DelphiScript używany do pisania skryptów nie rozróżnia wielkości liter — to znaczy, że wszystkie słowa kluczowe, instrukcje, nazwy zmiennych, nazwy funkcji i procedur mogą być zapisywane bez względu na użycie wielkich lub małych liter. Wielkie i małe litery są traktowane równoważnie.
Na przykład nazwa zmiennej myVar jest równoważna myvar oraz MYVAR. DelphiScript traktuje wszystkie te nazwy jako tę samą zmienną.
Jedynym wyjątkiem są literały łańcuchowe, takie jak tekst tytułu w definicji okna dialogowego lub wartość zmiennej typu string. Te łańcuchy zachowują różnice w wielkości liter.
Znak spacji
Spacja służy do rozdzielania słów kluczowych w instrukcji skryptu. Jednak DelphiScript ignoruje dodatkowe białe znaki w instrukcji.
Na przykład:
X = 5
// is equivalent to
X =5
Możesz używać białych znaków, aby zwiększyć czytelność skryptu.
Funkcje i procedury w skrypcie
Interpreter DelphiScript dopuszcza dwa rodzaje metod (procedur): Procedures i Functions. Jedyna różnica między funkcją a procedurą polega na tym, że funkcja zwraca wartość.
Skrypt może mieć co najmniej jedną procedurę, która definiuje główny kod programu. Możesz jednak zdefiniować inne procedury i funkcje, które będą wywoływane przez Twój kod.
Podobnie jak w Embarcadero Delphi, procedury i funkcje definiuje się w bloku instrukcji Begin-End. Aby wywołać funkcję lub procedurę, umieść nazwę funkcji lub procedury w instrukcji w taki sam sposób, jak przy używaniu wbudowanych funkcji i procedur DelphiScript. Jeśli funkcja lub procedura wymaga parametrów, muszą one zostać uwzględnione w instrukcji wywołania. Zarówno funkcje, jak i procedury mogą być zdefiniowane tak, aby przyjmowały parametry, ale tylko funkcje mogą być zdefiniowane tak, aby zwracały wartość do instrukcji wywołującej.
Funkcjom i procedurom można nadać dowolną nazwę podczas ich definiowania, o ile jest ona zgodna ze standardowymi konwencjami nazewnictwa DelphiScript.
Typical DelphiScript Procedure:
Procedure CreateSchObjects;
Begin
If SchServer = Nil Then Exit;
SchDoc := SchServer.GetCurrentSchDocument;
If SchDoc = Nil Then Exit;
PlaceSchematicObjects;
SchDoc.GraphicallyInvalidate;
End;
Typical DelphiScript Function:
Function BooleanToString(AValue : Boolean) : String;
Begin
If (AValue) Then Result := 'True'
Else Result := 'False';
End;
Nazwa funkcji nie może być użyta do ustawienia jej wartości zwracanej. Zamiast tego należy użyć słowa kluczowego Result.
Var, Begin-End global block:
Var
A, B, C;
Begin
B := 10;
C := 20;
A := B + C;
ShowMessage(IntToStr(A));
End;
Wskazówki dotyczące skryptów
Odwoływanie się do skryptów w projekcie skryptów
Kod w jednym skrypcie może wywołać procedurę w innym skrypcie w ramach tego samego projektu skryptów. Do każdej zmiennej globalnej w dowolnym skrypcie można uzyskać dostęp w obrębie tego samego projektu.
Zmienne lokalne i globalne
Ponieważ skrypty mają zmienne lokalne i globalne, ważne jest, aby w skryptach w ramach projektu skryptów stosować unikatowe nazwy zmiennych. Jeśli zmienne są zdefiniowane poza jakimikolwiek procedurami i funkcjami, są globalne i mogą być dostępne z poziomu każdej jednostki (unit) w tym samym projekcie. Jeśli zmienne są zdefiniowane wewnątrz procedury lub funkcji, wówczas te zmienne lokalne nie są dostępne poza tymi procedurami/funkcjami.
Zaleca się umieszczanie w projekcie skryptów o podobnym charakterze oraz utrzymywanie liczby skryptów w projekcie na rozsądnym poziomie — śledzenie zmiennych globalnych w wielu skryptach może stać się problematyczne. Nie ma obowiązku przechowywania skryptów w projekcie skryptów, ponieważ skrypty można umieszczać także w innych typach projektów.
Unikatowe identyfikatory i zmienne
Podczas używania formularzy skryptów upewnij się, że wszystkie formularze skryptów mają unikatowe nazwy formularzy. Możliwe jest, aby wszystkie formularze skryptów w tym samym projekcie skryptów miały nazwę form1 (na przykład). W takim przypadku system skryptów napotyka konflikt podczas próby wyświetlenia właściwego formularza w momencie uruchomienia formularza skryptu.
Nazwę formularza skryptu można zmienić za pomocą Object Inspector. Nazwa zostanie automatycznie zmieniona zarówno w plikach jednostki skryptu, jak i formularza skryptu.
Procedury i funkcje bez parametrów
Skrypty należy pisać tak, aby procedury wymagane do wywołania w celu uruchomienia skryptu pojawiały się wyłącznie w oknie dialogowym Select Items to Run dialog. Aby zapobiec pojawianiu się innych procedur/funkcji w oknie dialogowym Select Items to Run, obok nazwy metody można wstawić parametr (Dummy : Integer). Zobacz przykład poniżej.
// This function is prevented from appearing in the Select Items to Run dialog.
Function TSineWaveform.CreateShape(Dummy : Integer);
Begin
//Do something
End;
{..................................................}
{..................................................}
Procedure TSineWaveform.bCloseClick(Sender: TObject);
var
I : integer;
Begin
//Doing something
Close;
End;
{..................................................}
{..................................................}
procedure DrawSine;
Begin
SineWaveform.showmodal;
End;
Kody błędów DelphiScript
|
Error |
Description |
|---|---|
|
|
W skrypcie użyto nieprawidłowego ciągu znaków. |
|
|
W skrypcie użyto nieprawidłowego ciągu znaków. |
|
|
W kodzie nie są dozwolone wielokrotne wystąpienia funkcji o tej samej nazwie. Zmień nazwy pozostałych funkcji, które mają tę samą nazwę. |
|
|
Nieznany identyfikator. Należy najpierw zadeklarować ten identyfikator, zanim zostanie użyty. |
|
|
Skrypt zawiera typ Variable, który jest nieprawidłowy lub nieznany. |
|
|
Wielokrotne wystąpienia tych samych nazw jednostek (unit) nie są dozwolone. Upewnij się, że nazwy jednostek skryptu są unikatowe. |
|
|
Deklaracja jednostki (unit) nie jest poprawnie zdefiniowana. |
|
|
Brak funkcji w skrypcie. |
|
|
DelphiScript nie może powiązać skryptu z wymaganymi wewnętrznymi komponentami. |
|
|
W skrypcie istnieje wiele wystąpień tej samej etykiety. Upewnij się, że etykiety w skrypcie są unikatowe. |
|
|
Blok deklaracji nie jest poprawnie zdefiniowany. |
|
|
Etykieta Goto nie jest zdefiniowana. |
|
|
W skrypcie istnieje wiele wystąpień tych samych zmiennych. Upewnij się, że zmienne są unikatowe. |
|
|
W bloku deklaracji zmiennych występuje błąd. Nieprawidłowe deklaracje lub deklaracje nierozpoznawane przez system skryptów. |
|
|
Zmienna nie została zdefiniowana, więc system skryptów nie może jej zdefiniować. |
|
|
Sygnatura metody jest niedozwolona. |
|
|
Użyto nieprawidłowych parametrów dla metody. |
|
|
Właściwości obiektu nie są rozpoznawane przez system skryptów. |
|
|
Podjęto próbę zadeklarowania deklaracji innych niż klasy. |
|
|
W skrypcie występuje błąd deklaracji. |
|
|
W skrypcie wystąpił błąd składni |
|
|
Nieprawidłowa nazwa identyfikatora, np. zduplikowana nazwa identyfikatora. Zdefiniuj ponownie nazwę identyfikatora. |
|
|
Nieprawidłowy identyfikator. Zdefiniuj nowy identyfikator |
|
|
Funkcja nie została poprawnie użyta w skrypcie |
|
|
Procedura nie została poprawnie użyta w skrypcie |
|
|
Wartość stałej szesnastkowej nie została poprawnie zadeklarowana. |
|
|
Skrypt musi zostać najpierw skompilowany, zanim będzie można go uruchomić. Błąd wewnętrzny. |
|
|
Błąd deklaracji stałej typu Real. |
|
|
Błąd deklaracji stałej typu String. |
|
|
Nieznany typ parametru zgłoszony przez system skryptów. |
|
|
Nie znaleziono wyniku wartości zmiennej dla określonego ciągu w skrypcie. |
|
|
Brak procedury w skrypcie. |
|
|
Brak parametru w skrypcie. |
|
|
Błąd wewnętrzny. |
|
|
Ta sama procedura lub funkcja została zadeklarowana i zaimplementowana w różny sposób. Sprawdź parametry między tymi dwoma. |
|
|
Jeden z parametrów metody, funkcji lub procedury nie ma poprawnego typu wariantowego. |
|
|
Próba ustawienia wartości dla właściwości tylko do odczytu albo właściwość nie istnieje. |
|
|
Argumenty użyte dla procedury lub funkcji nie są prawidłowe dla skryptu. |
|
|
Brak wartości parametru. |
|
|
Użyto nieprawidłowego typu parametru. |
|
|
Ten interfejs nie jest zadeklarowany ani zdefiniowany. |
|
|
Brak parametru wymaganego dla metody, funkcji lub procedury. |
|
|
DelphiScript wykrył nieznany błąd skryptu, który nie jest zdefiniowany w wewnętrznej tabeli błędów. |
|
|
DelphiScript wykrył nieprawidłowy kod operacji. |