Icons

Icons sind Symbole die unter anderem bei der Darstellung einer Anwendung im Explorer oder auch oben links in der Titelzeile eines Fensters verwendet werden. Icons können aber auch als grafische Elemente in Fenstern und Dialogboxen eingesetzt werden. Sie können eine (fast) beliebige Größe annehmen. Standardgrößen für Icons sind 16x16 Pixel (small icon) und 32x32 Pixel (standard icon). Soll ein Icon als Fenstersymbol verwendet werden, so muss es zumindest in der Größe 32x32 Pixel vorhanden sein. Das kleine Icon (16x16) wird u.a. für die Darstellung in der Titelzeile eingesetzt. Außerdem wird es angezeigt wenn im Explorer die Darstellung 'kleine Symbole' verwendet wird. Die Farbtiefe für Icons kann 2, 16 oder 256 Farben betragen.

Viele der in diesem Kapitel behandelten Ressourcen lassen sich entweder aus einer zum Programm gelinkten Ressource oder aus einer separaten Datei (z.B. ICO-Datei für Icons) laden. Versuchen Sie aber trotzdem soweit wie möglich Ihre Ressourcen in einer Ressource-Datei unterzubringen. Sie brauchen dann bei der Weitergabe Ihrer Anwendung nur die EXE/DLL-Datei weitergeben und nicht noch zusätzliche Ressource-Dateien.

Und gehen wir jetzt auch gleich wieder zur Praxis über.

Erstellen Sie nun zunächst, wie gewohnt, ein SDI-Rahmenprogramm mit Hilfe des Anwendungs-Assistenten. Geben Sie dem Projekt den Namen 'Icons'. Nach dem das Rahmenprogramm erstellt wurde, werden wir uns nun die Handhabung des Icon-Editors einmal kurz ansehen.

Klicken Sie im Arbeitsbereich einmal auf den Tabellenreiter Ressourcen. Sie erhalten dann in Baumdarstellung alle vom Anwendungs-Assistenten erstellten Ressourcen aufgelistet. Öffnen Sie nun die Icon-Ressourcen durch einen Doppelklick auf den Ordner Icon. Daraufhin werden alle im Projekt verwendeten Icon-IDs aufgelistet. Um ein bestimmtes Icon im Icon-Editor zu öffnen, führen Sie erneut einen Doppelklick auf die ID des gewünschten Icons aus. Im Beispiel unten wurde das Icon IDR_MAINFRAME im Editor geöffnet.

Der Icon-Editor

Das Icon mit der ID IDR_MAINFRAME wird zur Darstellung der Anwendung im Explorer verwendet wenn Sie unter Ansicht die Option 'Große Symbole' eingestellt haben. Doch wo ist das kleine Icon, das z.B. in der Titelleiste darstellt wird? Klicken Sie einmal auf den Pfeil im Auswahlfeld Gerät, oberhalb des Icon-Editors. Im aufgeklappten Auswahlfeld erscheint der Eintrag 'Klein (16x16)'. Klicken Sie diesen Eintrag an und das kleine Icon wird im Icon-Editor dargestellt. Wie Sie sehen, können sich unter einer ID mehrere Icons mit unterschiedlichen Auflösungen befinden. Wie innerhalb einer Anwendung verschiedene Icons mit der gleichen ID auswählt werden, das erfahren Sie später.

Um nun zu sehen, dass dies wirklich zwei verschiedene Icons sind, füllen Sie die Rechtecke über den Buchstaben MFC beim kleinen Icon einmal mit der Farbe gelb und beim großen Icon mit der Farbe rot aus. Übersetzen Sie das Programm und starten Sie es. In der Titelzeile wird das kleine Icon (mit gelb ausgefüllten Rechtecken) dargestellt werden. Rufen Sie anschließend den Explorer auf und gehen Sie in das Verzeichnis, in dem die EXE-Datei des Beispiels abgelegt ist. Je nach dem, ob Sie die Ansicht auf 'Große Symbole' eingestellt haben oder nicht, wird das das Icon mit den roten oder mit den gelben Rechtecken dargestellt werden.

