Figure 3   CAnimateCtrl


////////////////////////////////////////////////////////////////
// MFC Animation control from afxcmn.h
//

class CAnimateCtrl : public CWnd
{
    DECLARE_DYNAMIC(CAnimateCtrl)

// Constructors
public:
    CAnimateCtrl();
    BOOL Create(DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID);

// Operations
    BOOL Open(LPCTSTR lpszFileName);
    BOOL Open(UINT nID);
    BOOL Play(UINT nFrom, UINT nTo, UINT nRep);
    BOOL Stop();
    BOOL Close();
    BOOL Seek(UINT nTo);

// Implementation
public:
    virtual ~CAnimateCtrl();
};
 

Figure 5   CTBAnim

TBAnim.h

////////////////////////////////////////////////////////////////
// 1999 Microsoft Systems Journal. 
// If this code works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
// Compiles with Visual C++ 6.0, runs on Windows 98 and probably Windows NT too.
//
#include "StatLink.h"

#define DEFAULT_ANIM_STYLE WS_CHILD | WS_VISIBLE | ACS_CENTER

////////////////
// Toolbar animation control that has a hyperlink.
//
class CTBAnim : public CAnimateCtrl {
public:
    CTBAnim(LPCTSTR lpszURL=NULL) : m_link(lpszURL) { }
    virtual ~CTBAnim() { }
    CHyperlink m_link;         // go here when clicked

protected:
    afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
    afx_msg UINT OnNcHitTest(CPoint point);
    DECLARE_MESSAGE_MAP()
    DECLARE_DYNCREATE(CTBAnim)
};

//////////////////
// Derive your toolbar from this if you're not using a rebar.
//
class CAnimToolBar : public CToolBar {
public:
    CAnimToolBar(UINT nWidthAnim, UINT nResID) {
        m_nWidthAnim = nWidthAnim;
        m_nIDAnim = nResID;
    }
    ~CAnimToolBar() { }
    CTBAnim m_wndAnim;    // animation control

protected:
    int m_nWidthAnim;     // width of animation
    int m_nIDAnim;        // resource ID of animation

    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    afx_msg void OnSize(UINT nType, int cx, int cy);
    DECLARE_DYNAMIC(CAnimToolBar)
    DECLARE_MESSAGE_MAP()
};
TBAnim.cpp
/ ////////////////////////////////////////////////////////////////
// 1999 Microsoft Systems Journal. 
// If this code works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
// Compiles with Visual C++ 6.0, runs on Windows 98 and probably Windows NT too.
//
#include "StdAfx.h"
#include "TBAnim.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

IMPLEMENT_DYNCREATE(CTBAnim, CAnimateCtrl)
BEGIN_MESSAGE_MAP(CTBAnim, CAnimateCtrl)
    ON_WM_NCHITTEST()
    ON_WM_LBUTTONDOWN()
END_MESSAGE_MAP()

//////////////////
// Normally, the animation control returns HTTRANSPARENT, which disallows
// mouse clicks; need to return HTCLIENT to get WM_LBUTTONDOWN, etc.
//
UINT CTBAnim::OnNcHitTest(CPoint point)
{
    return HTCLIENT;
}

//////////////////
// User clicked: launch the hyperlink
// If string is empty, load it from resource.
// 
void CTBAnim::OnLButtonDown(UINT nFlags, CPoint point)
{
    if (m_link.IsEmpty())
        m_link.LoadString(GetDlgCtrlID());
    m_link.Navigate();
}

////////////////////////////////////////////////////////////////
// CAnimToolBar

IMPLEMENT_DYNAMIC(CAnimToolBar, CToolBar)
BEGIN_MESSAGE_MAP(CAnimToolBar, CToolBar)
    ON_WM_CREATE()
    ON_WM_SIZE()
END_MESSAGE_MAP()

//////////////////
// Create handler: create the animation control
//
int CAnimToolBar::OnCreate(LPCREATESTRUCT lpcs)
{
    if (CToolBar::OnCreate(lpcs)==-1)
        return -1;
    m_wndAnim.Create(DEFAULT_ANIM_STYLE, CRect(0,0,0,0), this, m_nIDAnim);
    return 0;
}

