Programmieren mit C++

Visual C++

Oberflächen

Animierte Symbole in der Statusleiste

Wie können Symbole in der Statuszeile von Windows animiert werden?

Frage

Um ein Symbol in der Statuszeile zu animieren, sind mehrere Schritte notwendig, die im folgenden Beispiel gezeigt werden. Der Lösungsvorschlag zeigt dabei,

  • wie das Symbol animiert werden kann,
  • wie die zugehörigen Tooltips für die Anzeige von variierenden Statusinformationen nutzbar sind und
  • wie auch das Handling der linken und rechten Maustaste berücksichtigt wird.

Schritt 1: Daten definieren

Im ersten Schritt sind die Daten für die Animation zu definieren. Die Arrays werden dabei so organisiert, daß die verschiedenen Symbole mit den unterschiedlichen Tooltips über den gleichen Index adressiert werden können.

Eine Animation im Symbol wird hier durch das Austauschen des Symbols gegen ein anderes erreicht. Für jeden Zustand der Animation muß ein eigenes Symbol entworfen werden. Die entsprechenden Ressourcen-IDs werden in einem Array zusammengefaßt, dessen Größe durch NUM_ICONS_IN_ANIMATION definiert wird.

#define NUM_ICONS_IN_ANIMATION 5
 
static int iconResourceArray[NUM_ICONS_IN_ANIMATION] =  { 
    IDI_ICON1, IDI_ICON2, IDI_ICON3, IDI_ICON4, IDI_ICON5 };

Die zugehörigen Texte für die Tooltips stehen in strToolTipArray.

static CString strToolTipArray[NUM_ICONS_IN_ANIMATION] = 
{ 
 CString("Ressourcenbedarf = 20%") ,
 CString("Ressourcenbedarf = 40%") ,
 CString("Ressourcenbedarf = 60%") ,
 CString("Ressourcenbedarf = 80%"),
 CString("Ressourcenbedarf = 100%") }; 

Für das hier aufgezeigte Beispiel wird ein Ressourcen-Monitor angenommen, der fünf Zustände kennt, die durch die entsprechenden gerundeten Prozentzahlen in Klartext umgewandelt werden. Es ginge natürlich auch komfortabler durch flexible Stringumwandlung, aber hier soll ja gerade der andere Weg aufgezeigt werden. Schließlich ist noch eine benutzerdefinierte Windows-Nachricht zu deklarieren.

#define MYMSG_NOTIFYICON (WM_USER + 100)

Schritt 2: Hilfsfunktion hinzufügen

Die nachfolgende Hilfsfunktion bildet eine Hülle um den Shell_NotifyIcon()-Aufruf. Der erste Parameter spezifiziert, ob das Icon neu hinzugefügt, gelöscht oder modifiziert werden soll. Die entsprechenden konstanten lauten:

  • NIM_ADD
  • NIM_DELETE
  • NIM_MODIFY

Der zweite Parameter übergibt den Index in die Arrays der Symbole, die zuvor definiert wurden, während der dritte Parameter den Tooltip-String spezifiziert.

Lösung

void CShellAnimDlg:: InstallAnimatedIcon (
    DWORD dwMsgType,
    UINT nIndexOfIcon, 
    CString strToolTip)

Im ersten Schritt lädt die Methode das erforderliche Symbol aus dem Array.

{
  HICON hIconAtIndex = AfxGetApp()->LoadIcon(
                                iconResourceArray[nIndexOfIcon]);

Als nächstes ist die NOTIFYICONDATA-Struktur zu initialisieren. Zu setzen sind in hWnd das Fensterhandle und in uID der Identifier des Symbols. In uFlags werden drei Standardflags zugewiesen, die neben dem Symbol und dem Tooltip auch die benutzerdefinierte Nachricht anzeigen, deren Wert in uCallbackMessage steht. Das Handle des Symbols steht schließlich in hIcon.

 NOTIFYICONDATA iconData;
 iconData.cbSize  = sizeof(NOTIFYICONDATA);
 iconData.hWnd  = GetSafeHwnd();
 iconData.uID   = 100 ;
 iconData.uFlags  = NIF_MESSAGE|NIF_ICON|NIF_TIP;
 iconData.uCallbackMessage = MYMSG_NOTIFYICON;
 iconData.hIcon  = hIconAtIndex; 

Der Tooltip wird wie folgt behandelt:

 LPCTSTR lpszToolTip = strToolTip.GetBuffer(
                                          strToolTip.GetLength());
 lstrcpyn(iconData.szTip,lpszToolTip,strlen(lpszToolTip)+1);

Die letzte zu übernehmende Information legt fest, was der Aufruf von Shell_NotifyIcon() bewirken soll, und wird in dwMsgType übergeben.

 Shell_NotifyIcon(dwMsgType, &iconData); 

Abschließend sind noch die Ressourcen wieder freizugeben.

 if (hIconAtIndex)
  DestroyIcon(hIconAtIndex);
}