Und noch ein Hinweis zum Schluss dieser kleinen Demonstration. Icons besitzen transparente und inverse Bereiche. Transparente Bereiche werden bei der Darstellung des Icons nicht gezeichnet, d.h. der Hintergrund bleibt erhalten. Die inversen Bereiche verwenden zur Darstellung der aktuellen Iconfarbe die invertierte Farbe des Hintergrunds. Um einen bestimmten Bereich innerhalb eines Icons als transparenten bzw. inversen Bereich zu kennzeichnen, klicken Sie das entsprechende Symbol lt. nachfolgendem Bild in der Farbauswahl an. Sie können die zur Darstellung der Bereiche im Icon-Editor verwendeten Farben ändern, in dem Sie einen Doppelklick auf die Symbole durchführen.

Transparente und inverse Bereiche

Sehen wir uns jetzt die verschiedenen Icon-Arten an. WINDOWS kennt im Prinzip drei verschiedene Arten von Icons:

  • System-Icon: vordefinierte Icons z.B. für die Darstellung innerhalb von Messageboxen.
  • Shell-Icon: vordefinierte Icons für Laufwerke, Verzeichnisse usw.
  • Anwender-Icon: vom Anwender mittels Icon-Editor erstellte Icons.

Bevor eines dieser Icon dargestellt werden kann, muss es zunächst geladen werden. Und je nach Icon-Typ sind hierfür verschiedene Methoden/Funktionen einzusetzen.

Um ein System-Icon zu laden muss die CWinApp-Methode LoadStandardIcon(...) aufgerufen werden. Diese Methode erhält als Parameter die ID des zu ladenden Icons laut nachfolgender Tabelle:

ID

Icon

ID

Icon

IDI_APPLICATION IDI_ERROR
IDI_INFORMATION IDI_QUESTION
IDI_WARNING IDI_WINLOGO

Als Returnwert liefert LoadStandardIcon(...) ein Handle HICON auf das geladene Icon. Um dieses Icon darzustellen wird die CDC-Methode DrawIcon(...) aufgerufen, die als Parameter das vorhin ermittelte Handle des Icons erhält.

Erweitern wir das Beispiel nun um die Darstellung der System-Icons.

Damit die transparenten Bereiche der Icons besser ersichtlich werden, füllen wir den Hintergrund des Fensters mit einem Farbverlauf aus. Fügen Sie dazu der Klasse CIconsView über den Klassen-Assistenten die Nachrichten-Methode OnEreaseBkgnd(...) hinzu. Modifizieren Sie den Code der Methode wie folgt. Beachten Sie bitte, dass der Aufruf der Basisklassen-Methode entfernt wurde.
BOOL CIconsView::OnEraseBkgnd(CDC* pDC)
{
    // TODO: Code für die Behandlungsroutine für Nachrichten hier einfügen ...

    // Fuelle Hintergrund aus
    CRect CClientRect;
    GetClientRect(&CClientRect);

    // Farbverlauf initialisieren
    int nDirection = 1;
    COLORREF ActColor = 0x000080FF;
    // Fensterhintergrund mit Muster versehen
    for (int nLoop=0; nLoop<(CClientRect.right>>2); nLoop++)
    {
        pDC->FillSolidRect(0,(nLoop<<2),CClientRect.right,7,ActColor);
        ActColor += 0x00001000*nDirection;
        if (ActColor == 0x0000F0FF)
            nDirection = -1;
        if (ActColor == 0x000080FF)
            nDirection = 1;
    }
    return TRUE;
}

So, und nun sind Sie wieder daran. Versuchen Sie einmal alle System-Icons innerhalb einer Zeile darzustellen. Das Laden der Icons erfolgt sinnvollerweise nur einmal, und zwar beim Initialisieren des Ansichtsobjekts. Fügen Sie daher der Klasse CIconsView die virtuelle Methode OnInitialUpdate(...) sowie die Membervariable HICON m_ahSysIcon[6] hinzu um die Icon-Handles abzuspeichern. Geben Sie der Zeile mit den Icons die Überschrift "System-Icons".

