½ºÅ©·ÑµÇ´Â Å©·¹µðÆ® ´ÙÀ̾ó·Î±×
(Scrolling Credits Dialog)

ÀÌ ³»¿ëÀº Äڵ屸·ç(http://www.codeguru.com)¿¡¼­ °¡Á®¿Â °ÍÀÔ´Ï´Ù.

 

 ¼Ò½ºÄÚµå ¹Þ±â (credits.h/cpp) : ¾Æ·¡ÀÇ ¼Ò½º¿Í °°Àº °Í.

 Å©·¹µðÆ® ´ÙÀ̾ó·Î±×¶õ º¸Åë, ¿µÈ­°¡ ³¡³­ ÈÄ, ¸¸µå´Âµ¥ Âü¿©ÇÑ »ç¶÷µéÀÇ À̸§ÀÌ Á× È­¸é¿¡ ½ºÅ©·ÑµÇ´Â °Íó·³, ¾î¶² ÇÁ·Î±×·¥¿¡¼­  Æ¯Á¤ÇÑ Å° ½ÃÄö½º¸¦ ´­·ÈÀ» ¶§ ±× Á¦Ç° Á¦ÀÛ¿¡ Âü¿©ÇÑ »ç¶÷µéÀÇ À̸§ÀÌ Á× ½ºÅ©·ÑµÇ´Â ´ëÈ­»óÀÚ¸¦ ¸»ÇÑ´Ù.

 ÀÌ ´ÙÀ̾ó·Î±×´Â »ç¿ëÀÚ°¡ ÁöÁ¤ÇÑ »ö±ò°ú ÆùÆ®·Î ±ÛÀ» º¸¿©ÁÖ°í ¶ÇÇÑ ½ºÅ©·ÑµÇ´Â È­¸é¿¡ ºñÆ®¸Êµµ º¸¿©ÁØ´Ù. ³ªÅ¸³»°í ½ÍÀº ±ÛÀ» CPP ÆÄÀÏ ¾È¿¡ Á¤ÀÇµÈ °íÁ¤ ¹è¿­¿¡ ½á³Ö°í, ´Ù¸¥ ÆùÆ®, »ö µîÀ» »ç¿ëÇϱâ À§Çؼ­ escape sequenceÀ» »ç¿ëÇÑ´Ù.

 Å©·¹µðÆ®´Â ¼øȯÇϸ鼭, ½ÃÀÛºÎÅÍ °è¼Ó ¹Ýº¹ÇÏ¿© µ¹¾Æ°£´Ù.

 

´Ü°è

1. ¸®¼Ò½º ¿¡µðÅ͸¦ »ç¿ëÇÏ¿© ´ÙÀ̾ó·Î±×¸¦ Çϳª ¸¸µç´Ù.  ID´Â IDD_DISPLAY ¶ó°í ÇÑ´Ù.

    ´ÙÀ̾ó·Î±×¿¡ ÀÖ´Â OK ¹öÆ°Àº »ç¿ëÀÚ°¡ ´ÙÀ̾ó·Î±×¸¦ ¾ø¾Ö±â À§ÇØ »ç¿ëÇÒ ¼ö ÀÖ´Ù.

2. Å©·¹µðÆ®  Ç¥½Ã À©µµ¿ì¸¦ static text ·Î »ý¼ºÇÑ´Ù. (ÃæºÐÈ÷ Å« Å©±â·Î ¸¸µç´Ù.)

   ÀÌ ÅؽºÆ®¹Ú½º¸¦ IDC_DISPLAY_STATIC À̶ó°í À̸§ Áþ´Â´Ù. (ȤÀº »ç¿ëÀÚÀÇ ¸¶À½¿¡ µå´Â  ´Ù¸¥ À̸§À¸·Î, ÇÏÁö¸¸ ´Ù¸¥ À̸§À» »ç¿ëÇÑ´Ù¸é, ÀÌ ±Û¿¡¼­ Á¦°øÇÏ´Â ¼Ò½ºÄڵ忡¼­ IDC_DISPLAY_STATIC À» »ç¿ëÀÚ°¡ ¸¸µç »õ·Î¿î À̸§À¸·Î ¹Ù²ãÁÖ¾î¾ß ÇÑ´Ù.)

3. Ŭ·¡½º À§Àúµå¸¦ »ç¿ëÇÏ¿© ÀÌ ´ÙÀ̾ó·Î±×¹Ú½º¿¡ ¿¬°áµÉ »õ·Î¿î Ŭ·¡½º¸¦ ¸¸µç´Ù.

    Å¬·¡½º¸íÀº CCredits·Î ÇÏ°í, Base Class ´Â CDialog·Î ÇÑ´Ù.

4. Ŭ·¡½º À§Àúµå·Î ´ÙÀ½ÀÇ ÇÔ¼ö¿Í ¸Þ½ÃÁö Çڵ鷯µéÀ» ¸¸µç´Ù.

         virtual void OnOK();
         afx_msg void OnPaint();
         virtual BOOL OnInitDialog();
         afx_msg void OnTimer(UINT nIDEvent);
         afx_msg void OnDestroy();

5. ¾Æ·¡ ¼Ò½º ÄÚµåÀÇ ±½Àº ±Û¾¾ºÎºÐÀÌ Á÷Á¢ Ãß°¡ÇÑ ºÎºÐÀÌ´Ù. º¹»ç-ºÙ¿©³Ö±â¸¦ ÇÏ¸é µÈ´Ù. ¼Ò½ºÄڵ尡 ÇÊ¿äÇÏ´Ù¸é À§ÀÇ ¸µÅ©¿¡¼­ ¹ÞÀ» ¼ö ÀÖ´Ù.

6. ¾Æ·¡ Äڵ带 ´Ù ³ÖÀº ÈÄ, ´Ù¸¥ °÷¿¡¼­ DoModal() ÇÔ¼ö·Î ºÒ·¯ »ç¿ëÇÏ¸é µÈ´Ù.

   ¿¹¸¦ µé¾î AboutBox¿¡¼­ ºÒ·¯¿Â´Ù°í »ý°¢Çϸé AboutBoxÀÇ ´ÙÀ̾ó·Î±×¿¡ ¹öÆ° Çϳª¸¦ Ãß°¡ÇÏ°í ±× ¹öÆ°ÀÇ Çڵ鷯¿¡ ´ÙÀ½Ã³·³ Äڵ带 ³ÖÀ¸¸é µÈ´Ù.

   ±×¸²À» Ãâ·ÂÇÒ °æ¿ì ¹Ì¸® ±×¸²À» ¸¸µé¾î µÎ´Â °ÍÀ» ÀØÁö ¸» °Í

 

=============¼Ò½º ÄÚµå===================

// credits.h : header file
//
/////////////////////////////////////////////////////////////////////////////
// CCredits dialog

#define     DISPLAY_TIMER_ID    150     // timer id

class CCredits : public CDialog
{
// Construction
public:
        CCredits(CWnd* pParent = NULL);   // standard constructor

        RECT    m_ScrollRect,r;         // rect of Static Text frame
        int     nArrIndex,nCounter;      // work ints
        CString     m_szWork;           // holds display line
        BOOL       m_bFirstTime;
        BOOL       m_bDrawText;
        int             nClip;
        int             nCurrentFontHeight;
        CWnd*      m_pDisplayFrame;
        CBitmap    m_bmpWork;                     // bitmap holder
        CBitmap*   pBmpOld;                         // other bitmap work members
        CBitmap*    m_bmpCurrent;
        HBITMAP   m_hBmpOld;
        CSize      m_size;                              // drawing helpers
        CPoint     m_pt;
        BITMAP     m_bmpInfo;
        CDC        m_dcMem;
        BOOL       m_bProcessingBitmap;

// Dialog Data
        //{{AFX_DATA(CCredits)
        enum { IDD = IDD_DISPLAY };
        //}}AFX_DATA

// Overrides
        // ClassWizard generated virtual function overrides
        //{{AFX_VIRTUAL(CCredits)
        protected:
        virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
        //}}AFX_VIRTUAL

// Implementation
protected:
        // Generated message map functions
        //{{AFX_MSG(CCredits)
        virtual void OnOK();                      // <-----Ŭ·¡½º À§Àúµå¿¡¼­ Ãß°¡ÇÑ ºÎºÐ

        afx_msg void OnPaint();               // <-----Ŭ·¡½º À§Àúµå¿¡¼­ Ãß°¡ÇÑ ºÎºÐ
        virtual BOOL OnInitDialog();           // <-----Ŭ·¡½º À§Àúµå¿¡¼­ Ãß°¡ÇÑ ºÎºÐ
        afx_msg void OnTimer(UINT nIDEvent);  // <-----Ŭ·¡½º À§Àúµå¿¡¼­ Ãß°¡ÇÑ ºÎºÐ
        afx_msg void OnDestroy();           // <-----Ŭ·¡½º À§Àúµå¿¡¼­ Ãß°¡ÇÑ ºÎºÐ
        //}}AFX_MSG
        DECLARE_MESSAGE_MAP()
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// credits.cpp : implementation file
//**************************************************************************
// Note : ½ºÅ©·ÑµÇ´Â È­¸é¿¡´Â ±×¸²µµ ³ªÅ¸³ª°Ô ÇÒ ¼ö Àִµ¥, ÀÌ ¿¹Á¦¿¡¼­´Â
//           ID°¡ "BITMAP1" ÀÎ ºñÆ®¸Ê Çϳª¸¦  »ç¿ëÇß´Ù.
//           ¿©±â¼­ ÁÖÀÇÇÒ Á¡Àº ÀÌ ID ¿¡ µû¿ÈÇ¥µµ Æ÷ÇԵȴٴ °ÍÀÌ´Ù.
//            ( "BITMAP1"   not   BITMAP1 )
//            ±×¸®°í pArrCredit[] ¹è¿­¿¡ ±×¸²ÀÇ À̸§À» ³ÖÀ» ¶§ ÆÄÀϸí°ú
//            escape sequence »çÀÌ¿¡ ºó °ø°£À» µÎ¸é ¾ÈµÈ´Ù.
//            ( "BITMAP1\b" = ¿ÇÀº °æ¿ì,  "BITMAP1   \b" = Ʋ¸° °æ¿ì)

#include "stdafx.h"
#include "resource.h"
#include "credits.h"

#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif

#define SCROLLAMOUNT    -1
#define DISPLAY_SLOW    70
#define DISPLAY_MEDIUM  40
#define DISPLAY_FAST    10
#define DISPLAY_SPEED   DISPLAY_MEDIUM

#define RED             RGB(255,0,0)
#define GREEN           RGB(0,255,0)
#define BLUE            RGB(0,0,255)
#define WHITE                   RGB(255,255,255)
#define YELLOW                  RGB(255,255,0)
#define TURQUOISE       RGB(0,255,255)
#define PURPLE                  RGB(255,0,255)
#define BLACK                   RGB(0,0,0)

#define BACKGROUND_COLOR                     BLACK
#define TOP_LEVEL_TITLE_COLOR        RED
#define TOP_LEVEL_GROUP_COLOR       YELLOW
#define GROUP_TITLE_COLOR                   TURQUOISE
#define NORMAL_TEXT_COLOR             WHITE

// ÆùÆ®ÀÇ ³ôÀ̸¦ Á¤ÇÏ´Â ºÎºÐ
#define TOP_LEVEL_TITLE_HEIGHT           21             
#define TOP_LEVEL_GROUP_HEIGHT        19     
#define GROUP_TITLE_HEIGHT               17     
#define NORMAL_TEXT_HEIGHT               15

// Ãâ·ÂÇÒ ¹®Àڹ迭°ú ÇÔ²² ¾²ÀÏ escape sequence¸¦ Á¤ÀÇÇÏ´Â ºÎºÐ
// Å« ±ÛÀÚ¿¡¼­ ÀÛÀº ±ÛÀÚ¼øÀ¸·Î Ç¥½ÃµÇ¾î ÀÖ´Ù.

#define TOP_LEVEL_TITLE        '\n'
#define TOP_LEVEL_GROUP      '\r'
#define GROUP_TITLE               '\t'
#define NORMAL_TEXT             '\f'
#define DISPLAY_BITMAP          '\b'

#define ARRAYCOUNT      8          // Ãâ·ÂµÉ ¹®ÀåÀÇ °¹¼ö

// Ãâ·ÂµÉ ¹®ÀåÀ» °íÁ¤¹è¿­¿¡ ³Ö´Â´Ù.
char *pArrCredit[] = {  "Å©·¹µðÆ® ´ÙÀ̾ó·Î±×\n",
                                 "",
                                 "BITMAP1\b",    // ºñÆ®¸Ê ID¿¡´Â µû¿ÈÇ¥µµ Æ÷ÇԵǾî ÀÖ´Ù.
                                 "TOP LEVEL TITLE\n",
                                 "TOP LEVEL GROUP\r",
                                 "GROUP TITLE\t",
                                 "NORMAL TEXT\f",
                                 ""              };

/////////////////////////////////////////////////////////////////////////////
// CCredits dialog
 
CCredits::CCredits(CWnd* pParent /*=NULL*/)
        : CDialog(CCredits::IDD, pParent)
{
        //{{AFX_DATA_INIT(CCredits)
        //}}AFX_DATA_INIT
}

void CCredits::DoDataExchange(CDataExchange* pDX)
{
        CDialog::DoDataExchange(pDX);
        //{{AFX_DATA_MAP(CCredits)
        //}}AFX_DATA_MAP
}

BEGIN_MESSAGE_MAP(CCredits, CDialog)
        //{{AFX_MSG_MAP(CCredits)
        ON_WM_PAINT()
        ON_WM_TIMER()
        ON_WM_DESTROY()
        //}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CCredits message handlers

void CCredits::OnOK()
{
        KillTimer(DISPLAY_TIMER_ID);
        CDialog::OnOK();
}

//************************************************************************
//       InitDialog
//
//              Setup the display rect and start the timer.
//************************************************************************
BOOL CCredits::OnInitDialog()
{
        CDialog::OnInitDialog();
       BOOL bRet;
        UINT nRet;

        nCurrentFontHeight = NORMAL_TEXT_HEIGHT;

        CClientDC dc(this);
        bRet = m_dcMem.CreateCompatibleDC(&dc);

        m_bProcessingBitmap=FALSE;
        nArrIndex=0;
        nCounter=1;
        nClip=0;
        m_bFirstTime=TRUE;
        m_bDrawText=FALSE;
        m_hBmpOld = 0;

        m_pDisplayFrame=(CWnd*)GetDlgItem(IDC_DISPLAY_STATIC);  

        // If you assert here, you did not assign your static display control
        // the IDC_ value that was used in the GetDlgItem(...). This is the
        // control that will display the credits.
        _ASSERTE(m_pDisplayFrame);

        m_pDisplayFrame->GetClientRect(&m_ScrollRect);
        nRet = SetTimer(DISPLAY_TIMER_ID,DISPLAY_SPEED,NULL);
         _ASSERTE(nRet != 0);
 
       return TRUE;  // return TRUE unless you set the focus to a control
                           // EXCEPTION: OCX Property Pages should return FALSE
}

//************************************************************************
//       OnTimer
//
//              On each of the display timers, scroll the window 1 unit. Each 20
//      units, fetch the next array element and load into work string. Call
//      Invalidate and UpdateWindow to invoke the OnPaint which will paint
//      the contents of the newly updated work string.
//************************************************************************
void CCredits::OnTimer(UINT nIDEvent)
{
        if (nIDEvent != DISPLAY_TIMER_ID) {
                CDialog::OnTimer(nIDEvent);
                return;
        }

        if (!m_bProcessingBitmap)
        if (nCounter++ % nCurrentFontHeight == 0) {     // every x timer events, show new line
                nCounter=1;
                m_szWork = pArrCredit[nArrIndex++];
                if (nArrIndex > ARRAYCOUNT-1) nArrIndex=0;
                nClip = 0;
                m_bDrawText=TRUE;
                }

        m_pDisplayFrame->ScrollWindow(0,SCROLLAMOUNT,&m_ScrollRect,&m_ScrollRect);
        nClip = nClip + abs(SCROLLAMOUNT);      

        CRect r;
        CWnd* pWnd = GetDlgItem(IDC_DISPLAY_STATIC);
        ASSERT_VALID(pWnd);
        pWnd->GetClientRect(&r);
        pWnd->ClientToScreen(r);
        ScreenToClient(&r);
        InvalidateRect(r,FALSE); // FALSE does not erase background

        CDialog::OnTimer(nIDEvent);
}

//************************************************************************
//       OnPaint
//
//              Send the newly updated work string to the display rect.
//************************************************************************
void CCredits::OnPaint()
{
        CPaintDC dc(this); // device context for painting
        
        PAINTSTRUCT ps;
        CDC* pDc = m_pDisplayFrame->BeginPaint(&ps);

        pDc->SetBkMode(TRANSPARENT);

        //*********************************************************************
        //      FONT SELECTION
        CFont m_fntArial;
        CFont* pOldFont;
        BOOL bSuccess;
        BOOL bUnderline;
        BOOL bItalic;

        if (!m_szWork.IsEmpty())
        switch (m_szWork[m_szWork.GetLength()-1] ) {
        case NORMAL_TEXT:
        default:
                bItalic = FALSE;
                bUnderline = FALSE;
                nCurrentFontHeight = NORMAL_TEXT_HEIGHT;
                bSuccess = m_fntArial.CreateFont(NORMAL_TEXT_HEIGHT, 0, 0, 0,
                        FW_THIN, bItalic, bUnderline, 0,
                        ANSI_CHARSET,  OUT_DEFAULT_PRECIS,
                        CLIP_DEFAULT_PRECIS,  PROOF_QUALITY,
                        VARIABLE_PITCH | 0x04 | FF_DONTCARE,  (LPSTR)"Arial");

                pDc->SetTextColor(NORMAL_TEXT_COLOR);
                pOldFont  = pDc->SelectObject(&m_fntArial);

                break;

        case TOP_LEVEL_GROUP:
                bItalic = FALSE;
                bUnderline = FALSE;
                nCurrentFontHeight = TOP_LEVEL_GROUP_HEIGHT;
                bSuccess = m_fntArial.CreateFont(TOP_LEVEL_GROUP_HEIGHT, 0, 0, 0,
                                 FW_BOLD, bItalic, bUnderline, 0,  ANSI_CHARSET,
                                 OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,  PROOF_QUALITY,
                                 VARIABLE_PITCH | 0x04 | FF_DONTCARE, (LPSTR)"Arial");                   

                 pDc->SetTextColor(TOP_LEVEL_GROUP_COLOR);
                 pOldFont  = pDc->SelectObject(&m_fntArial);

                break;

        case GROUP_TITLE:
                bItalic = FALSE;
                bUnderline = FALSE;
                nCurrentFontHeight = GROUP_TITLE_HEIGHT;
                bSuccess = m_fntArial.CreateFont(GROUP_TITLE_HEIGHT, 0, 0, 0,
                        FW_BOLD, bItalic, bUnderline, 0,
                        ANSI_CHARSET, OUT_DEFAULT_PRECIS,
                        CLIP_DEFAULT_PRECIS, PROOF_QUALITY,
                        VARIABLE_PITCH | 0x04 | FF_DONTCARE, (LPSTR)"Arial");

                pDc->SetTextColor(GROUP_TITLE_COLOR);
                pOldFont  = pDc->SelectObject(&m_fntArial);

                break;

        case TOP_LEVEL_TITLE:
                bItalic = FALSE;
                bUnderline = TRUE;
                nCurrentFontHeight = TOP_LEVEL_TITLE_HEIGHT;
                bSuccess = m_fntArial.CreateFont(TOP_LEVEL_TITLE_HEIGHT, 0, 0, 0,
                        FW_BOLD, bItalic, bUnderline, 0,  
                        ANSI_CHARSET, OUT_DEFAULT_PRECIS,
                        CLIP_DEFAULT_PRECIS, PROOF_QUALITY,
                        VARIABLE_PITCH | 0x04 | FF_DONTCARE,  (LPSTR)"Arial");

                pDc->SetTextColor(TOP_LEVEL_TITLE_COLOR);
                pOldFont  = pDc->SelectObject(&m_fntArial);

                break;

        case DISPLAY_BITMAP:
                if (!m_bProcessingBitmap) {
                        CString szBitmap = m_szWork.Left(m_szWork.GetLength()-1);
                         if (!m_bmpWork.LoadBitmap((const char *)szBitmap)) {
                                CString str;
                                str.Format("Could not find bitmap resource \"%s\". "
                                                "Be sure to assign the bitmap a QUOTED resource name", szBitmap);
                                KillTimer(DISPLAY_TIMER_ID);
                                MessageBox(str);

                                return;
                           }
                           m_bmpCurrent = &m_bmpWork;
                           m_bmpCurrent->GetObject(sizeof(BITMAP), &m_bmpInfo);
                           m_size.cx = m_bmpInfo.bmWidth;       // width  of dest rect

                           RECT workRect;
                           m_pDisplayFrame->GetClientRect(&workRect);
                           m_pDisplayFrame->ClientToScreen(&workRect);
                           ScreenToClient(&workRect);
                            // upper left point of dest
                           m_pt.x = (workRect.right -
                                 ((workRect.right-workRect.left)/2) - (m_bmpInfo.bmWidth/2));
                           m_pt.y = workRect.bottom;

                           pBmpOld = m_dcMem.SelectObject(m_bmpCurrent);
                           if (m_hBmpOld == 0)   m_hBmpOld = (HBITMAP) pBmpOld->GetSafeHandle();

                           m_bProcessingBitmap = TRUE;
                    }

                    break;
             }

             CBrush bBrush(BLACK);
             CBrush* pOldBrush;
             pOldBrush  = pDc->SelectObject(&bBrush);

             // Only fill rect comprised of gap left by bottom of scrolling window
             r=m_ScrollRect;
             r.top = r.bottom-abs(SCROLLAMOUNT);
             pDc->DPtoLP(&r);

             if (m_bFirstTime) {
                    m_bFirstTime=FALSE;
                    pDc->FillRect(&m_ScrollRect,&bBrush);

             } else
                    pDc->FillRect(&r,&bBrush);
                    r=m_ScrollRect;
                    r.top = r.bottom-nClip;

                    if (!m_bProcessingBitmap) {
                            int x = pDc->DrawText((const char *)m_szWork, m_szWork.GetLength()-1, &r,
                                   DT_TOP| DT_CENTER| DT_NOPREFIX | DT_SINGLELINE);     
             
                             m_bDrawText=FALSE;
              
                    } else {
                             dc.StretchBlt( m_pt.x, m_pt.y-nClip, m_size.cx, nClip, &m_dcMem, 0, 0,
                                            m_bmpInfo.bmWidth-1, nClip, SRCCOPY );

                             if (nClip > m_bmpInfo.bmHeight) {
                                      m_bmpWork.DeleteObject();
      
                             m_bProcessingBitmap = FALSE;
                             nClip=0;
                             m_szWork.Empty();
                             nCounter=1;
                    }
                    pDc->SelectObject(pOldBrush);
                    bBrush.DeleteObject();
                    m_pDisplayFrame->EndPaint(&ps);

                    return;
           }
           pDc->SelectObject(pOldBrush);
           bBrush.DeleteObject();

           if (!m_szWork.IsEmpty()) {
                pDc->SelectObject(pOldFont);
                m_fntArial.DeleteObject();
           }

           m_pDisplayFrame->EndPaint(&ps);
           // Do not call CDialog::OnPaint() for painting messages
}

void CCredits::OnDestroy()
{
        CDialog::OnDestroy();

        m_dcMem.SelectObject(CBitmap::FromHandle(m_hBmpOld));
        m_bmpWork.DeleteObject();
}

 

- the end of this article -