Programmieren mit C++

Visual C++

Oberflächen

AVI-Animation in Statuszeilenpanel

Wie kann während länger andauernder Operationen in einem Panel die Statusanzeige über eine AVI-Animation erfolgen?

Frage

Eine einfache AVI-Animation in einem Panel, wie es die nachfolgende Abbildung zeigt, ist relativ einfach zu realisieren.

Abbildung 5/2.6.1.13-1: Animierter Rechenschieber

Für die konkrete Einbindung wird eine spezielle universell einsetzbare Klasse implementiert, die nachfolgend beschrieben wird. Hier zunächst die notwendigen Schritte zur Integration der Lösung:

  • Zuerst sind die Dateien BrushStatusBar.cpp und .h sowie StatusbarAnimate.cpp und .h dem Projekt hinzuzufügen.
  • Dem Projekt ist dann ein CStatusbarAnimate Member in der CmainFrame-Klasse hinzuzufügen, sowie das CStatusBar Member auf die Klasse CBrushStatusBar abzuändern. Beim Design der Statuszeile ist darauf zu achten, daß das entsprechende Panel groß genug ist, um die AVI-Animation aufzunehmen.
  • Die geeignete AVI-Ressource ist dem Ressourcen-File hinzuzufügen. Die Ausgabe der AVI-Animation erfolgt transparent, wobei die transparente Farbe durch das erste Pixel links oben definiert wird.
  • Abschließend muß der Code von to CMainFrame erweitert werden, indem zunächst der Konstruktor das Member m_pAnimate auf NULL setzt.

Lösung

CMainFrame::CMainFrame()
{
  m_pAnimate = NULL;
}

Der Destruktor des Rahmenfensters hat sicherzustellen, daß die Animation beendet wird.

Konstruktor CMainFrame

CMainFrame:: ~CMainFrame()
{
  StopAnimation();
}

Die Methode StopAnimation() selbst ist in der CMainFrame-Klasse wie folgt zu implementieren:

Destruktor ~CMainFrame

void CMainFrame::StopAnimation()
{
  delete m_pAnimate;
  m_pAnimate = NULL;
}

Zum Starten der Animation erzeugt die Methode StartAnimation() eine neue Instanz der Klasse CStatusbarAnimate, deren Methode Create() anschließend ein Animationspanel erzeugt.

Methode StopAnimation

void CMainFrame::StartAnimation( 
    UINT id, int nPane /*=1*/ )
{
  StopAnimation();
 
  m_pAnimate = new CStatusbarAnimate;
  m_pAnimate->Create(id, nPane);
}

Über die Methode IsAnimationActive() läßt sich ermitteln, ob gerade eine Animation läuft.

bool CMainFrame::IsAnimationActive()
{
  return (m_pAnimate != NULL);
}

Damit bei einer Aktualisierung der Control nicht der Originaltext des Panels angezeigt wird, stellt der Eventhandler des Ereignisses OnUpdateAnimate() sicher, daß der Text des Panels gelöscht wird.

void CMainFrame::OnUpdateAnimate(
    CCmdUI* pCmdUI) 
{
  pCmdUI->SetText(_T(""));
}

Damit der OnCtlColor() Event der CStatusBar nicht die Animation zerstört, wird dieser Event über eine eigene Ableitung entschärft.

HBRUSH CBrushStatusBar::OnCtlColor(CDC*  pDC, 
                                   CWnd* pWnd, 
                                   UINT  nCtlColor) 
{
  if (pWnd->IsKindOf(RUNTIME_CLASS(CStatusbarAnimate))) {
    HBRUSH hbr = CStatusBar::OnCtlColor(pDC, pWnd, nCtlColor);
    return hbr;
  }
 
  return (HBRUSH)GetStockObject(NULL_BRUSH);
}