Schritt 3: Animation des Symbols

Der Beginn der Animation erfolgt sinnvollerweise in der Methode OnInitDialog() mit dem ersten Symbol des Arrays, das durch NIM_ADD hinzugefügt wird, während nachfolgende Aufrufe dann über NIM_MODIFY das Symbol ändern.

BOOL CShellAnimDlg::OnInitDialog()
{
  CDialog::OnInitDialog();
 
  int nIndexFirstIcon = 0;
  InstallAnimatedIcon(NIM_ADD, nIndexFirstIcon,
                      strToolTipArray[nIndexFirstIcon]);

Ebenfalls in OnInitDialog() wird ein Timer gesetzt, dessen Ereignis dann zum Animieren des Symbols verwendet werden kann.

  SetTimer(1,1000,NULL);
     
  return TRUE;
}

Den aktuellen Index in das Array der Symbole verwaltet das Static-Member nCounter, das zunächst mit 0 vorbelegt und anschließend mit jedem Aufruf der Methode OnTimer() hochgezählt wird, bis NUM_ICONS_IN_ANIMATION erreicht ist und wieder bei Symbol 0 angefangen wird.

void CShellAnimDlg::OnTimer(UINT nIDEvent) 
{
  static int nCounter = 0;
  InstallAnimatedIcon(NIM_MODIFY, nCounter,
                      strToolTipArray[nCounter]);
m_nCounter = nCounter;
  nCounter++;
  nCounter = nCounter%( NUM_ICONS_IN_ANIMATION);
CDialog::OnTimer(nIDEvent);
}

Es bleibt anzumerken, daß es notwendig sein kann, das letzte Symbol selbst zu löschen, wenn die Anwendung schließt. Es sollte daher sichergestellt werden, daß beim Schließen der Anwendung die folgenden Zeilen Code ausgeführt werden:

KillTimer(1);
InstallAnimatedIcon(NIM_DELETE,m_nCounter,"")

Schritt 4: Behandlung der Benachrichtigungen

Als letzter Schritt ist das Handling der Benachrichtigungen auf Mausereignisse zu implementieren. Dazu wurde die benutzerdefinierte Nachricht MYMSG_NOTIFYICON installiert, die für Callback-Benachrichtigungen verwendet wird. Für jede Aktion, die der Anwender auf dem Symbol ausführt, sendet die Shell eine Nachricht. Da hier nur Mausnachrichten interessieren, brauchen die übrigen nicht behandelt zu werden. Zunächst ist also ein Message-Handler zu erzeugen ...

afx_msg void OnHandleIconNotify(UINT wParam, LONG lParam);

... sowie zusätzlich das Mapping der Nachricht auf die entsprechende Funktion.

ON_MESSAGE(MYMSG_NOTIFYICON, OnHandleIconNotify)

Die Methode OnHandleIconNotify() besitzt dann folgenden Aufbau:

Methode InstallAnimated-Icon

void CShellAnimDlg::OnHandleIconNotify(
    UINT wParam, 
    LONG lParam)
{
  CString strTest;
  CString strCurrPosition(
                strToolTipArray[m_nCounter]);
  switch (lParam) {
    case WM_LBUTTONDOWN:
       // benutzerdefinierte Aktion
       break;
    case WM_RBUTTONDOWN:
       // benutzerdefinierte Aktion
       break;
    case WM_LBUTTONDBLCLK:
       // benutzerdefinierte Aktion
       break;
 
     default:
       break;
   }
}

Damit steht ein animiertes Symbol in der Statuszeile, das analog zum Symbol passende Tooltips setzt und das auf Mausklicks reagieren kann.

Methode OnHandle-IconNotify





Sachgebiet


© 2009-2012 by Alojado Publishing. Alle Rechte vorbehalten. Ausgewiesene Marken gehören ihren jeweiligen Eigentümern.
Mit der Benutzung dieser Seite erkennen Sie die Nutzungsbedingungen und die Datenschutzerklärung an. Der Betreiber übernimmt keine Haftung für den Inhalt verlinkter externer Internetseiten.
Seite erzeugt 2012-05-20 01:05:16 von textarchiv.alojado.de