PORADY

Porady > Programowanie > Delphi > Migracja na Delphi XE2 - jak przenieść projekt aplikacji do XE2

Migracja na Delphi XE2 - jak przenieść projekt aplikacji do XE2

Delphi XE2 to pierwsze środowisko wydane przez Embarcadero (dawniej wydawane przez Borland), które pozwala na kompilowanie 64-bitowych aplikacji. Choć samo występuje wyłącznie w trybie 32-bitowym (wszystkie kompilatory Embarcadero są tworzone w... Delphi! Stąd dopiero przyszła wersja prawdopodobnie dostępna będzie w wersji 64-bitowej) i jest jeszcze mocno niestabilne, to jednak ta rewolucja nakłoniła wielu użytkowników do przejścia z wersji Delphi 6, 7 czy 8 właśnie do tego nowego środowiska. Poza koniecznością kłopotliwej migracji na standard UNICODE, dochodzi problem migracji na kod 64-bitowy. Oczywiście podręczniki i pomoce opisują na co należy zwracać uwagę podczas przenoszenia kodu. Jednak często praktyka i teoria są od siebie odległe. Dlatego postanowiłem sam przedstawić kilka wskazówek, jakie należy wziąć pod uwagę migrując swoje projekty do Delphi XE2.

Oczywiście poniższe wytyczne nie są wyczerpujące i nie zastępują oficjalnych podręczników wydawanych przez Embarcadero opisujących zmiany (szczególnie gorąco polecam podręcznik „Reasons to Migrate to Delphi XE2” - niestety w języku angielskim). W związku z licznymi bieżącymi zmianami radzę także bardzo dokładnie wczytywać się w opisy nowości i znanych problemów, jakie pojawiają się wraz z kolejnymi uaktualnieniami środowiska XE2, gdyż może się okazać, że migracja nawet z Delphi XE2 Update 1 do Delphi XE2 Update 4 może nieść ze sobą bardzo dużo niespodzianek!

Poradnik ten adresuję w większości do zaawansowanych użytkowników. Nie będę tu wyjaśniał znaczenia komponentów czy pokazywał przykładowych konstrukcji licząc na to, że czytelnik sam będzie wiedział, co należy wykonać. Nadmienię tylko jeszcze, że nie wszystkie porady dotyczą tylko Delphi XE2, ale znajdą też zastosowanie w starszych wydaniach, jak przejście na Delphi XE, Delphi 2010 czy Delphi 2009.

Spis treści

Przenoszenie projektów

Okazuje się, że import ustawień projektu może przynieść kilka niespodzianek w postaci albo błędnie zaimportowanych danych, albo danych nadmiarowych. Tak jest w przypadku wersji projektu – nie ma możliwości w samym środowisku nakazać pobierania wersji z ustawień nadrzędnych. Ponadto część plików staje się bezużyteczna w nowym środowisku. Jak więc zrobić to najlepiej?

  1. Otwieramy plik dpr w Delphi XE2 i zamykamy bez zapisywania zmian.
  2. Otwieramy w edytorze tekstowym powstały plik dproj i edytujemy w celu wyeliminowania bałaganu w wersjach po przeniesieniu:
    1. Odszukujemy wszystkie wystąpienia '1.0.0.0' (o ile nasz projekt nie zawierał takiej wersji)
    2. Usuwamy sekcje, w których się znajdują takie ciągi znaków
    to nalezy wyrzucić z pliku dproj po przeniesieniu projektu do Delphi XE2
  3. Otwieramy ponownie projekt w XE2 i zapisujemy.
  4. Z katalogu, gdzie zostały przeniesione pliki usuwamy niepotrzebne już *.cfg, *.drc, *.dof oraz *.ddp (w tym ostatnim przypadku o ile nie korzystaliśmy w projekcie z diagramów). Także warto usunąć pliki *.~* (nowe Delphi historię tworzy w nowych podkatalogach).
  5. Uwaga – stary plik res jest nadpisywany. Wszelkie niestandardowe zasoby są wyciągane do pliku z rozszerzeniem otares. Dodać je można dyrektywą {$R *.otares} umieszczaną w pliku dpr.
  6. Po zaimportowaniu projektu patrzymy, czy ścieżki ustawione są OK. Jeśli w kodach nie chcemy stosować podanych przestrzeni nazw (ang. namespace), to w Delphi Compiler / Unit scope names wpisujemy: Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;System;Xml;Data;Datasnap;Web;Vcl;Vcl.Samples;Vcl.Shell (powinno wystarczyć dla zachowania kompatybilności).
  7. Jeśli w ścieżkach wystąpi stała $(DELPHI) to wskazuje ona na stare środowisko Delphi! Nowe jest pod stałą $(BDS)

