Krok 4: Dodanie formularza do biblioteki //----------------------------------------------------- #include <vcl.h> #include <stdio.h> #pragma hdrstop #include "Add2Nos.h" //----------------------------------------------------- static short int siDLL_MAJOR_VERSION_NO = 1; static short int siDLL_MINOR_VERSION_NO = 0; //------------------------------------------------- USEFORM("Add2Nos.cpp", frmAddNumbers); //------------------------------------------------- extern "C" __declspec(dllexport) void VerNo(short int*, short int*); extern "C" __declspec(dllexport) bool Add2(char*, char*, long int*); void GetVersionNumbers(short int*, short int*); //-------------------------------------------------- int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void*) { return 1; } //-------------------------------------------------- void VerNo(short int* iMAJOR, short int* iMINOR) { GetVersionNumbers(iMAJOR, iMINOR); return; } //--------------------------------------------------- void GetVersionNumbers(short int* iMAJOR_VERSION, short int* iMINOR_VERSION) { *iMAJOR_VERSION = siDLL_MAJOR_VERSION_NO; *iMINOR_VERSION = siDLL_MINOR_VERSION_NO; return; } //------------------------------------------------- bool Add2(char* cText1, char* cText2, long int *Sum) { long int i, j; char cString1[20], cString2[20]; bool bMyLocalResult; TfrmAddNumbers *X = new TfrmAddNumbers(NULL); X->Edit1->Text = (AnsiString)cText1; X->Edit2->Text = (AnsiString)cText2; X->ShowModal(); bMyLocalResult = X->bResult; strcpy(cString1, X->Edit1->Text.c_str()); strcpy(cString2, X->Edit2->Text.c_str()); delete X; if(!bMyLocalResult) return false; sscanf(cString1, "%d", &i); sscanf(cString2, "%d", &j); *Sum = i + j; return true; }Na początku, dodajemy plik nagłówkowy Add2Nos.H, który definiuje formularz. Deklaracje funkcji Add2 i VerNo są do siebie w pewnym sensie podobne. Jeśli funkcje mają być używane na zewnątrz biblioteki, musimy wyeksportować ich nazwy. Potem musimy tylko zaprogramować to, co funkcje mają zrobić. Ponieważ sami tworzymy formularz, musimy wpisać odpowiedni kod w funkcji Add2. Pierwszą rzeczą jaką musimy zrobić, jest stworzenie egzemplarza naszego formularza. I tu właśnie używamy następującej konstrukcji: TfrmAddNumbers *X=new TfrmAddNumbers(NULL);Tworzymy obiekt X jako wskaźnik do formularza, obiekt ten będzie symbolizował nasz formularz. W tym momencie egzemplarz już istnieje, a my możemy obiektowi X przypisywać wszelkie właściwości, metody oraz zdarzenia, z których korzystamy przy projektowaniu formularzy w IDE. Sam formularz już powstał, ale nie jest jeszcze widoczny na ekranie. Zanim go jednak "uwidocznimy" zauważ, że biorę z funkcji wywołującej dwa stringi i używam ich do zainicjalizowania zawartości pól edycyjnych Edit1, Edit2. Spójrz na nazwę w powyższej konstrukcji i przypomnij sobie nazwę formularza (jego właściwość Name w tabeli przy punkcie 2). Builder dodaje przedrostek "T" jako część konwencji nazewniczej dla klas. Naszemu formularzowi nadaliśmy nazwę frmAddNumbers, więc Builder stworzył klasę o nazwie TfrmAddNumbers. Po prostu miej na uwadze, że jeśli podasz nazwę czegoś co nie istnieje, kompilator wyrzuci błąd. Być może zauważyłeś już pewną słabość jaka tu występuje: nie sprawdzamy poprawności wpisywanych przez użytkownika danych do pól edycyjnych. No, ale przecież ten samouczek dotyczy DLL-i, a takie sprawdzenie możesz wykonać bez mojej pomocy. Dopiero dzięki wyrażeniu X->ShowModal() nasz formularz fizycznie pojawia się na ekranie. Będąc tzw. oknem modalnym, wstrzymuje on pracę aplikacji aż do momentu jego zamknięcia. To znaczy, jeśli na ekranie mamy formularz w trybie modalnym, to nie możemy przejść do innych formularzy bez wcześniejszego zamknięcia tego modalnego. Formularze się pojawiają, użytkownik wpisuje tekst i klika któryś z dwóch przycisków. Kiedy użytkownik zamyka formularz, wykonywane są instrukcje następujące po X->ShowModal(). I tak, najpierw zapisałem wartość zmiennej bResult w formularzu (pamiętasz?, zadeklarowaliśmy ją w sekcji public) i teraz przypisuję ją do naszej nowej zmiennej typu bool w bibliotece (bMyLocalResult) Potem robimy kopie bieżących zawartości pól edycyjnych. Następnie likwidujemy obiekt X. UWAGA!!! Jeżeli tworzysz obiekt w czasie wykonywania, po zakończeniu operacji na nim, zawsze go usuń! Jeśli tego nie zrobisz, narażasz się na trudną do wykrycia konsumpcję pamięci. Zanim wywołasz metodę ShowModal, możesz robić z danym obiektem co tylko chcesz. Po tej metodzie - jest już za późno! Kiedy zamkniesz formularz modalny, to pobierz wszystkie potrzebne ci informacje z obiektu zanim go zlikwidujesz. Później, funkcja Add2 sprawdza wartość zmiennej typu bool którą zapisaliśmy przed zlikwidowaniem formularza. Jeśli wartość jest równa 0, to wciśnięto Anuluj, i zwracamy ten stan. Jeśli wartość jest 1, to znaczy że wciśnięto przycisk Oblicz. Zerknij do treści funkcji dla zdarzenia OnClick przycisku Oblicz. Jest to jedyne miejsce, gdzie wartość ta jest ustawiana na 1 (true). W końcu przekształcamy te dwa stringi wzięte z pól edycyjnych na binarne (sscanf) a ich sumę zwracamy potem w parametrze SUM. Nadajemy również całej funkcji Add2 wartość true, żeby w razie potrzeby program mógł wykonać jakieś specjalne działanie na parametrze SUM. Na tym właściwie kończy się samo tworzenie biblioteki DLL. Już prawie po krzyku! Krok 5: Utworzenie biblioteki importowej (.lib) Musimy jeszcze zrobić parę rzeczy. Wybierz Project/Make w celu skompilowania i zlinkowania wprowadzonego kodu. Nie powinieneś dostać żadnych błędów więc sprawdź swój kod i usuń ewentualne literówki przed kompilacją. Kolejnym krokiem jest utworzenie spisu zawartości biblioteki DLL, przy użyciu narzędzia zwanego implib. Taki spis (biblioteka importowa) będzie używana w każdym programie korzystającym z DLL-a. Niestety C++Builder nie pokazuje implib w menu Tools, zatem musisz przejść do okna DOS-u. Biblioteka importowa stanowi pomost pomiędzy programem a DLL-em. Ma decydujące znaczenie przy określaniu zawartości biblioteki DLL. Bez niej, twój program nie byłby w stanie używać żadnych funkcji DLL-a. Zatem do dzieła: kliknij Start/Programy/Tryb MS-DOS. Zmień katalog na DLLTUTOR. C++Builder dostarczany jest z programem implib.exe, który powinien znajdować się w katalogu Program Files/Borland/Builder/Bin. Podczas instalacji C++Builder zadbał już o to, abyś mógł uruchamiać implib.exe z każdego innego katalogu - po prostu umieścił w.w. ścieżkę w pliku autoexec.bat. Wpisz poniższą komendę: implib tutorial.lib tutorial.dllProgram implib przeczyta pozycje funkcji w DLL-u (stworzone przez Builder'a) i utworzy w bieżącym katalogu bibliotekę importową o nazwie TUTORIAL.LIB i rozmiarze ok. 2Kb. Możesz już używać biblioteki importowej oraz DLL-a w twoim programie. TUTORIAL.LIB posiada nazwy funkcji eksportowanych. Skopiuj teraz TUTORIAL.LIB i TUTORIAL.DLL do drugiego z utworzonych przez ciebie katalogów, a mianowicie do TESTPROG. Jak często musisz używać implib? To zależy od tego co zmieniasz w DLL-u. Jeżeli chcesz dodać lub usunąć z biblioteki jakieś funkcje eksportowane, to na pewno po każdej takiej zmianie musisz użyć implib. Reguła ta dotyczy jednak tylko funkcji eksportowanych, nie dotyczy to funkcji wewnętrznych. Ostatnio utworzona biblioteka importowa stanowi dla twojego programu swego rodzaju spis treści tego co zawiera DLL, pomijając fakt że mogłeś już usunąć stamtąd jakąś funkcję. Mógłbyś być bardzo niemile zaskoczony, gdyby twój program odwołał się do DLL-a w poszukiwaniu funkcji, która tam nie istnieje. Nie musisz powtórnie używać implib, jeśli tylko zmieniasz kod w definicji funkcji lub jej parametry. Jak już mówiłem, biblioteka importowa jest takim indeksem tego co znajduje się w DLL-u, a nie tego, jak jest to wykonywane.
|