//////////////////
// Size handler: size the animation control
//
void CAnimToolBar::OnSize(UINT nType, int cx, int cy)
{
    CToolBar::OnSize(nType, cx, cy);
    CRect rc(cx-m_nWidthAnim, 0, cx, cy);    // right edge
    m_wndAnim.MoveWindow(&rc);               // do it
}
 

Figure 7   ShowIcons

Doc.h

////////////////////////////////////////////////////////////////
// 1999 Microsoft Systems Journal. 
// If this code works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
// Compiles with Visual C++ 6.0, runs on Windows 98 and probably Windows NT too.
//
const MAXNUMICONS = 1024;

////////////////
// Document holds an array of small and large icons
//
class CIconsDoc : public CDocument {
public:
   CIconsDoc();
   virtual ~CIconsDoc();

    // public interface
   int GetNumIcons()             { return m_nIcons; }
   const HICON* GetSmallIcons()  { return m_pIconsSmall; }
   const HICON* GetLargeIcons()  { return m_pIconsLarge; }

protected:
   int      m_nIcons;                   // total number of icons
   HICON    m_pIconsSmall[MAXNUMICONS]; // array of small HICONs
   HICON    m_pIconsLarge[MAXNUMICONS]; // array of large HICONs

    // MFC overrides
   virtual BOOL OnNewDocument();
   virtual void Serialize(CArchive& ar);
   virtual void SetTitle(LPCTSTR lpszTitle);

   afx_msg void OnUpdateIconIndicator(CCmdUI* pCmdUI);
   DECLARE_MESSAGE_MAP()
   DECLARE_DYNCREATE(CIconsDoc)
};
Doc.cpp
/ ////////////////////////////////////////////////////////////////
// 1999 Microsoft Systems Journal. 
// If this code works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
// Compiles with Visual C++ 6.0, runs on Windows 98 and probably Windows NT too.
//
#include "stdafx.h"
.
.
.

IMPLEMENT_DYNCREATE(CIconsDoc, CDocument)
BEGIN_MESSAGE_MAP(CIconsDoc, CDocument)
   ON_UPDATE_COMMAND_UI(ID_INDICATOR_ICONS, OnUpdateIconIndicator)
END_MESSAGE_MAP()

//////////////////
// Add number of icons to document title
//
void CIconsDoc::SetTitle(LPCTSTR lpszTitle)
{
   CString sTitle;
   if (m_nIcons>=0) {
      sTitle.Format(_T("%s [%d icons]"), lpszTitle, m_nIcons);
      lpszTitle = sTitle;
   }
   CDocument::SetTitle(lpszTitle);
}

//////////////////
// Load all the icons into the array.
// Ignore extra icons if more than MAXNUMICONS (so sorry).
//
void CIconsDoc::Serialize(CArchive& ar)
{
   if (!ar.IsStoring()) {
      m_nIcons = ::ExtractIconEx(
         ar.GetFile()->GetFilePath(),   // file name
         0,                             // start index
         m_pIconsLarge,                 // array of HICONs
         m_pIconsSmall,                 // ..ditto
         MAXNUMICONS);                  // max num to get
      ASSERT(m_nIcons != -1);
   }
}

//////////////////
// Update the status bar indicator for number of icons
//
void CIconsDoc::OnUpdateIconIndicator(CCmdUI* pCmdUI)
{
   CString s = _T("No File");
   if (m_nIcons>=0)
      s.Format(_T("%d Icons"), m_nIcons);
   pCmdUI->SetText(s);
}

View.h
////////////////////////////////////////////////////////////////
// 1999 Microsoft Systems Journal. 
// If this code works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
// Compiles with Visual C++ 6.0, runs on Windows 98 and probably Windows NT too.
//
#include "doc.h"

const MYWM_GETTOOLBAR = WM_USER;

//////////////////
// Icon view displays all the icons in its window
//
class CIconsView : public CScrollView {
protected:
	CIconsView() { }
	virtual ~CIconsView() {	}
   CIconsDoc* GetDocument() { return (CIconsDoc*)m_pDocument; }

protected:
   virtual void OnInitialUpdate();
   virtual void OnDraw(CDC* pDC);
   afx_msg void OnFoo();
   DECLARE_MESSAGE_MAP()
   DECLARE_DYNCREATE(CIconsView)
};