Na co zwrócić uwagę podczas otwierania projektu i jego ustawień oraz ustawień Delphi

Czasem otwarcie projektu sprawia nam niemiłą i zaskakującą niespodziankę. To nie musi występować zawsze, ale ostrzegam, co może się przytrafić.

  • Jeśli podczas otwarcia projektu pojawia się komunikat o braku komponentu, a na pewno go mamy (np. IBQuery), to zamykamy projekt bez zapisywania i otwieramy ponownie – powinno pomóc.
  • Uważnie patrzymy, dla jakiej konfiguracji/platformy ustawiamy opcje projektu. Jeśli się określi np. wersję pliku dla konfiguracji Release / Win32, a nie dla All, to pozamiatane – pozostaje wykonać punkt 4 z poprzedniego tematu.
  • Warto z ustawień Release wyłączyć domyślne Assercje (zupełnie niepotrzebne dodatkowe dołożenie kodu do wyniku).
  • W paczkach (Component / Instal packages) czasem odznaczają się obie paczki związane z Officem.
  • Przełączanie pomiędzy trybem 32/64-bity zawsze wymaga użycia opcji build dla projektu.
  • Domyślnie wyłączona jest opcja związana z kompilacją zmienianych plików. Jeśli lubimy edytować otwarty plik w innym edytorze lub innej instancji Delphi, to zmiany nie zostaną uwzględnione przy kompilacji (nie dotyczy budowania). Dlatego warto zaznaczyć opcję Environment Options / Always compile modified projects.
    Opcję 'Always compile modified projects' warto zaznaczyć w ustawieniach

Komponenty w Delphi XE2

Instalacja komponentów w Delphi XE2 wnosi pewne nowości. Po pierwsze w zależności od tego, czy mamy komponenty w wersji 32-bitowej czy 64-bitowej będziemy mogli ich użyć wyłącznie w programach o takiej architekturze (dla projektów przeznaczonych dla platformy Windows 32 i Windows 64 potrzebne są komponenty w obu wersjach). Jeśli ręcznie instalujemy komponenty, to należy dokonać kompilacji z wykorzystaniem obu platform, natomiast instalacji dokonujemy wyłącznie w trybie 32-bitowym (gdyż samo środowisko jest wyłącznie 32-bitowe).

Na co zwrócić uwagę w kodzie

