MFC·Î 'ÀÚµ¿ µé¿©¾²±â' ³ëÆ®ÆÐµå ¸¸µé±â

 

 ¿ª½Ã ¸¶ÀÌÅ©·Î¼ÒÇÁÆ® 97³â 3¿ùÈ£¿¡ ½Ç¸° ³»¿ëÀÔ´Ï´Ù. ¿¹Á¦ ÇÁ·ÎÁ§Æ®´Â ¿©±â¼­..

 ÇöÀç Ä¿¼­ÀÇ ¶óÀΰú Ä÷³, ¼öÁ¤µÈ ¹®¼­ Ç¥½Ã ±â´É, ÀÚµ¿ µé¿©¾²±â¸¦ ±¸ÇöÇÑ °£´ÜÇÑ ³ëÆ®Æе带 ¸¸µé¾î º¸±â·Î  ÇÏÁö¿ä. CWinAppÀÇ OnIdle ÇÔ¼ö¸¦ ¿À¹ö¶óÀ̵åÇؼ­ À§ÀÇ ±â´ÉµéÀ» ±¸ÇöÇÑ °Ì´Ï´Ù. ´ÙÀ½Àº º»¹® ³»¿ë Áß ÀϺθ¦ ÀοëÇÑ °Ì´Ï´Ù.

 Ã³¸®ÇÒ ¸Þ½ÃÁö°¡ ¾øÀ» ¶§ (¿¹ : ¸Þ½ÃÁö Å¥°¡ ºñ¾îÀÖÀ» ¶§) ÇÁ·¹ÀÓ¿÷Àº CWinAppÀÇ ¸â¹öÇÔ¼öÀÎ OnIdle()À» È£ÃâÇϱ⠶§¹®¿¡ ¹é±×¶ó¿îµå ÀÛ¾÷À» ¼öÇàÇÏ·Á¸é ÀÌ ÇÔ¼ö¸¦ ¿À¹ö¶óÀ̵åÇÏ¸é µÈ´Ù. ±âº»ÀûÀ¸·Î OnIdle ÇÔ¼ö´Â Åø¹Ù ¹öÆ°À̳ª ¸Þ´º µî »ç¿ëÀÚ ÀÎÅÍÆäÀ̽º¿¡ °ü·ÃµÈ °´Ã¼ »óŸ¦ °»½ÅÇϰųª, ÇÁ·¹ÀÓ¿÷ÀÌ »ý¼ºÇÑ Àӽà °´Ã¼¸¦ Áö¿ì´Â µî ÀÌ°ÍÀú°ÍÀ» ÇÑ´Ù. À̶§ ÁÖÀÇÇÒ Á¡Àº ³Ê¹« ±ä ½Ã°£À» ¿äÇÏ´Â ÀÛ¾÷À» Idle ŸÀÓ¿¡ ó¸®Çϸé Àý´ë ¾ÈµÈ´Ù´Â °Í. Idle ŸÀÓ ÇÁ·Î¼¼½ÌÀÌ ³¡³¯ ¶§±îÁö ÇÁ·Î±×·¥Àº ¾Æ¹« Àϵµ ÇÒ ¼ö ¾ø±â ¶§¹®ÀÌ´Ù. ±×·¸°Ô µÇ¸é ÁÖ°´ÀÌ ÀüµµµÈ ¼ÀÀÌ µÇ°í ¸¸´Ù.

~~~~~~~~~~~

 UI (User Interface)ºÎºÐ¿¡¼­ Idle ŸÀÓ ÇÁ·Î¼¼½ÌÀ» ÀÀ¿ëÇÒ ¼ö ÀÖ´Â ºÐ¾ß°¡ ¾ÆÁÖ ¸¹´Ù. °¡·É ½Ã°è¿Í °°ÀÌ ÇÁ·Î±×·¥ÀÌ ½ÇÇàµÇ´Â µ¿¾È Áö¼ÓÀûÀ¸·Î »óŸ¦ °»½ÅÇØ ÁÖ¾î¾ß ÇÏ´Â ÀÛ¾÷¿¡ À¯¿ëÇÏ°Ô »ç¿ëÇÒ ¼ö ÀÖÀ¸¸ç, °¢ °³ÀÎÀÇ Ã¢ÀǷ¿¡ µû¶ó¼­ ´õ °­·ÂÇÑ ±â´ÉÀ» ±¸»çÇÒ ¼ö ÀÖ´Ù.

 