Lösung zur Darstellung der System-Icons

Zuerst werden in der OnInitialUpdate(...) Methode die System-Icons mittels LoadStandardIcon(...) geladen.

void CIconsView::OnInitialUpdate()
{
    CView::OnInitialUpdate();
   
    // TODO: Speziellen Code hier einfügen und/oder Basisklasse aufrufen
    // Standard-Icons laden
    static const char* m_acSYSICONS[] = {IDI_APPLICATION,IDI_INFORMATION,
                                         IDI_WARNING,IDI_ERROR,
                                         IDI_QUESTION,IDI_WINLOGO};
    for (int iLoop=0; iLoop<sizeof(m_ahSysIcon)/sizeof(HICON); iLoop++)
        m_ahSysIcon[iLoop]= AfxGetApp()->LoadStandardIcon(m_acSYSICONS[iLoop]);   
}

Haben Sie auch beachtet, dass LoadStandardIcon(...) eine Methode von CWinApp ist? Den Zeiger auf das aktuelle CWinApp Objekt erhalten Sie durch den Aufruf der Funktion AfxGetApp(...).

Wurden die Icons geladen, so können sie schließlich mittels DrawIcon(...) dargestellt werden. Sie fragen sich: wo? Dort wo alle Ausgaben in der Regel erfolgen, in der OnDraw(...) Methode natürlich.

void CIconsView::OnDraw(CDC* pDC)
{
    CIconsDoc* pDoc = GetDocument();
    ASSERT_VALID(pDoc);
    // ZU ERLEDIGEN: Hier Code zum Zeichnen der ursprünglichen Daten hinzufügen

    // Textausgabe initialisieren
    pDC->SetBkMode(TRANSPARENT);
    pDC->SelectStockObject(SYSTEM_FONT);
    pDC->SetTextColor(RGB(0,0,0));

    // System-Icons zeichnen
    pDC->TextOut(10,10,"System-Icons");
    for (int iLoop=0; iLoop<sizeof(m_ahSysIcon)/sizeof(HICON); iLoop++)
        pDC->DrawIcon(iLoop*40+10,30,m_ahSysIcon[iLoop]);
}

War doch nicht besonders schwierig, oder?

Ende der Lösung

Wenn Sie alles richtig eingegeben haben, dann sollten Sie in etwa folgende Ausgabe erhalten:

Die System-Icons

So weit, so gut. Sehen wir uns nun an, wie Shell-Icons (z.B. Laufwerks- oder Drucker-Icons) dargestellt werden. Auch diese Icons müssen zuerst geladen werden. Leider kann hierfür nicht die Methode LoadStandardIcon(...) verwendet werden. Um Shell-Icons zu laden muss die API-Funktion SHGetFileInfo(...) aufgerufen werden. Da die Bedeutung der Funktionsparameter vielleicht aus der Online-Hilfe nicht gleich ersichtlich ist, wollen wir uns hier einmal wieder das Prototyping der Funktion ansehen:

WINSHELLAPI DWORD WINAPI SHGetFileInfo( LPCTSTR pszPath, DWORD dwFileAttributes,
                                        SHFILEINFO FAR *psfi, UINT cbFileInfo,
                                        UINT uFlags );

Mit Hilfe dieser Funktion können Sie vielseitige Informationen über ein Shell-Objekt (wie z.B. einem Verzeichnis oder einem Laufwerk) abfragen. Wir werden hier aber nur den Fall betrachten, dass ein entsprechendes Shell-Icon geladen werden soll. Dazu setzen Sie den Parameter pszPath auf einen String der den Pfad enthält, dessen Icon geladen werden soll. Soll z.B. das Laufwerks-Icon für das Laufwerk C: geladen werden, so ist pszPath auf   "C:\\" zu setzen. Beachten Sie bitte die doppelten Backslash im Pfad! Genauso leicht lässt sich aber auch das Shell-Icon für ein Verzeichnisse laden. Setzen Sie dazu pszPath einfach auf das gewünschte Verzeichnis, z.B. "C:\\WINDOWS". Der nächste Parameter dwFileAttributes wird zum Laden von Icons nicht benötigt und sollte mit '0UL' belegt werden. psfi ist ein Zeiger auf eine Struktur vom Typ SHFILEINFO. Diese Struktur wird durch die Funktion mit den angeforderten Informationen ausgefüllt und besitzt folgenden Aufbau:

typedef struct _SHFILEINFO{
    HICON hIcon;
    int iIcon;
    DWORD dwAttributes;
    char szDisplayName[MAX_PATH];
    char szTypeName[80];
} SHFILEINFO;

In unserem Fall, dem Auslesen von Shell-Icons, ist nur der Inhalt des Elements hIcon relevant. Es enthält nach dem Aufruf der Funktion das Handle des geladenen Shell-Icon. Der nächste Parameter der Funktion SHGetFileInfo(...), cbFileInfo, enthält die Größe der Struktur SHFILEINFO in Bytes. Und der letzte Parameter uFlags steuert unter anderem, welches Icon geladen werden soll. Wie Sie bereits erfahren haben, können unter einer ID Icons mit verschiedenen Größen abgespeichert sein. Folgende Flags können u.a. beim Laden eines Shell-Icons für uFlags gesetzt werden:

Flag

Bedeutung

SHGFI_ICON Laden eines Shell-Icons; dieses Flag muss immer gesetzt sein!
SHGFI_LARGEICON Lädt das große Icon, Auflösung 32x32; Standard-Einstellung!
SHGFI_OPENICON Lädt das Icon, das einem geöffnetem Objekt (z.B. Verzeichnis) entspricht.
SHGFI_SMALLICON Lädt das kleine Icon, Auflösung 16x16.
SHGFI_PIDL Pfadangabe pszPath enthält einen Zeiger auf eine ITEMIDLIST
Struktur (siehe weiter unten).

Die so erhaltenen Icons müssen nun 'nur' noch ausgegeben werden. Leider geht dies nicht mit der vorhin aufgeführten CDC-Methode DrawIcon(...). DrawIcon(...) ist nur in der Lage Icons mit der Standardauflösung von 32x32 darzustellen. Kleine Icons (Auflösung 16x16) werden bei der Ausgabe entsprechend vergrößert. Sollen auch die kleinen Icons richtig dargestellt werden, so muss dazu die API-Funktion DrawIconEx(...) verwendet werden. Für die Ausgabe von Icons sind nur die Parameter hDC, xLeft, yTop, hIcon und diFlags der Funktion relevant. Die Bedeutung der ersten 4 Parameter dürfte aus ihrem Namen hervorgehen. Für den Parameter diFlags setzen Sie standardmäßig die Konstante DI_NORMAL ein.

Wird das mittels SHGetFileInfo(...) erhaltene Icon nicht mehr benötigt, muss es mittels DestroyIcon(...) entfernt werden.

So, und nun sind Sie wieder daran. Versuchen Sie einmal folgende Shell-Icon zu laden:
  • das kleine und große Laufwerk-Icon des Laufwerks C:
  • das kleine Laufwerk-Icon Ihres CD-ROM Laufwerks
  • das kleine Icon und das Icon für ein geöffnetes Verzeichnis des Verzeichnisses C:\WINDOWS

Alle Shell-Icons sind innerhalb einer Zeile darzustellen. Das Laden der Icon erfolgt auch hier sinnvollerweise wieder in der OnInitialUpdate(...) Methode des Ansichtsobjekts. Fügen Sie zur Klasse CIconsView die Membervariable HICON m_ahShellIcon[12] hinzu um die Icon-Handles abzuspeichern. Geben Sie den einzelnen Icon-Gruppen die Überschriften Laufwerk, CD-ROM und Verzeichnisse. Denken Sie daran, dass Sie die geladenen Icons jetzt mit Hilfe der Funktion DrawIconEx(...) darstellen und die Icons am Ende des Programms auch wieder entfernen müssen.