Podczas kompilowania starego projektu jest niemal pewne, że kompilator zarzuci nas garścią informacji o przestarzałym kodzie (deprecated) lub wskazówkami i ostrzeżeniami o wątpliwych częściach kodu. Często obok komunikatu znajdziemy też podpowiedź z gotowym rozwiązaniem (np. o wskazaniu użycia przestrzeni FormatSettings). A na co zwrócić szczególną uwagę?

  • Uważnie obserwujemy wszelkie niejawne rzutowania StringAnsiString. Jeśli potrzebujemy pracować na AnsiStringach (czyli 8-bitowych), to w przestrzeni System.AnsiStrings są funkcje przeznaczone dla tego typu (np.: AnsiStr:=System.AnsiStrings.Trim(AnsiStr)). Przestrzeń dodajemy oczywiście do sekcji uses.
  • Zwracamy uwagę na wszelkie operacje chr i ord – one z założenia pracują na pełnym zakresie (16-bitowym), więc wyniki mogą być inne niż kiedyś.
  • Nie wolno w sekcji finally umieszczać kolejnej try..finally. Jeśli jest taka potrzeba – to, co jest objęte kolejnym blokiem chronionym należy przenieść do funkcji i wywołać ją. (Stan dla Delphi XE2 Update 1 do Update 4; możliwe, że także przyszłe aktualizacje nie wyeliminują tego błędu).
  • Jeśli często wywołujemy jakąś funkcję (w pętli), to można rozważyć oznaczenie jej jako inline – zyska się na wydajności kosztem rozmiaru pliku wynikowego.
  • Wszelkie operacje na znakach z użyciem operatora In powoduje konwersję na 8-bitowy zapis. Należy używać CharInSet. Jednak aby w pełni sprawdzić zawartość znaku w zbiorze znaków UNICODE, należy użyć WideStrUtils.InOpArray(WideChar, array of WideChar). UWAGA! Drugi parametr jest już tablicą, a nie zbiorem! Dlatego w pewnych sytuacjach nie będzie możliwości skorzystania z tego rozwiązania. Wówczas pozostaje przerobienie kodu na pętlę i badanie indywidualne znak po znaku.
  • Obecnie modułami zajmującymi się przetwarzaniem obrazu są standardowe: Vcl.Imaging.JPEG, Vcl.Imaging.GifImg oraz Vcl.Imaging.PNGImage. Nie ma już potrzeby korzystania z zewnętrznych klas obsługi.
  • AnsiString, OpenString (zalecany do używania w nagłówkach eksportowanych funkcji DLL), ShortString i String[x] to typy 8-bitowe. Ponodnie jak AnsiChar i PAnsiChar. Nie ma możliwości określenia zmiennej zawierającej ciąg znaków UNICODE o zadanej długości (pomijając tablice znaków równoważne z typem PChar).
  • Dla obiektu TAnimate, który pobiera animację z zasobów, najpierw należy określić ResHandle. Ponadto zauważyłem, że animacje przerysowują się wyłącznie podczas przerysowania formy lub wyświetlania np. okienka z komunikatem. Niestety nie znalazłem rozwiązania tego problemu.
  • Obiekt typu TStringField jest typem AnsiString (8-bitowy)! Należy używać pola TWideStringField lub w przypadku komponentów Interbase – TIBString. Podobnie warto postąpić w przypadku pól typu TFloatField i zastąpić je typem TBCDField (jeśli pola były zdefiniowane w komponencie TQuery i pochodnych, należy przedefiniować na nowo). Warto w tym miejscu nadmienić, że bardzo prostą metodą jest edycja tekstowa plików dfm (z poziomu widoku formy należy wywołać menu kontekstowe i wybrać opcję View as text). Nie ma przy tym potrzeby edycji w pliku kodu – kompilator zrobi to za nas przy kompilacji, o ile mu na to pozwolimy.
  • W podobny sposób swoje znaczenie zachowały typy zmiennych Variantowych. varString pozostaje typem oznaczającym AnsiString. W przypadku operowania na typach pól bazodanowych, typ ftString także oznacza typ AsniString. W obu tych przypadkach należy zwrócić uwagę, że ta pozorna niekonsekwencja bierze się z faktu, iż już wcześniej istniały oznaczenia określające typ WideString (odpowiednio: varUString i ftWideString), więc nie zdecydowano się wprowadzać jakichkolwiek zmian. To w następstwie zmusza do wprowadzania zmian w kodzie.
  • Obiekty i klasy bazodanowe zwracają obecnie znacznie szerszy wachlarz typów pól, niż miało to miejsce w starszych wersjach Delphi. Jeśli gdzieś użyte jest bazowanie na typie pola (FieldType) to warto zweryfikować kod i ewentualnie rozszerzyć go o obsługę pełnej listy typów pól. Listę tą można znaleźć w pomocy.
  • W przypadku odwoływania się do pól poprzez Fields lub FieldByName lub parametrów poprzez Params lub ParamByName aby odwołać się do starego formatu stringa należy użyć AsAnsiString.
  • Prawdopodobnie błąd powoduje, że jeśli mamy na komponencie typu TQuery lub pochodnych (TIBQuery) pola zwracające liczbe o więcej niż 4 miejscach po przecinku (także powstała wskutek rzutowania lub mnożenia/dzielenia kolumn z liczbami z przecinkiem), to pojawia się błąd Field '' not found podczas wykonywania programu lub podczas próby dodania pola do komponentu TQuery, jeśli jest to pierwsza próba od nawiązania połączenia (tryb projektowania). W takim przypadku niestety trzeba w zapytaniu wskazać typ wynikowy poprzez rzutowanie na liczbę o maksymalnie 4 miejscach po przecinku (np.: SELECT CAST(c1 * c2 AS DECIMAL(14,4)) AS kolumna)).
  • Wszystkie obiekty typu TIBQuery muszą mieć przypisaną bazę danych (Database). Nie można przypisywać wyłącznie transakcji! (choć zdarzają się wyjątki)
  • Jeśli podczas wykonywania zapytań bazodanowych pojawi się błąd pochodzący z bazy danych (np. podczas wykonania polecenia Open komponentu TIBQuery), a wszystko odbywa się w pliku DLL, to wyjście z pliku spowoduje zawieszenie się aplikacji. Aby wyeliminować ten problem należy po wejściu w funkcję pliku DLL wywołać polecenie IBSQLMonitor.DisableMonitoring. Warto więc wykonać to polecenie zawsze, kiedy w pliku DLL używamy bazy danych poprzez komponenty InterBase.
  • Nie można inicjalizować (GdiPlusStartup) i finalizować (GdiplusShutdown) interfejsu GDI+ w plikach DLL. Takie rzeczy muszą odbyć się w EXE. To samo dotyczy używania komponentów takich jak obecnie standardowy TTeeGDIPlus - także one muszą znaleźć się w pliku EXE, nawet jeśli nie są powiązane z innymi komponentami.
  • Dla obiektów klasy TThread stały się przestarzałe metody Resume oraz Suspend. Zamiast Resume należy obecnie używać metody Start. Jednak trzeba uważać, aby nie wzbudzać tak już wzbudzonego wątku. Dlatego najlepiej zamienić to na kod if Suspendes then Start;. Natomiast metoda Suspend nie ma już odpowiednika. Można tylko utworzyć uśpiony wątek, ale nie można już usypiać działających. Pozostają tylko metody takie jak Sleep lub wsparcie się WinAPI lub funkcją WaitFor wewnątrz wątku (nie będzie go można wzbudzić normalnie, lecz tylko wysyłając komunikat!).