±×·³ ÀÌÁ¦ ÇØ¾ß ÇÒ ÀÏ¿¡ ´ëÇØ ¸»ÇØ µå¸®ÁÒ.

1. MDI·Î ÇÁ·ÎÁ§Æ®¸¦ ¸¸µéµÇ AppWizard ¸¶Áö¸· ´Ü°è¿¡¼­ CView¸¦ CEditView·Î ¹Ù²Ù¾î ÁÖ¾î¾ß ÇÕ´Ï´Ù. ÀÌ·¸°Ô¸¸ ÇÏ°í ÄÄÆÄÀÏÀ» Çصµ ±âº»ÀûÀÎ ¿¡µðÅÍ ±â´ÉÀº °¡Áö°í ÀÖÁÒ. ¿©±â¼­ ÇÁ·ÎÁ§Æ® À̸§Àº Pad ·Î Çß½À´Ï´Ù.

2. MainFrm.cpp¿¡¼­ ´ÙÀ½ ºÎºÐÀ» ã¾Æ ±½Àº ±Û¾¾ ºÎºÐÀ» Ãß°¡ÇÕ´Ï´Ù. ¿©±â¼­ ÇÏ´Â ÀÛ¾÷Àº »óŹٿ¡ paneÀ» Çϳª Ãß°¡ÇÏ´Â °ÍÀÌ°í, ¿©±â¼­ ¶óÀΰú Ä÷³À» Ãâ·ÂÇÕ´Ï´Ù.

static UINT indicators[] =
{
        ID_SEPARATOR,           // status line indicator
        ID_INDICATOR_INFO,
        ID_INDICATOR_CAPS,
        ID_INDICATOR_NUM,
        ID_INDICATOR_SCRL,
};

3. MainFrm.cpp ÆÄÀÏÀÇ ´ÙÀ½ºÎºÐµµ °íÃÄÁÝ´Ï´Ù. ¾Æ·¡ÀÇ ±½Àº ±Û¾¾ ºÎºÐ ÇÑ ÁÙ¸¸ Ãß°¡ÇÏ¸é µË´Ï´Ù.

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
        if (CMDIFrameWnd::OnCreate(lpCreateStruct) == -1)
                return -1;
        
        if (!m_wndToolBar.CreateEx(this, TBSTYLE_FLAT, WS_CHILD | WS_VISIBLE | CBRS_TOP
                | CBRS_GRIPPER | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC) ||
                !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))
        {
                TRACE0("Failed to create toolbar\n");
                return -1;      // fail to create
        }

        if (!m_wndStatusBar.Create(this) ||
                !m_wndStatusBar.SetIndicators(indicators,
                  sizeof(indicators)/sizeof(UINT)))
        {
                TRACE0("Failed to create status bar\n");
                return -1;      // fail to create
        }

        m_wndStatusBar.SetPaneInfo(1, ID_INDICATOR_INFO, SBPS_NORMAL, 100);

        // TODO: Delete these three lines if you don't want the toolbar to
        //  be dockable
        m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);
        EnableDocking(CBRS_ALIGN_ANY);
        DockControlBar(&m_wndToolBar);

        return 0;
}

4. À§ÀÇ 2, 3 ¹ø¿¡¼­ º¸¸é ID_INDICATOR_INFO¸¦ ¾Æ¹«µ¥µµ Á¤Àǵµ ÇÏÁö ¾Ê°í ±×³É ½á³ùÁÒ? ±×·³ Á¤ÀǸ¦ ÇØÁÖÁö¿ä ¹¹.. ¸®¼Ò½º ºä¿¡¼­ String TableÀ» ¿­¾îº¾´Ï´Ù. °Å±â´Ù ´ÙÀ½ ³»¿ëÀ» Ãß°¡ÇÏ´Â °ÅÁÒ.

      ID : ID_INDICATOR_INFO
      Caption : Ln 1, Col 1

Value ´Â Àû´çÈ÷ ¾Ë¾Æ¼­ Á¤ÇØÁú °Ì´Ï´Ù. ´Ù¸¥ id¿Í Áߺ¹µÇÁö ¾Ê´Â Àû´çÇÑ °ª ¾Æ¹«°Å³ª »ó°üÀº ¾øÁö¿ä.

