TN035: używanie wielu plików zasobów i plików nagłówków z programem Visual C++
[!UWAGA]
Następująca uwaga techniczna nie został zaktualizowana od pierwszego uwzględnienia jej w dokumentacji online.W rezultacie niektóre procedury i tematy może być nieaktualne lub nieprawidłowe.Aby uzyskać najnowsze informacje, zaleca się wyszukać temat w indeksie dokumentacji online.
Ta uwaga opisuje, jak edytor zasobów Visual C++ obsługuje wiele plików zasobów i plików nagłówkowych współdzielonych w jednym projekcie lub współdzielonych przez wiele projektów, a także, jak można wykorzystać tę obsługę.Ta uwaga odpowiada na te pytania:
Kiedy warto podzielić projekt na wiele plików zasobów i/lub plików nagłówkowych i jak to zrobić?
Jak współdzielić wspólny plik nagłówkowy .H między dwoma plikami .RC?
Jak podzielić zasoby projektu na wiele plików .RC?
Jak (przy użyciu narzędzi) zarządzać zależnościami kompilacji między plikami .RC, .CPP i .H?
Należy pamiętać, że po dodaniu dodatkowego pliku zasobów do projektu, ClassWizard nie rozpozna zasobów w dodanym pliku.
Ta uwaga odpowiada na powyższe pytania w następujący sposób:
Overview of How Visual C++ Manages Resource Files and Header Files zawiera omówienie, jak polecenie "Zestaw zasobów zawiera" w programie Visual C++ umożliwia korzystanie z wielu plików zasobów i plików nagłówkowych w tym samym projekcie.
Moduł Analysis of AppWizard-created .RC and .H Files sprawdza wiele plików zasobów i nagłówkowych, które są używane przez aplikację utworzoną przez kreatora AppWizard.Te pliki stanowią dobry model dla dodatkowych plików zasobów i plików nagłówkowych, które można dodać do projektu.
Including Additional Header Files opisuje, gdzie można dołączyć wiele plików nagłówkowych i podaje szczegółowe informacje, jak to zrobić.
Sharing a Header File Between Two .RC Files pokazuje, jak można współdzielić jeden plik nagłówkowy między wieloma plikami .RC w różnych projektach lub w tym samym projekcie.
Using Multiple Resource Files in the Same Project opisuje, w jakich sytuacjach warto rozważyć rozdzielenie projektu na wiele plików .RC, i podaje szczegółowe informacje, jak to zrobić.
Enforcement of Non-Editable Visual C++ Files opisuje, jak można się upewnić, że Visual C++ nie edytuje i nie zmienia w niezamierzony sposób formatowania niestandardowych zasobów.
Managing Symbols Shared by Multiple Visual C++-Edited .RC Files opisuje sposób współdzielenia tych samych symboli przez wiele plików .RC oraz sposób, w jaki można unikać przypisywania zduplikowanych wartości liczbowych identyfikatora.
Managing Dependencies Between .RC, .CPP, and .H Files opisuje, jak Visual C++ pozwala uniknąć niepotrzebnych rekompilacji plików .CPP, które są zależne od plików symboli zasobów.
How Visual C++ Manages Set Includes Information zawiera szczegółowe informacje techniczne na temat tego, jak Visual C++ śledzi wiele (zagnieżdżonych) plików .RC i wiele plików nagłówkowych dołączonych dyrektywą #include przez plik .RC.
Omówienie, jak Visual C++ zarządza plikami zasobów i plikami nagłówkowymi
Visual C++ zarządza pojedynczym plikiem zasobów .RC i odpowiadającym mu plikiem nagłówkowym .H jako parą ściśle powiązanych plików.Kiedy edytujesz i zapisujesz zasoby w pliku .RC, pośrednio edytujesz i zapisujesz symbole w odpowiadającym mu pliku .H.Chociaż można otwierać i edytować wiele plików .RC naraz (za pomocą interfejsu użytkownika interfejsu MDI programu Visual C++), dla danego pliku .RC można pośrednio edytować dokładnie jeden odpowiedni plik nagłówkowy.
Plik nagłówkowy symboli
Domyślnie program Visual C++ zawsze nazywa odpowiedni plik nagłówkowy RESOURCE.H, niezależnie od nazwy pliku zasobów (np. MYAPP.RC).Za pomocą polecenia Zasób zawiera z menu Widok w programie Visual C++ można zmienić nazwę tego pliku nagłówkowego, aktualizując plik nagłówkowy symboli w oknie dialogowym Zestaw zawiera.
Dyrektywy symboli tylko do odczytu
Chociaż środowisko Visual C++ edytuje tylko jeden plik nagłówkowy dla każdego pliku .RC, obsługuje odwołania do symboli zdefiniowanych w dodatkowych plikach nagłówkowych tylko do odczytu.Za pomocą polecenia Zasób zawiera z menu Widok w programie Visual C++ można określić dowolną liczbę dodatkowych plików nagłówkowych tylko do odczytu jako dyrektywy symboli tylko do odczytu.Ograniczenie "tylko do odczytu" oznacza, że podczas dodawania nowego zasobu w pliku .RC możesz użyć symbolu zdefiniowanego w pliku nagłówkowym tylko do odczytu; ale jeśli usuniesz zasób, symbol nadal pozostaje zdefiniowany w pliku nagłówkowym tylko do odczytu.Nie możesz zmienić wartości numerycznej przypisanej do symbolu tylko do odczytu.
Dyrektywy czasu kompilacji
Visual C++ obsługuje również zagnieżdżanie plików zasobów, gdzie jeden plik .RC jest dołączony przez #include w innym.Podczas edytowania danego pliku .RC przy użyciu Visual C++, wszystkie zasoby w plikach dołączanych przez #include nie są widoczne.Ale przy kompilacji pliku .RC pliki umieszczone w dyrektywie #include również są kompilowane.Za pomocą polecenia Zasób zawiera z menu Widok w programie Visual C++ można określić dowolną liczbę plików .RC dołączanych dyrektywą #include jako dyrektywy czasu kompilacji.
Zwróć uwagę, co się stanie, jeśli wczytasz do Visual C++ plik .RC, w którym znajduje się dołączony dyrektywą #include inny plik .RC, który nie jest określony jako dyrektywa czasu kompilacji.Ta sytuacja może powstać po przywróceniu do programu Visual C++ pliku .RC, który użytkownik wcześniej utrzymywał ręcznie za pomocą edytora tekstów.Kiedy Visual C++ odczytuje plik .RC dołączony dyrektywą #include, łączy on dołączane zasoby z macierzystym plikiem .RC.Podczas zapisywania nadrzędnego pliku .RC, instrukcja #include w efekcie zostanie zastąpiona przez zasoby dołączane za pośrednictwem #include.Jeżeli nie chcesz takiego połączenia, usuń instrukcję #include z nadrzędnego pliku .RC przed wczytaniem go do Visual C++; następnie przy użyciu Visual C++ dodaj z powrotem tę samą instrukcję #include jako dyrektywę czasu kompilacji.
Visual C++ zapisuje w pliku .RC trzy rodzaje powyższych informacji Zestaw zawiera (plik nagłówkowy symboli, dyrektywy symboli tylko do odczytu i dyrektywy czasu kompilacji) w dyrektywach #include oraz w zasobach TEXTINCLUDE.Zasoby TEXTINCLUDE, szczegóły implementacji, z którymi programista zwykle nie ma do czynienia, są wyjaśnione w Jak Visual C++ zarządza informacjami o zawartości zestawu.
Analiza plików .RC i .H utworzonych przez kreatora AppWizard
Badanie kodu aplikacji, tworzonego przez AppWizard zapewnia wgląd w sposób, w jaki Visual C++ zarządza wieloma plikami zasobów i plikami nagłówkowymi.Fragmenty kodu zbadane poniżej pochodzą z aplikacji MYAPP, stworzonej przez AppWizard przy użyciu opcji domyślnych.
Aplikacja utworzona przez kreatora AppWizard używa wielu plików zasobów i wielu plików nagłówkowych, jak opisano w poniższym diagramie:
RESOURCE.H AFXRES.H
\ /
\ /
MYAPP.RC
|
|
RES\MYAPP.RC2
AFXRES.RC
AFXPRINT.RC
Możesz przeglądać takie relacje plików za pomocą polecenia Plik Visual C++/Zestaw zawiera.
- MYAPP.RC
Plik zasobów aplikacji, który edytujesz za pomocą programu Visual C++.
RESOURCE.H to plik nagłówkowy charakterystyczny dla aplikacji.AppWizard zawsze nadaje mu nazwę RESOURCE.H, zgodnie z domyślną nazwą pliku nagłówkowego w Visual C++.Instrukcja #include dla tego pliku nagłówkowego to pierwsza instrukcja w pliku zasobów (MYAPP.RC):
//Microsoft Visual C++ generated resource script
//
#include "resource.h"
- RES\MYAPP.RC2
Zawiera zasoby, które nie będą edytowane przez Visual C++, ale zostaną uwzględnione w ostatecznym skompilowanym pliku .EXE.Kreator AppWizard nie tworzy domyślnie takich zasobów, ponieważ środowisko Visual C++ może edytować wszystkie standardowe zasoby, łącznie z zasobami wersji (nowa funkcja w tym wydaniu).Pusty plik jest generowana przez kreatora AppWizard w przypadku, gdy chcesz dodać swoje własne niestandardowo sformatowane zasoby do tego pliku.
Jeśli używasz zasobów z niestandardowym formatem, możesz je dodać do RES\MYAPP.RC2 i edytować za pomocą edytora tekstu Visual C++.
Pliki AFXRES.RC i AFXPRINT.RC zawierają standardowe zasoby wymagane przez niektóre funkcje środowiska.Podobnie jak RES\MYAPP.RC2, te dwa pliki zasobów dostarczone przez platformę są dołączane dyrektywą #include na końcu MYAPP.RC i są one określone w dyrektywach czasu kompilacji w oknie dialogowym Zestaw zawiera.W ten sposób nie wyświetlasz ani nie edytujesz bezpośrednio tych zasobów platformy podczas edycji MYAPP.RC w programie Visual C++, ale są one wkompilowywane w binarny plik aplikacji .RES i końcowy .EXE.Aby uzyskać więcej informacji na temat standardowych zasobów ram, w tym procedur ich modyfikowania, zobacz Uwaga techniczna 23.
Plik AFXRES.H definiuje standardowe symbole, takie jak ID_FILE_NEW, używane przez architekturę i używane konkretnie w pliku AFXRES.RC.Plik AFXRES.H ma również dyrektywę #include z plikiem WINRES.H, który zawiera podzbiór plików WINDOWS.H, które są wymagane przez pliki .RC generowane przez środowisko Visual C++, jak również plik AFXRES.RC.Symbole zdefiniowane w AFXRES.H są dostępne podczas edycji pliku zasobu aplikacji (MYAPP.RC).Na przykład, ID_FILE_NEW jest używany dla elementu menu Plik Nowy w zasobie menu MYAPP.RC.Nie możesz zmienić ani usunąć tych symboli zdefiniowanych w platformie.
Włączanie dodatkowych plików nagłówkowych
Aplikacja utworzona przez AppWizard zawiera tylko dwa pliki nagłówkowe: RESOURCE.H i AFXRES.H.Tylko RESOURCE.H jest charakterystyczny dla aplikacji.Może być konieczne uwzględnienie dodatkowych plików nagłówkowych tylko do odczytu w następujących przypadkach:
Plik nagłówkowy jest dostarczany z zewnętrznego źródła lub chcesz współdzielić plik nagłówkowy między wieloma projektami lub wieloma częściami tego samego projektu.
Plik nagłówkowy ma formatowanie i komentarze, a nie chcesz, żeby Visual C++ je zmienił lub odfiltrował przy zapisywaniu pliku.Na przykład, być może chcesz zachować wiersze #define używające arytmetyki symbolicznej, takie jak:
#define RED 0
#define BLUE 1
#define GREEN 2
#define ID_COLOR_BUTTON 1001
#define ID_RED_BUTTON (ID_COLOR_BUTTON + RED)
#define ID_BLUE_BUTTON (ID_COLOR_BUTTON + BLUE)
#define ID_GREEN_BUTTON (ID_COLOR_BUTTON + GREEN)
Możesz dołączać dodatkowe pliki nagłówkowe tylko do odczytu za pomocą polecenia Zasób zawiera, aby wyszczególnić instrukcję #include jako drugą dyrektywę symboli tylko do odczytu, tak jak tutaj:
#include "afxres.h"
#include "second.h"
Nowy diagram relacji pliku wygląda teraz następująco:
AFXRES.H
RESOURCE.H SECOND.H
\ /
\ /
MYAPP.RC
|
|
RES\MYAPP.RC2
AFXRES.RC
AFXPRINT.RC
Współdzielenie pliku nagłówkowego przez dwa pliki .RC
Możesz chcieć współdzielić plik nagłówkowy między dwoma plikami .RC, które znajdują się w różnych projektach, lub ewentualnie w tym samym projekcie.Aby to zrobić, po prostu zastosuj opisaną technikę dyrektyw tylko do odczytu w obu plikach .RC.W przypadku gdy dwa pliki .RC są do różnych aplikacji (różnych projektów), wynik jest zilustrowany na poniższym schemacie:
RESOURCE.H AFXRES.H RESOURCE.H
(for MYAPP1) SECOND.H (for MYAPP2)
\ / \ /
\ / \ /
MYAPP1.RC MYAPP2.RC
/ \ / \
/ \ / \
RES\MYAPP1.RC2 AFXRES.RC RES\MYAPP2.RC2
AFXPRINT.RC
Przypadek, w którym drugi plik nagłówkowy jest współdzielony przez dwa pliki .RC w tej samej aplikacji (projekcie), omówiono poniżej.
Korzystanie z wielu plików zasobów w tym samym projekcie
Visual C++ i kompilator zasobów obsługują wiele plików .RC w tym samym projekcie za pośrednictwem dołączania przez #include jednego pliku .RC w innym.Wielokrotne zagnieżdżanie jest dozwolone.Istnieją różne powody, aby podzielić zasoby projektu na wiele plików .RC:
Łatwiej jest zarządzać dużą liczbą zasobów między wieloma członkami zespołu projektu, jeśli podzieli się zasoby na wiele plików .RC.Jeśli używasz pakietu zarządzania kontrolą źródła do wyewidencjonowywania plików i ewidencjonowania zmian, dzielenie zasobów na wiele plików .RC daje lepszą kontrolę nad zarządzaniem zmianami w zasobach.
Jeśli chcesz użyć dyrektyw preprocesora, takich jak #ifdef, #endif i #define, dla części zasobów, musisz odizolować je w zasobach tylko do odczytu, które zostaną skompilowane przez kompilator zasobów.
Pliki .RC składników będą ładowane i zapisywane szybciej w programie Visual C++ niż jeden złożony plik .RC.
Jeśli chcesz obsługiwać zasób za pomocą edytora tekstów w czytelnej formie, powinieneś go przechowywać w pliku .RC oddzielnie od pliku edytowanego przez Visual C++.
Jeśli chcesz utrzymywać zasób zdefiniowany przez użytkownika w postaci binarnej lub tekstowej, interpretowanej przez inny wyspecjalizowany edytor danych, powinieneś go utrzymywać w oddzielnym pliku .RC, aby Visual C++ nie zmienił jego formatu na dane szesnastkowe.Zasoby plików .WAV (dźwięk) w próbce zaawansowanych koncepcji MFC SPEAKN są dobrym przykładem.
Możesz za pośrednictwem #include dołączyć SECOND.RC w dyrektywach czasu kompilacji, w oknie dialogowym Zestaw zawiera:
#include "res\myapp.rc2" // non-Visual C++ edited resources
#include "second.rc" // THE SECOND .RC FILE
#include "afxres.rc" // Standard components
#include "afxprint.rc" // printing/print preview resources
Poniższy diagram ilustruje wynik:
RESOURCE.H AFXRES.H
\ /
\ /
MYAPP.RC
|
|
RES\MYAPP.RC2
SECOND.RC
AFXRES.RC
AFXPRINT.RC
Używając dyrektyw czasu kompilacji, możesz organizować edytowalne i nieedytowalne zasoby Visual C++ w wielu plikach .RC, gdzie "wzorcowy" MYAPP.RC nic nie robi, ale włącza dyrektywą #include inne pliki .RC.Jeśli używasz pliku .MAK projektu Visual C++, powinieneś dołączyć do projektu "główny" (master) plik .RC, tak aby wszytkie zasoby włączane dyrektywą #include były wkompilowane w aplikacji.
Wymuszanie nieedytowalnych plików Visual C++
Utworzony przez AppWizard plik RES\MYAPP.RC2 to przykład pliku zawierającego zasoby, którego nie chcesz wczytać przypadkowo do Visual C++, a następnie zapisać go z powrotem, tracąc informacje o formatowaniu.Aby się przed tym zabezpieczyć, umieść następujące wiersze na początku pliku RES\MYAPP.RC2:
#ifdef APSTUDIO_INVOKED
#error this file is not editable by Visual C++
#endif //APSTUDIO_INVOKED
Gdy Visual C++ kompiluje plik .RC, określa on APSTUDIO_INVOKED jak również RC_INVOKED.Jeśli struktura pliku utworzona przez AppWizard jest uszkodzona i Visual C++ odczytuje wiersz #error znajdujący się wyżej, zgłasza błąd krytyczny i przerywa czytanie pliku .RC.
Zarządzanie symbolami współdzielonymi przez wiele plików .RC edytowanych w Visual C++
Kiedy podzielisz swoje zasoby na wiele plików .RC, które chcesz edytować oddzielnie w programie Visual C++, wystąpią dwa problemy:
Być może chcesz współdzielić te same symbole w wielu plikach .RC.
Musisz pomóc Visual C++, aby unikał przypisywania tych samych wartości numerycznych ID różnym zasobom (symbolom).
Poniższy diagram ilustruje organizację plików .RC i .H, które odpowiadają za pierwszą kwestię:
MYAPP.RC
/ \
/ \
MYSTRS.H / MYSHARED.H \ MYMENUS.H
\ / / \ \ \
\ / / \ \ \
MYSTRS.RC MYMENUS.RC
W tym przykładzie zasoby ciągów są przechowywane w jednym pliku zasobów, MYSTRS.RC, a menu są przechowywane w innym, MYMENUS.RC.Niektóre symbole, takie jak w przypadku poleceń, mogą wymagać, aby współdzielić je między dwoma plikami.Na przykład, ID_TOOLS_SPELL może być identyfikatorem polecenia menu dla elementu Sprawdzanie pisowni w menu Narzędzia; może to być również identyfikator ciągu wiersza poleceń wyświetlany przez szablon na pasku stanu głównego okna aplikacji.
Symbol ID_TOOLS_SPELL jest przechowywany we współdzielonym pliku nagłówkowym, MYSHARED.H.Utrzymujesz ten współdzielony plik nagłówkowy ręcznie za pomocą edytora tekstów; Visual C++ nie edytuje go bezpośrednio.W dwóch plikach zasobów MYSTRS.RC i MYMENUS.RC, definiujesz wiersz #include MYSHARED.H w dyrektywach tylko do odczytu dla MYAPP.RC, za pomocą polecenia Zasób zawiera, w sposób opisany wcześniej.
Najwygodniej jest przewidzieć symbol, który będzie współdzielony, zanim spróbuje się go wykorzystywać do identyfikacji jakiegoś zasobu.Dodaj symbol do udostępnionego pliku nagłówka, a jeśli nie umieszczono jeszcze dyrektywy #include z udostępnionym plikiem nagłówkowym w dyrektywach tylko do odczytu dla pliku .RC, uczyń to przed używaniem symbolu.Jeśli nie przewidujesz współdzielenia symbolu w ten sposób, musisz ręcznie (przy użyciu edytora tekstów) przenieść instrukcję #define dla symbolu z np. MYMENUS.H do MYSHARED.H przed użyciem go w MYSTRS.RC.
Kiedy zarządzasz symbolami w wielu plikach .RC, musisz również pomóc Visual C++ unikać przypisywania tych samych wartości numerycznych ID różnych zasobom (symbolom).Dla każdego pliku .RC, Visual C++ przyrostowo przypisuje identyfikatory w każdej z czterech domen identyfikatorów.Między sesjami edycji program Visual C++ przechowuje informacje o ostatnim identyfikatorze, który przypisał w każdej domenie, w pliku nagłówkowym symboli dla pliku .RC.Oto wartości APS_NEXT dla pustego (nowego) pliku .RC:
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1000
#define _APS_NEXT_SYMED_VALUE 101
_APS_NEXT_RESOURCE_VALUE jest następną wartością symboliczną, która będzie używana dla zasobu okna dialogowego, zasobu menu i tak dalej.Prawidłowy zakres dla wartości symboli zasobu to 1 do 0x6FFF.
_APS_NEXT_COMMAND_VALUE jest następną wartością symboliczną, która będzie używana do identyfikacji polecenia.Prawidłowy zakres dla wartości symboli polecenia to 0x8000 do 0xDFFF.
_APS_NEXT_CONTROL_VALUE jest następną wartością symboliczną, która będzie używana do sterowania oknem dialogowym.Prawidłowy zakres dla wartości symboli formantu dialogu to 8 do 0xDFFF.
_APS_NEXT_SYMED_VALUE jest następną wartością symboliczną, który zostanie wysłana po ręcznym przypisaniu wartości symboliczną za pomocą polecenia Nowy w Przeglądarce symboli.
Visual C++ rozpoczyna z nieco wyższymi wartościami niż najniższa dopuszczalna wartość przy tworzeniu nowego pliku .RC.Kreator AppWizard również zainicjuje te wartości na coś bardziej odpowiedniego dla aplikacji MFC.Aby uzyskać więcej informacji dotyczących zakresów wartości identyfikatora, zobacz Uwagi techniczne 20.
Po każdorazowym utworzeniu nowego pliku zasobu, nawet w tym samym projekcie, Visual C++ definiuje takie same wartości _APS_NEXT_.Oznacza to, że jeśli dodasz, np., wiele okien dialogowych w dwóch różnych plikach .RC, jest wysoce prawdopodobne, że taka sama wartość #define zostanie przypisana do różnych okien dialogowych.Na przykład, IDD_MY_DLG1 w pierwszym pliku .RC może mieć przypisany taki sam numer, 101, jak IDD_MY_DLG2 w drugim pliku .RC.
Aby tego uniknąć, należy zarezerwować oddzielny zakres numeryczny dla każdej z czterech domen identyfikatorów we właściwych plikach .RC.W tym celu ręczne aktualizuj wartości _APS_NEXT w każdym z plików .RC before (zanim) rozpoczniesz dodawanie zasobów.Na przykład, jeśli pierwszy plik .RC używa domyślnych wartości _APS_NEXT, można przypisać następujące wartości _APS_NEXT do drugiego pliku .RC:
#define _APS_NEXT_RESOURCE_VALUE 2000
#define _APS_NEXT_COMMAND_VALUE 42000
#define _APS_NEXT_CONTROL_VALUE 2000
#define _APS_NEXT_SYMED_VALUE 2000
Oczywiście jest nadal możliwe, że Visual C++ przypisze tak wiele identyfikatorów w pierwszym pliku .RC, że wartości numeryczne zaczną się pokrywać z zarezerwowanymi dla drugiego pliku .RC.Powinno się zarezerwować dostatecznie duże zakresy, aby tak się nie stało.
Zarządzanie zależnościami między plikami .RC, .CPP i .H
Kiedy Visual C++ zapisuje plik .RC, zapisuje również zmiany symboli w odpowiednim pliku RESOURCE.H.Każdy plik .CPP, który odwołuje się do zasobów w pliku .RC, musi zawierać dyrektywę #include z plikiem RESOURCE.H, zazwyczaj z głównego pliku nagłówkowego projektu.Prowadzi to do niepożądanych skutków ubocznych ze względu na wewnętrzne zarządzanie projektami środowiska programistycznego, które skanuje pliki źródłowe w poszukiwaniu zależności od plików nagłówkowych.Za każdym razem, gdy dodajesz nowy symbol w programie Visual C++, wszystkie pliki .CPP z wierszem #include RESOURCE.H muszą zostać zrekompilowane.
Visual C++ obchodzi zależność od RESOURCE.H poprzez dołączenie poniższego komentarza jako pierwszego wiersza pliku RESOURCE.H:
//{{NO_DEPENDENCIES}}
Środowisko programistyczne interpretuje ten komentarz, ignorując zmiany w RESOURCE.H, dzięki czemu nie trzeba rekompilować zależnych plików .CPP.
Visual C++ zawsze dodaje wiersz komentarza //{{NO_DEPENDENCIES}} do pliku .RC podczas zapisywania pliku.W niektórych przypadkach obejście zależności kompilacji od RESOURCE.H może prowadzić do błędów czasu wykonywania niewykrytych w czasie linkowania.Na przykład, jeśli używasz przeglądarki symboli, aby zmienić wartość numeryczną przypisaną do określonego symbolu dla zasobu, zasób nie zostanie poprawnie znaleziony i załadowany w przypadku wykonywania aplikacji, jeśli plik .CPP odnoszący się do tego zasobu nie zostanie zrekompilowany.W takich przypadkach należy jawnie zrekompilować wszelkie pliki .CPP, o których wiadomo, że dotyczą ich zmiany symboli w RESOURCE.H, lub wybrać Zrekompiluj wszystkie.Jeśli potrzebujesz często zmieniać wartości symboli dla określonej grupy zasobów, prawdopodobnie wygodniej i bezpieczniej będzie wydzielić te symbole i umieścić je w oddzielnym pliku nagłówkowym tylko do odczytu, jak opisano w powyższej sekcji Dołączanie dodatkowych plików nagłówkowych.
Jak zarządzać zestawami informacji Include w Visual C++
Jak wskazano powyżej, polecenie Zestaw zawiera w menu Plik pozwala określić trzy typy informacji:
Plik nagłówkowy symboli
Dyrektywy symboli tylko do odczytu
Dyrektywy czasu kompilacji
Poniżej przedstawiono, jak Visual C++ przechowuje te informacje w pliku .RC.Nie potrzebujesz tych informacji, aby używać Visual C++, ale to może pomóc w lepszym zrozumieniu zagadnień, tak aby bardziej optymalnie korzystać z funkcji Zestaw zawiera.
Każdy z trzech powyższych rodzajów informacji w funkcji Set Includes jest zapisywany w pliku .RC w dwóch postaciach: (1) jako #include lub inne dyrektywy interpretowane przez kompilator zasobów i (2) jako specjalne zasoby TEXTINCLUDE interpretowane tylko przez Visual C++.
Zasób TEXTINCLUDE służy do bezpiecznego przechowywania informacji o zawartości zestawu w formularzu, który jest gotowy do prezentacji w oknie dialogowym Visual C++ Zestaw zawiera.TEXTINCLUDE to typ zasobu zdefiniowany przez Visual C++.Visual C++ rozpoznaje trzy określone zasoby TEXTINCLUDE, które mają numery identyfikacyjne zasobu 1, 2 i 3:
Identyfikator zasobu TEXTINCLUDE |
Rodzaj informacji Zestaw zawiera |
---|---|
1 |
Plik nagłówkowy symboli |
2 |
Dyrektywy symboli tylko do odczytu |
3 |
Dyrektywy czasu kompilacji |
Każdy z trzech powyższych rodzajów informacji w funkcji Set Includes jest zilustrowany przez domyślne pliki MYAPP.RC i RESOURCE.H utworzone przez AppWizard, jak opisano poniżej.Dodatkowe tokeny \0 i "" pomiędzy blokami BEGIN i END są wymagane przez składnię RC do określania odpowiednio ciągów zakończonych wartością zerową i znaku podwójnego cudzysłowu.
Plik nagłówkowy symboli
Forma informacji o pliku nagłówkowym symboli interpretowana przez kompilator zasobów ma postać po prostu instrukcji #include:
#include "resource.h"
Odpowiedni zasób TEXTINCLUDE to:
1 TEXTINCLUDE DISCARDABLE
BEGIN
"resource.h\0"
END
Dyrektywy symboli tylko do odczytu
Dyrektywy symbolu tylko do odczytu są uwzględniane w górnej części MYAPP.RC w następującej formie interpretowanej przez kompilator zasobów:
#include "afxres.h"
Odpowiedni zasób TEXTINCLUDE to:
2 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
Dyrektywy czasu kompilacji
Dyrektywy czasu kompilowania są umieszczane na końcu pliku MYAPP.RC w następującej formie interpretowanej przez kompilator zasobów:
#ifndef APSTUDIO_INVOKED
///////////////////////
//
// From TEXTINCLUDE 3
//
#include "res\myapp.rc2" // non-Visual C++ edited resources
#include "afxres.rc" // Standard components
#include "afxprint.rc" // printing/print preview resources
#endif // not APSTUDIO_INVOKED
Dyrektywa #ifndef APSTUDIO_INVOKED nakazuje językowi Visual C++ pominąć dyrektywy czasu kompilacji.
Odpowiedni zasób TEXTINCLUDE to:
3 TEXTINCLUDE DISCARDABLE
BEGIN
"#include ""res\myapp.rc2"" // non-Visual C++ edited resources\r\n"
"\r\n"
"#include ""afxres.rc"" // Standard components\r\n"
"#include ""afxprint.rc"" // printing/print preview resources\r\n"
"\0"
END