Na co zwrócić uwagę na formatkach

Poza zwróceniem szczególnej uwagi na kod, warto też przyjrzeć się formatkom. I nie chodzi tu tylko o zmiany w wyglądzie związane ze stosowaniem styli (widoczne tylko, gdy mamy włączone w systemie).

  • Zmieniły się wartości ModalResult w Delphi XE2 oraz w Delphi XE2 Update 3. W plikach dfm są zapisywane przez wartość, więc wyniki obecnie mogą być niezgodne z wcześniej określonymi. Sprawdzić przyciski na formatkach (głównie stany inne niż mrOk i mrCancel).
  • Doszła własność ParentBackground, domyślnie włączona (ale również zdarzają się wyjątki). Takie ustawienie powoduje, że tam, gdzie są użyte tematy, nie zostanie zastosowany kolor określony przez nas. Należy wyłączyć tą własność.
  • Podczas importu zanika stan włączony dla własności AutoScroll (zdiagnozowane w przypadku formatek). Okazuje się, że podobne cyrki potrafią dziać się z innymi własnościami, np MultiSelect dla DBGrid. A czasem okazuje się, że wszystko jest pomyślnie. Jednym słowem - trzeba uważać na wszystkie własności.
  • Stan własności Transparent (np. dla TLabel) zmienił stan domyślny z False na True. Z tego względu tam, gdzie mieliśmy to włączone to tak zostanie, a tam gdzie było wyłączone – zostanie włączone. ;)
  • Własność DoubleBuffered jest określona teraz w inspektorze obiektów. Warto włączyć dla animowanych elementów (także często zmieniających się tekstów) czy komponentów używających zdarzeń CustomDraw. (W nowym Delphi efekty migotania są bardziej dokuczliwe niż w starym).
  • Nowy wygląd okienek zapisu i odczytu pliku (OpenDialog, SaveDialog) jest w innych komponentach – TFileOpenDialog i TFileSaveDialog. Komponenty TOpenPictureDialog niestety są zepsute i obrazek wyświetla się gdzieś w tle. Je można jednak śmiało zastąpić właśnie nowymi oknami, które w opcjach mają możliwość włączenia podglądu pliku.
  • Jeśli na komponencie TListView ikony i elementy są przesunięte (tak, jakby był do nich stosowany jakiś margines) pomaga włączenie i wyłączenie własności Checkboxes tego komponentu.
  • Komponent TListView posiada ciekawą własność - grupowaia elementów. Określając grupy i włączając opcję GroupView uzyskujemy efekt, jaki widać np. w oknie Mój komputer przy grupowaniu po kategoriach. Z tą opcją związane są jednak dwie uwagi: Po pierwsze aplikacja musi mieć włączone style (ang. Enable runtime themes - opcja znajduje się w ustawieniach projektu w gałęzi Application). Po drugie wszystkie elementy muszą znajdować się w jakiejś grupie, aby były widoczne.
  • Uzywając styli w systemie oraz włączając je w aplikacji można zauważyć, że nagłówki komponentów DBGrid i pochodzne nie są ładnie wygradientowane (lub nie przyjmują innych ustawień stylu systemu), lecz są szare (lub w innym kolorze). Przy czym nie zawsze dotyczy to wszystkich kolumn. Aby naprawić ten san rzeczy należy we właściwości Columns.Tilte.Color ustawić kolor clDefault dla wszystkich kolumn komponentu.