5. ºäÀÇ OnKeyDownÀ» ¿À¹ö¶óÀ̵å ÇÕ´Ï´Ù. ÀÌ ÇÔ¼ö¸¦ °íÄ¡´Â ÀÌÀ¯´Â ºä¿¡¼­ ¿£ÅÍ°¡ ´­·ÈÀ» ¶§ ÀÚµ¿ µé¿©¾²±â¸¦ Çϵµ·Ï ÇØÁÖ±â À§Çؼ­ÀÌÁÒ.

void CPadView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
        // TODO: Add your message handler code here and/or call default
        if(nChar == VK_RETURN) { // ¿£ÅÍÅ°°¡ ´­·ÁÁ³À» ¶§
                ((CPadApp *)AfxGetApp())->m_bTabFlag = TRUE;
        }

                
        CEditView::OnKeyDown(nChar, nRepCnt, nFlags);
}

6. ¾ÖÇø®ÄÉÀÌ¼Ç Å¬·¡½º¿¡ ´ÙÀ½ µÎ º¯¼ö¸¦ public ¼Ó¼ºÀ¸·Î Á¤ÀÇÇÕ´Ï´Ù. m_nTabCount ´Â ÇöÀç ¶óÀÎÀÇ ÅÇ ¼ö¸¦ °¡Áö°í ÀÖ´Â º¯¼öÀÌ°í, m_nTabFlag ´Â ¿£ÅÍÅ°°¡ ´­·ÁÁ³´ÂÁöÀÇ ¿©ºÎ¸¦ ÀúÀåÇÏ´Â Ç÷¡±× º¯¼öÀÔ´Ï´Ù.

public:
        int m_nTabCount;
        BOOL m_bTabFlag;

7. ¸¶Áö¸·À¸·Î °¡Àå ÇÙ½ÉÀÌ µÇ´Â OnIdle ÇÔ¼ö ºÎºÐÀÔ´Ï´Ù.

