Wygląd XP naszej aplikacji przy wykorzystaniu plików .manifest

intol

W chwili obecnej na każdej (dobrej) stronie poświęconej programowaniu znajduje się opis jak przy pomocy plików .xml i funkcji InitCommonControls () sprawić aby nasz program nabrał wyglądu Windows XP. Ja jednak (jak zwykle skromnie ;-) ) znalazłem inny ciekawy sposób (piszę "znalazłem", a powinienem napisać "podpatrzyłem", ponieważ sposób ten zauważyłem w jednej z Microsoft'owych aplikacji - bodajże NetMeeting). Oto on:

Aby nasza aplikacja w systemach wyposażonych w Lunę (czyli interfejs "XP") wyglądała "ładnie", z jej plikiem .exe podczas kompilowania nie musimy nic robić. Wystarczy że w katalogu w którym "trzymamy" program utworzymy plik: nazwa_programu.exe.manifest (oczywiście zamiast nazwa_programu wstawiamy nazwę naszego pliku .exe). W skrócie ten proces nazywania pliku można przedstawić tak: na sam koniec nazwy naszego programu (po rozszerzeniu .exe) dodajemy słowo .manifest (ważna jest kropka na początku). Do tak przygotowanego pliku wklejamy następującą zawartość:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
   <assemblyIdentity
      version="2.0.0.0"
      processorArchitecture="X86"
      name="Nazwa programu, dowolna "
      type="win32"
   />
   <description>Opis Programu</description>
   <dependency>
      <dependentAssembly>
         <assemblyIdentity
            type="win32"
            name="Microsoft.Windows.Common-Controls"
            version="6.0.0.0"
            processorArchitecture="X86"
            publicKeyToken="6595b64144ccf1df"
            language="*"
         />
      </dependentAssembly>
   </dependency>
</assembly>

Oczywiście to rozwiązanie ma swoje plusy i minusy:

Plusy:

szybkość wykonania takiego pliku .manifest (przez nas)

mniejszy plik wykonywalny aplikacji (nie kompilujemy razem z nim pliku .xml)

program UPX niekiedy nie radził sobie zbyt dobrze z plikami, które miały "w sobie" plik .xml ponieważ kompresował go, a wtedy występował błąd (trzeba było ustawić brak kompresji dla zasobów, co zwiększało rozmiar pliku wykonywalnego)

Minusy:

aplikacje trzeba rozprowadzać razem z plikiem .manifest (może przeszkadzać gdy program mieści się np. w jednymi pliku .exe). Mozna jednak dodać funkcję, która sprawdzała by czy plik .manifest znajduje się w katalogu programu, a w przeciwnym razie tworzyła go.

gdy użytkownik (nie programista) zmieni przez przypadek nazwę naszego pliku .exe, plik .manifest przestanie działać (tego minusa też da się uniknąć, patrz minus pierwszy)

Manifest w Visual Studio 2005 lub nowszym

Jeżeli ktoś pisze w VS 2005 lub nowszym to na pewno ma problem z tym całym manifestem. Problem jest taki, że generowany automatycznie manifest nie ma dodanej zależności odnoszącej się do comctl32.dll w wersji 6.0 lub nowszej. Trzeba wtedy dodać ją ręcznie - najeży przy tym wiedzieć jak.

Najłatwiej jest użyć dyrektywę preprocesora, która zrobi wszystko za nas:

#pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")

albo odpowiednio skonfigurować linker. Jeżeli ktoś lubi ręczne dodawanie to musi wpisać (zazwyczaj jest tam już inna zależność do Microsoft.VC90.CRT):

<dependency>
   <dependentAssembly>
      <assemblyIdentity
         type="win32"
         name="Microsoft.VC90.CRT"
         version="9.0.21022.8"
         processorArchitecture="x86"
         publicKeyToken="1fc8b3b9a1e18e3b"
      />
   </dependentAssembly>
</dependency>
<dependency>
   <dependentAssembly>
      <assemblyIdentity
         type="win32"
         name="Microsoft.Windows.Common-Controls"
         version="6.0.0.0"
         processorArchitecture="*"
         publicKeyToken="6595b64144ccf1df"
         language="*"
      />
   </dependentAssembly>
</dependency>

Więcej informacji na MSDN.

--
Autorzy: Mariusz Żurawek (INTOL), Mammoth
http://www.zurawek.comww.zurawek.com">http://www.zurawek.com</a>
Wszelkie prawa zastrzeżone.

10 komentarzy

A ja polecam nie stosować tych durnych znaków cudzysłowowa. Jak sama nazwa wskazuje "cudze słowo". Co to maja być, niby cytat? Używasz normalnych słów występujących w języku polskim i po co je cytujesz??

Acha, z tego, co napisał Microsoft podaję listę komponentów, które obsługuje manifest XP ( z plikiem Comctl32.dll w wersji 6):

*  TextBox control
* ListView control
* RichTextBox control	
* TreeView control
* HScrollBar control
* DateTimePicker control
* VScrollBar control
* MonthCalendar contro
* ProgressBar control
* Splitter control
* TabControl control
* TrackBar contro
* MainMenu control
* StatusBar control
* ContextMenu control
* ToolBar control
* ComboBox control
* TreeView control
* DataGrid control
* ListView control
* ListBox control

Zamiast "Nazwa programu, dowolna" można wpisać "DelphiApplication". Wtedy przy zmianie pliku .exe nie trzeba się męczyć także z manifestem. U mnie (BCB 6) manifest działa tylko z standardowymi kontrolkami windowsa.

Wiekszosc rzeczy rzeczywiscie wyglada ladnie po xp-kowemu, ale np wszelkiej masci buttony wygladaja nadal po staremu:( Czy mozna cos z tym zrobic? A moze ktos ma link do jakiegos innego sposobu?

ja robie manifes wewnątrz programu w zasobach i nie musze miec tego durnego manifestu w folderze gdzie jest exe

Co do plusów -
"> mniejszy plik wykonywalny aplikacji (nie kompilujemy razem z nim pliku .xml)"
Hm, tym gorzej, ze nie kompilujemy razem z aplikacją xml. Aplikacja powiększy się niewiele, bo w sumie ile zajmuje taki plik. Ale jeśli zawartość bedzie w osobnym pliku to zajmie znacznie wiecej miejsca na dysku. Ten osony plik zajmie caly sektor na dysku. Tak ze to raczej nie plus a minus tego rozwiazania.

Nie stety nie działa mi :( Wyświetla błąd o złej konfiguracji programu. Czy to wogóle działa z Builderem 5??

W Builderze 6 nie ma żadnych błędów <_<

przy użyciu w builderze wyskakuje błąd: "Acces Violation at Adress 5264529e in module 'direct50.dpl'. Read of Adress 00000000"

Polecam użycie tego na Builderze.