Die Klasse CStatusbarAnimate setzt anschließend auf die MFC-Klasse CAnimateCtrl auf und erweitert deren Basisfunktionalität um die hier geforderte Spezialisierung auf die Statuszeile. Die Methode Create() erzeugt darum auch zunächst intern eine Referenz auf die Statuszeile.

Methode StartAnimation

BOOL CStatusbarAnimate::Create( 
    UINT nIDanimation, int nPane /*=1*/ )
{
 CStatusBar *pStatusBar = GetStatusBar();
 if (!pStatusBar)
  return FALSE;

Als Stil setzt die Methode

 DWORD dwStyle = WS_CHILD | WS_VISIBLE | 
                  ACS_AUTOPLAY | ACS_TRANSPARENT | ACS_CENTER;

Die Koordinaten des betroffenen Panel-Rechtecks liefert:

 CRect paneRect;
 pStatusBar->GetItemRect(nPane, &paneRect);
 paneRect.InflateRect(-1,-1);

Nach diesen Vorbereitungen kann die Control über die ererbte Methode Create() erzeugt werden.

 if (!CAnimateCtrl::Create( dwStyle, paneRect, pStatusBar, 0 ))
  return FALSE;

Abschließend wird der Panelindex übernommen und das Fenster in seiner Größe angepaßt. Den Rückgabewert der Methode definiert dann der Aufruf von Open() mit der Ressourcen-ID als Parameter.

 m_nPane = nPane;
 
 Resize();
 
 return Open( nIDanimation );
}

Einen Zeiger auf die Statusbar liefert die Methode GetStatusBar(), die allerdings dann, wenn das Hauptfenster ein FrameWindow ist, auf die normalen Funktionen zurückgreift.

CStatusBar* CStatusbarAnimate::GetStatusBar()
{
  CWnd *pMainWnd = AfxGetMainWnd();
  if (!pMainWnd)
    return NULL;
 
  if (pMainWnd->IsKindOf(RUNTIME_CLASS(CFrameWnd)))
  {
    CWnd* pMessageBar = ((CFrameWnd*)pMainWnd)->GetMessageBar();
    return DYNAMIC_DOWNCAST(CStatusBar, pMessageBar);
  }

Ist das Hauptfenster kein FrameWindow, durchläuft die Methode die Liste der Kindfenster und sucht nach einer Statuszeile.

  else return DYNAMIC_DOWNCAST(
               CStatusBar, 
               pMainWnd->GetDescendantWindow(AFX_IDW_STATUS_BAR));
}

Der Event-Handler für das Ereignis OnEraseBkgnd() stellt sicher, daß das Panelsegment auf die richtige Größe gesetzt ist, bevor der geerbte Event-Handler aufgerufen wird.

Methode Create

BOOL CStatusbarAnimate::OnEraseBkgnd(
   CDC* pDC) 
{
 Resize();
 
 return CAnimateCtrl::OnEraseBkgnd(pDC);
}

Die von OnEraseBkgnd() aufgerufene Methode Resize() bringt das zur Animation gehörende Panel auf die richtige Größe, indem das Fenster entsprechend verschoben wird.

Event-Handler OnEraseBkgnd

BOOL CStatusbarAnimate::Resize()
{
  if (!IsWindow(GetSafeHwnd()))
    return FALSE;
 
  CStatusBar *pStatusBar = GetStatusBar();
  if (!pStatusBar)
    return FALSE;

Liegt der Zeiger auf die Statuszeile vor, wird das Rechteck des Panels, in das gezeichnet werden soll, bestimmt.

  CRect rc;
  pStatusBar->GetItemRect(m_nPane, rc);
 
  rc.InflateRect(-1,-1);

Anschließend kann das Fenster, wenn sich seine Größe geändert hat, verschoben werden, um die Größenänderung widerzuspiegeln.

  if (rc != m_Rect) 
  {
    MoveWindow(&rc);
    m_Rect = rc;
  }
 
  return TRUE;
}

Methode Resize





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:14:24 von textarchiv.alojado.de