BOOL CPadApp::OnIdle(LONG lCount)
{
        // TODO: Add your specialized code here and/or call the base class
        static CMainFrame*  pFrame = (CMainFrame*)AfxGetMainWnd();  // ÇÁ·¹ÀÓ
        static CStatusBar*  pStatusBar =  // »óŹٿ¡ ´ëÇÑ Æ÷ÀÎÅÍ(CStatusBar*)pFrame->GetDescendantWindow(AFX_IDW_STATUS_BAR);  
        static CChildFrame* pChild;  // Â÷Àϵå ÇÁ·¹ÀÓ¿¡ ´ëÇÑ Æ÷ÀÎÅÍ
        static CPadView*    pView;   // ºä¿¡ ´ëÇÑ Æ÷ÀÎÅÍ
        static CEdit*           pEdit;   // ¿¡µðÆ® ÄÁÆ®·Ñ¿¡ ´ëÇÑ Æ÷ÀÎÅÍ
        
        static CString str;       
        static int posStart;     // SelÀÇ ½ÃÀÛ ±ÛÀÚ À§Ä¡
        static int posEnd;      // SelÀÇ ³¡ ±ÛÀÚ À§Ä¡
        static int posFirst;     // ¶óÀÎÀÇ Ã¹ ±ÛÀÚ À§Ä¡
        static int posPrev;     // ÀÌÀü ±ÛÀÚ À§Ä¡, ¹®ÀÚ¿­ÀÌ ¼±ÅÃµÈ °æ¿ì
                                       // ¿ÞÂÊ ¹æÇâÀÎÁö ¿À¸¥ÂÊ ¹æÇâÀÎÁö ¾Ë±âÀ§ÇØ ÇÊ¿ä  
        static int nCurLine;   // ÇöÀç ¶óÀÎ ¼ö
        static int nCurCol;    // ÇöÀç Ä÷³ ¼ö
        static char buf[1024];

        int i;
        int n;

        pChild  = (CChildFrame*)pFrame->GetActiveFrame();
        pView   = (CPadView*)pChild->GetActiveView();
        pEdit   = &(pView->GetEditCtrl());

        switch(lCount)
        {
        case 0:
        case 1:
                
                CWinApp::OnIdle(lCount);
                return TRUE;

        case 2:  // »óŹٿ¡ ¶óÀÎ ¼ö¿Í Ä÷³ ¼ö¸¦ Ç¥½ÃÇÑ´Ù.

                if(!pStatusBar) return TRUE;
                if(!pEdit)
                {
                        str.Format("Ln ??, Col ??");
                        pStatusBar->SetPaneText(1, str);
                        
                        return TRUE;
                }
                
                pEdit->GetSel(posStart, posEnd);
                if(posStart == posEnd)        // ¹®ÀÚ¿­ÀÌ ¼±ÅõÇÁö ¾Ê¾ÒÀ¸¸é...
                {
                        posFirst = pEdit->LineIndex();
                        nCurLine = pEdit->LineFromChar() + 1;
                        nCurCol = posStart - posFirst + 1;
                        posPrev = posStart;
                }
                else                                  // ¹®ÀÚ¿­ÀÌ ¼±ÅõŠÀÖÀ¸¸é
                {
                        if(posStart < posPrev)    // ¿ÞÂÊ ¹æÇâÀ¸·Î ¼±ÅÃÇßÀ¸¸é
                        {
                                nCurLine = pEdit->LineFromChar(posStart) + 1;
                                posFirst = pEdit->LineIndex(nCurLine - 1);
                                nCurCol = posStart - posFirst + 1;    // ÇöÀç Ä÷³Àº
                        }
// ½ÃÀÛ ¹®ÀÚ À§Ä¡
                        else     // ¿À¸¥ÂÊ ¹æÇâÀ¸·Î ¼±ÅÃÇßÀ¸¸é
                        {
                                nCurLine = pEdit->LineFromChar(posEnd) + 1;
                                posFirst = pEdit->LineIndex(nCurLine - 1);
                                nCurCol = posEnd - posFirst + 1;      // ÇöÀç Ä÷³Àº
                        }
// ³¡ ¹®ÀÚ À§Ä¡
                }
                
                str.Format("Ln %d, Col %d", nCurLine, nCurCol);
                pStatusBar->SetPaneText(1, str);
                // »óŹٿ¡ ÇöÀç ¶óÀÎ, Ä÷³ Ç¥½Ã
                return TRUE;
        
        case 3:     // ÀÚµ¿ µé¿©¾²±â
                
                if(!pEdit) return TRUE;

                pEdit->GetSel(posStart, posEnd);
                posFirst = pEdit->LineIndex();

                if((m_bTabFlag == TRUE) && (posStart == posFirst))
                {
                        for(i = 0; i < m_nTabCount; i++)    // ÀÌÀü ¶óÀÎÀÇ ÅÇ ¼ö¸¸Å­
                        {                                               // ÅÇÀ» ä¿î´Ù.
                                pEdit->ReplaceSel("\t");
                        }
                        m_nTabCount = 0;
                        m_bTabFlag = FALSE;               // ´Ù½Ã Ç÷¡±×¸¦ °ÅÁþÀ¸·Î
                }
                else       // ÅÇ Ç÷¡±×°¡ °ÅÁþÀ̸é ÇöÀç ¶óÀÎÀ» Àоî¿Í¼­
                {           // ¾ÕÀÇ ÅÇ ¹®ÀÚ°¡ ¸î °³ ÀÎÁö¸¦ °è»êÇÑ´Ù.
                        n = pEdit->GetLine(pEdit->LineFromChar(), buf, 1024);
                        i = 0;
                        while(i < n && buf[i] == '\t') i++;
                        
                        m_nTabCount = i;
                }

                return TRUE;

        case 4:     // ŸÀÌƲ¿¡ '*' Ç¥½Ã
                
                if(!pEdit) return FALSE;

                if(pEdit->GetModify())       // ¹®¼­°¡ º¯°æµÇ¾úÀ¸¸é
                {
                        str = pView->GetDocument()->GetTitle();
                        if(str.Right(1) != '*')  // '*' Ç¥½Ã°¡ µÇ¾îÀÖÁö ¾ÊÀ¸¸é
                        {
                                str += '*';
                                pView->GetDocument()->SetTitle(str);
                        }
                }
                
                return FALSE;   // ´õ ÀÌ»ó Idle ŸÀÓ ÀÛ¾÷ÀÌ ¾øÀ½
        }

        return FALSE;
}