Lösung zur Darstellung der Shell-Icons

Zuerst werden in der OnInitialUpdate(...) Methode die Shell-Icons geladen.

void CIconsView::OnInitialUpdate()
{
    ....
    for (int iLoop=0; iLoop<sizeof(m_ahSysIcon)/sizeof(HICON); iLoop++)
        m_ahSysIcon[iLoop]= AfxGetApp()->LoadStandardIcon(m_acSYSICONS[iLoop]);
    // Shell-Icons laden
    SHFILEINFO FileInfo;
    // Lesen der Laufwerks-Icon
    ::SHGetFileInfo("C:\\",0UL,&FileInfo,sizeof(FileInfo),SHGFI_ICON);
    m_ahShellIcon[0] = FileInfo.hIcon;
    ::SHGetFileInfo("C:\\",0UL,&FileInfo,sizeof(FileInfo),
                    SHGFI_ICON|SHGFI_SMALLICON);
    m_ahShellIcon[1] = FileInfo.hIcon;
    // Lesen der CDROM-Icons, Laufwerksbuchstaben eventl. anpassen!
    ::SHGetFileInfo("E:\\",0UL,&FileInfo,sizeof(FileInfo),SHGFI_ICON);
                    m_ahShellIcon[2] = FileInfo.hIcon;
    ::SHGetFileInfo("E:\\",0UL,&FileInfo,sizeof(FileInfo),
                    SHGFI_ICON|SHGFI_SMALLICON);
    m_ahShellIcon[3] = FileInfo.hIcon;
    // Lesen der Folder-Icons
    ::SHGetFileInfo("C:\\WINDOWS",0UL,&FileInfo,sizeof(FileInfo),
                    SHGFI_ICON|SHGFI_OPENICON);
    m_ahShellIcon[4] = FileInfo.hIcon;
    ::SHGetFileInfo("C:\\WINDOWS",0UL,&FileInfo,sizeof(FileInfo),
                    SHGFI_ICON|SHGFI_SMALLICON);
    m_ahShellIcon[5] = FileInfo.hIcon;
}
void CIconsView::OnDestroy()
{
    CView::OnDestroy();

    // TODO: Code für die Behandlungsroutine für Nachrichten hier einfügen
    // System-Icons entfernen
    for (int iIndex=0; iIndex<6; iIndex++)
        DestroyIcon(m_ahShellIcon[iIndex]);
}

Haben Sie auch immer schön das Backslash-Zeichen innerhalb der Pfadangabe verdoppelt?

Wurden die Icons geladen, so können sie schließlich mittels DrawIconEx(...) dargestellt werden.

void CIconsView::OnDraw(CDC* pDC)
{
    ....
    // System-Icons zeichnen
    ....
    // Laufwerk-Icons zeichnen
    pDC->TextOut(10,90,"Laufwerk");
    ::DrawIconEx(*pDC,10,110,m_ahShellIcon[0],0,0,0,NULL,DI_NORMAL);
    ::DrawIconEx(*pDC,50,110,m_ahShellIcon[1],0,0,0,NULL,DI_NORMAL);
    // CDROM-Icons zeichnen
    pDC->TextOut(100,90,"CD-ROM");
    ::DrawIconEx(*pDC,100,110,m_ahShellIcon[2],0,0,0,NULL,DI_NORMAL);
    ::DrawIconEx(*pDC,140,110,m_ahShellIcon[3],0,0,0,NULL,DI_NORMAL);
    // Folder-Icons zeichnen
    pDC->TextOut(190,90,"Verzeichnisse");
    ::DrawIconEx(*pDC,190,110,m_ahShellIcon[4],0,0,0,NULL,DI_NORMAL);
    ::DrawIconEx(*pDC,230,110,m_ahShellIcon[5],0,0,0,NULL,DI_NORMAL);
}

War doch nicht besonders schwierig, oder?