Dla wygody

W nowym środowisku pojawiło się kilka użytecznych konstrukcji językowych, które na pewno skrócą kod źródłowy (kod wynikowy często pozostaje bez zmian). Oto najciekawsze:

  • Konstrukcja for..in pozwala na pominięcie określania zakresu czy zmiennych pomocniczych indeksujących. Jednak zmienna skanująca jest tylko do odczytu! Po szczegóły wykorzystania odsyłam do pomocy.
  • Konstrukcja Exit(wartość) pozwala na wyjście z funkcji z przypisaniem wartości zmiennej Result (nie trzeba dwóch linijek kodu).
  • Proponuję zapoznać się z formaterem kodu (wywoływany skrótem Ctrl+D) – bałagan w formatowaniu można teraz łatwo naprawić. ;)
Informacje o poradzie
Powiązane linki:Wróć
[Komentarze] | Share Podziel się
Poradę czytano:2 667 razy
Ocena porady:
6,00 (2 oceniających)
(Kliknij właściwą gwiazdkę, by oddać głos)

Uwaga! Wszystkie porady na tej stronie są mojego autorstwa i objęte są prawami autorskimi! Kopiowanie, publikowanie lub cytowanie całego tekstu bez wiedzy autora - ZABRONIONE! [Dowiedz się więcej o prawach autorskich]

Strona istnieje od 25.01.2001
Ta strona używa plików Cookie
 
archive To tylko kopia strony wykonana przez robota internetowego! Aby wyświetlić aktualną zawartość przejdź do strony.
Ładowanie...

Optymalizowane dla przeglądarki Firefox
© Copyright 2001-2017 Dawid Najgiebauer. Wszelkie prawa zastrzeżone.
Ostatnia aktualizacja podstrony: 22.09.2014 11:28
Wszystkie czasy dla strefy czasowej: Europe/Warsaw