View.cpp
////////////////////////////////////////////////////////////////
// 1999 Microsoft Systems Journal. 
// If this code works, it was written by Paul DiLascia.
// If not, I don't know who wrote it.
// Compiles with Visual C++ 6.0, runs on Windows 98 and probably Windows NT too.
//
#include "stdafx.h"
•
•
•

//////////////////
// Initial update: set scroll sizes and change toolbar bitmap.
//
void CIconsView::OnInitialUpdate()
{
   CIconsDoc* pdoc = GetDocument();
   ASSERT_VALID(pdoc);

   CScrollView::OnInitialUpdate();

   // compute width of all icons
   int nIcons = pdoc->GetNumIcons();
   int cx = nIcons > 0 ? nIcons * GetSystemMetrics(SM_CXICON) : 0;

   // ...and height
   int cy = GetSystemMetrics(SM_CYICON) + // normal icon
      GetSystemMetrics(SM_CYSMICON) +     // small icon
      GetSystemMetrics(SM_CYHSCROLL);     // allow room for scroll bar

   // First change window size, height only (leave width alone)
   GetParentFrame()->RecalcLayout();
   CRect rc;
   GetClientRect(&rc);
   SetScrollSizes(MM_TEXT, CSize(rc.Width(), cy));
   ResizeParentToFit();

   // Now that window size is correct, set true scroll sizes
   SetScrollSizes(MM_TEXT, CSize(cx, cy));

   // load toolbar bitmap
   CBitmap bm;
   VERIFY(bm.LoadBitmap(IDR_MAINFRAME));

   CToolBar* pToolBar = (CToolBar*)GetParent()->SendMessage(MYWM_GETTOOLBAR);

   if (nIcons > 0 && pToolBar) {
      // If there's a toolbar, change its first button to be the first
      // small icon in the currently open EXE or DLL

      // create memory DC
      CWindowDC dc(this);
      CDC memdc;
      memdc.CreateCompatibleDC(&dc);

      // select toolbar bitmap
      CBitmap *poldbm = memdc.SelectObject(&bm);

      // draw into the dc/bitmap
      CBrush brush;
      brush.CreateSysColorBrush(COLOR_BTNFACE);
      VERIFY(::DrawIconEx(memdc, 0, 0,  // dc, x, y
         *pdoc->GetSmallIcons(),        // HICON (first small one)
         GetSystemMetrics(SM_CXSMICON), // cx
         GetSystemMetrics(SM_CYSMICON), // cy
         0, brush, DI_NORMAL));         // frame, brush, flags
      memdc.SelectObject(poldbm);
   }

   // Change bitmap in toolbar. This will delete the old one
   pToolBar->SetBitmap((HBITMAP)bm.Detach());
   pToolBar->Invalidate(TRUE);       // repaint
}

//////////////////
// Draw the icons
//
void CIconsView::OnDraw(CDC* pdc)
{
   CIconsDoc* pdoc = GetDocument();
   ASSERT_VALID(pdoc);
   int nIcons = pdoc->GetNumIcons();
   if (nIcons > 0) {
      const HICON* pIconLarge = pdoc->GetLargeIcons();
      const HICON* pIconSmall = pdoc->GetSmallIcons();
      
      int w = GetSystemMetrics(SM_CXICON);
      int h = GetSystemMetrics(SM_CYICON);
      int wSmall = GetSystemMetrics(SM_CXSMICON);
      int hSmall = GetSystemMetrics(SM_CYSMICON);

      int x = 0;
      for (int i=0; i<nIcons; i++) {
         // NOTE: for normal (large) icons, you could also use
         // CWnd::DrawIcon, which has fewer args, but for small
         // icons, you must use DrawIconEx
         CBrush brush;
         brush.CreateSolidBrush(GetSysColor(COLOR_WINDOW));
         ::DrawIconEx(*pdc,x,0,pIconSmall[i],w,h,0,brush,DI_NORMAL);
         ::DrawIconEx(*pdc,x,h,pIconSmall[i],wSmall,hSmall,0,brush,DI_NORMAL);
         x += w;
      }
   }
}