Ende der Lösung

Wenn Sie alles richtig eingegeben haben, sollten Sie in etwa folgende Ausgabe erhalten:

Die Shell-Icons

Damit sind wir nun in der Lage, Shell-Icons darzustellen die sich mit Laufwerken und Verzeichnissen befassen. Doch das ist noch nicht alles was uns die Funktion SHGetFileInfo(...) bietet. Mit Hilfe dieser Funktion können auch Icons geladen werden die sich auf Systemobjekte wie z.B. dem Papierkorb (Recycle bin) oder auf Drucker beziehen. Dazu muss jedoch zuvor die API-Funktion SHGetSpecialFolderLocation(...) aufgerufen werden, um einen Zeiger auf das gewünschte Objekt zu erhalten. Diese Funktion erhält u.a. einen Zeiger auf einen Zeiger auf eine Struktur (tolle Konstruktion!) vom Typ ITEMIDLIST. In dieser Struktur befindet sich nach dem Ausführen der Funktion die gewünschte Information über das Objekt. Der genaue Aufbau der Struktur braucht uns hier nicht zu interessieren. Wir geben den erhaltenen Zeiger auf diese Struktur einfach direkt weiter an die vorhin erwähnte Funktion SHGetFileInfo(...). Beachten Sie nun bitte, dass im Parameter uFlags der Funktion SHGetFileInfo(...) zusätzlich das Flag SHIGFI_PIDL jetzt gesetzt sein muss.

Wenn Sie die Funktion SHGetSpecialFolderLocation(...) einsetzen, müssen Sie explizit die Header-Datei shlobj.h einbinden!
Erweitern wir das Beispiel wieder um die Ausgabe der Icons für Drucker, den Papierkorb und das Netzwerk. Dazu muss zunächst in der Methode OnInitialUpdate(...) das entsprechende Icon mit den erwähnten Funktionen geladen werden. Beachten Sie bitte, dass Sie unbedingt die Header-Datei shlobh.h explizit noch einbinden müssen (im Beispiel unten nicht dargestellt), ansonsten erhalten Sie beim Übersetzen eine Fehlermeldung!

Korrigieren Sie ebenfalls die Schleife zum Löschen der Icons in der Methode OnDestroy(...).

void CIconsView::OnInitialUpdate()
{
    ....
    m_ahShellIcon[5] = FileInfo.hIcon;

    // Lesen der Systemobjekt-Icons
    LPITEMIDLIST ItemIdList;
    // Drucker-Icon
    SHGetSpecialFolderLocation(*this,CSIDL_PRINTERS,&ItemIdList);
    ::SHGetFileInfo((LPCSTR)ItemIdList,0UL,&FileInfo,
                    sizeof(FileInfo),SHGFI_ICON|SHGFI_PIDL);
    m_ahShellIcon[6] = FileInfo.hIcon;
    ::SHGetFileInfo((LPCSTR)ItemIdList,0UL,&FileInfo, sizeof(FileInfo),
                    SHGFI_ICON|SHGFI_PIDL|SHGFI_SMALLICON);
    m_ahShellIcon[7] = FileInfo.hIcon;
    // Recycle Bin Icon, Icon wird autom. angepasst (Bin leer/gefuellt)
    SHGetSpecialFolderLocation(*this,CSIDL_BITBUCKET,&ItemIdList);
    ::SHGetFileInfo((LPCSTR)ItemIdList,0UL,&FileInfo, sizeof(FileInfo),
                    SHGFI_ICON|SHGFI_PIDL);
    m_ahShellIcon[8] = FileInfo.hIcon;
    ::SHGetFileInfo((LPCSTR)ItemIdList,0UL,&FileInfo, sizeof(FileInfo),
                    SHGFI_ICON|SHGFI_PIDL|SHGFI_SMALLICON);
    m_ahShellIcon[9] = FileInfo.hIcon;
    // Netzwerk-Icon
    SHGetSpecialFolderLocation(*this,CSIDL_NETWORK,&ItemIdList);
    ::SHGetFileInfo((LPCSTR)ItemIdList,0UL,&FileInfo,
                    sizeof(FileInfo),SHGFI_ICON|SHGFI_PIDL);
    m_ahShellIcon[10] = FileInfo.hIcon;
}
void CIconsView::OnDestroy()
{
    CView::OnDestroy();

    // TODO: Code für die Behandlungsroutine für Nachrichten hier einfügen
    // System-Icons entfernen
    for (int iIndex=0; iIndex<11; iIndex++)
        DestroyIcon(m_ahShellIcon[iIndex]);
}

Die Darstellung der geladenen Icons erfolgt in der OnDraw(...) Methode wiederum mittels der vorhin eingeführten API-Funktion DrawIconEx(...):

void CIconsView::OnDraw(CDC* pDC)
{
    ....
    // Folder-Icons zeichnen
    ....
    // Drucker-Icons zeichnen
    pDC->TextOut(10,170,"Drucker");
    ::DrawIconEx(*pDC,10,190,m_ahShellIcon[6],0,0,0,NULL,DI_NORMAL);
    ::DrawIconEx(*pDC,50,190,m_ahShellIcon[7],0,0,0,NULL,DI_NORMAL);
    // CDROM-Icons zeichnen
    pDC->TextOut(100,170,"Papierkorb");
    ::DrawIconEx(*pDC,100,190,m_ahShellIcon[8],0,0,0,NULL,DI_NORMAL);
    ::DrawIconEx(*pDC,140,190,m_ahShellIcon[9],0,0,0,NULL,DI_NORMAL);
    // Netzwerk-Icon zeichnen
    pDC->TextOut(190,170,"Netzwerk");
    ::DrawIconEx(*pDC,190,190,m_ahShellIcon[10],0,0,0,NULL,DI_NORMAL);
}

Wenn Sie alles richtig eingegeben haben, so sollten Sie folgende Icons zusätzlich erhalten:

Icons der Systemobjekte

Sie sehen, so einfach Icons Ihnen am Anfang vielleicht erschien sind, so vielfältig sind sie in der Praxis.

Haben wir bisher nur vom System vorgegebene Icons dargestellt, so wird es nun Zeit, selbst Icons zu entwerfen und auch darzustellen.

Wechseln Sie dazu zunächst zur Ressourcen-Ansicht im Arbeitsbereich. Klicken Sie dann in der Baumansicht den Ressource-Typ Icon mit der rechten Maustaste an. Daraufhin wird ein Kontext-Menü eingeblendet. Sie können durch Auswahl des Menüpunkts Icon einfügen nun selbst ein neues Icon erstellen oder, wenn Sie genauso wie der Autor grafisch weniger begabt sind, ein bestehendes Icon importieren. Wählen Sie dazu den Menüpunkt Importieren... aus. Im Verzeichnis 99Templates befindet sich die Icon-Datei MyIcon.ico die Sie hier z.B. importieren können. Dieses Icon wird dann im Icon-Editor mit der Standard-Auflösung 32x32 dargestellt. Zusätzlich enthält dieses Icon auch noch eine Darstellung für die Auflösung 16x16. Sie können sich diese Darstellung ansehen, in dem Sie im Auswahlfeld Gerät (oberhalb des Editorfensters) die entsprechende Auflösung auswählen.
Wollen Sie ein eigenes Icon entwerfen, so wird im Icon-Editor zunächst das Icon mit der Standard-Auflösung 32x32 dargestellt. Um auch ein kleines Icon mit der Auflösung 16x16 zu erstellen, klicken Sie bitte den Button neben dem Auswahlfeld Gerät an. Danach wird folgender Dialog eingeblendet:

Auswahl der Icongröße

Wählen Sie dort unter Zielgerät den Eintrag Klein (16x16) aus um ein kleines Icon zu erstellen.

Haben Sie das Icon erstellt bzw. importiert, so besitzt es standardmäßig die ID IDI_ICONx. Um diese nicht gerade aussagekräftige ID zu ändern, klicken Sie die ID in der Baumansicht mit der rechten Maustaste an und wählen im dann eingeblendeten Kontext-Menü den Eintrag Eigenschaften aus. Danach wird folgender Dialog eingeblendet:

Eigenschaften eines Icons

Überschreiben Sie die (markierte) ID IDI_ICON1 mit IDI_USER um dem Icon diese ID für das Beispiel zuzuweisen.

Es hat sich als Quasi-Standard eingebürgert, IDs für Icons immer mit IDI_xxx beginnen zu lassen

Damit haben Sie Ihr erstes Icon erstellt bzw. kopiert. Später im Kurs, bei den Tipps&Tricks, werden wir nochmals auf die Erstellung von Icons zurückkommen. Was uns zum Schluss jetzt nur noch fehlt, ist das Laden und Anzeigen unseres Icons. Außerdem werden wir im Beispiel noch ein Icon einer WINDOWS-Anwendung, das des NOTEPAD, laden und anzeigen.

Vervollständigen wir das Beispiel noch. Als erstes laden wir die gewünschten Icons wiederum in der Methode OnInitialUpdate(...).
void CIconsView::OnInitialUpdate()
{
    // Netzwerk-Icon
    ....

    // Grosses Icon aus Ressource laden
    m_hUserLarge = AfxGetApp()->LoadIcon(IDI_USER);
    // Kleines Icon aus Ressource laden
    // Beachten Sie die Groessenangaben beim Aufruf!
    m_hUserSmall = (HICON)::LoadImage(AfxGetInstanceHandle(),
                                      MAKEINTRESOURCE(IDI_USER),
                                      IMAGE_ICON, 16,16, LR_DEFAULTCOLOR);
    // Lesen eines Applikations-Icons (hier NOTEPAD-Icon)
    // Eventl. muessen Sie hier den Pfad noch anpassen!
    ::SHGetFileInfo("C:\\WINDOWS\\NOTEPAD.EXE",
                    0UL, &FileInfo,sizeof(FileInfo),SHGFI_ICON);
    m_hAppLarge = FileInfo.hIcon;
}

Anschließend fügen Sie der Klasse CIconsView auch noch die drei Membervariablen m_hUserLarge, m_hUserSmall und m_hAppLarge, alle vom Typ HICON, hinzu.

Beachten Sie im Beispiel oben bitte, dass Ressource-Icons, die von der Standard-Auflösung 32x32 abweichen, immer mit der API-Funktion LoadImage(...) geladen werden müssen. Außerdem ist hier in der Regel die Auflösung des zu ladenden Icons anzugeben.

Zum Schluss werden die geladenen Icons noch in der OnDraw(...) Methode ausgegeben.

void CIconsView::OnDraw(CDC* pDC)
{
    ....
    // Netzwerk-Icon zeichnen
    ....
    // Grosses Ressource-Icon zeichnen
    pDC->TextOut(10,250,"Ressourcen");
    pDC->DrawIcon(10,270,m_hUserLarge);
    // Kleines Ressource-Icon zeichnen
    ::DrawIconEx(*pDC,50,270,m_hUserSmall,0,0,0,NULL,DI_NORMAL);
    // NOTEPAD-Icon zeichen
    pDC->TextOut(100,250,"NOTEPAD");
    pDC->DrawIcon(100,270,m_hAppLarge);
}

Damit sollten Sie nun folgende Icons zusätzlich angezeigt bekommen:

Eigene und Anwendungs-Icons

Und wird sind damit auch fertig. Das fertige Beispiel finden Sie auch unter 07Ressourcen\Icons.

Beenden wir diese Lektion über Icon-Ressourcen und sehen uns in der nächsten Lektion die Cursor-Ressource an.



Copyright © 2004

Senden Sie Emails mit Fragen oder Kommentaren zu dieser Website an: mailto:info@cpp-tutor.de
 Wolfgang Schröder, Lerchenweg 23, D-72805 Lichtenstein. Tel: +49 7129 6470