유돌이

calendar

1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31

Notice

2009. 1. 2. 17:57 C/C++/MFC

MFC를 사용하여 웹 브라우저 만들기


1. Project 생성

  • Application Type : SDI
  • Application Name : myWebBr

2. 메뉴 추가

아래의 그림을 참조하면서 메뉴를 만들자.

1) 메인 메뉴

Caption

이동(&M)

2) 이동(&M)의 서브 메뉴

각 ID에 해당하는 함수는 View 클래스에서 만들자.

ID

Caption

Function

Prompt

ID_MOVE_NEXT

앞으로(&N)

OnMoveNext()

앞으로 이동한다.

ID_MOVE_BACK

뒤로(&B)

OnMoveBack()

뒤로 이동한다.

Separator

 

 

 

ID_MOVE_STOP

멈춤(&S)

OnMoveStop()

페이지 다운로드를 멈춘다.

ID_MOVE_RELOAD

다시읽기(&R)

OnMoveReload()

현재 페이지를 다시 읽는다.

Separator

 

 

 

ID_MOVE_HOME

홈페이지(&H)

OnMoveHome()

기본으로 설정된 홈페이지로 이동한다.

3. 툴바 추가

1) 이동 메뉴에서 [뒤로], [앞으로], [멈춤]에 해당 하는 툴바를 만들자.

2) 만들어진 툴바와 메뉴 아이템과 ID를 연결하자.

Menu ID

ToolBar

ID_MOVE_BACK

[뒤로]

ID_MOVE_NEXT

[앞으로]

ID_MOVE_STOP

[멈춤]

 

4. 다이알로그바 만들기

 

1) ToolBar는 일반적으로 단순한 아이콘형 버튼들로 이루어진 도구 모음이지만, 다이얼로그바는 보다 다양한 윈도우 컨트롤을 포함할 수 있는 도구모음이라 하겠다. 다이얼로그바는 AppWizard가 자동으로 생성해 주지는 않지만 VC++가 제공하는 Components를 사용하여 간단하게 만들 수 있다.

Project -> Add To Project -> Components and Controls

로 이동하면 VC++이 제공하는 Gallery폴더로 이동하는데 그중에서

Visual C++ Components -> Dialog Bar

를 선택하여 아래와 같이 설정한후 "OK"버튼을 만든다.

Dialog bar Name : My Dialog Bar
Member variable Name : m_wndAddressBar

2) 다이얼로그바를 아래와 같이 편집하자

만들어진 Dialog Bar의 ID는 자동으로 "CG_ID_VIEW_DLGBAR"로 만들어 진다.

Control

Caption

ID

Function

Static Text

주 소

IDC_STATIC

 

Combo Box

 

 

 

Button

이 동

IDC_GO_SITE

OnGoSize()

OnGoSize()함수는  MainFrame클래스에서 만든다. 그러나 다이얼로그바에서 추가한 컨트롤의 ID는 WizardBar에 나타나지 않는다. 따라서 다이얼로그바의 컨트롤에서 전달되는 WM_COMMAND를 처리하기 위해 ON_COMMAND()매크로를 직접 작성한다.

(1) 먼저 MainFrame.h에 매크로 함수임을 선언하고

  1. // CMainFrame.h
  2. class CMainFrame : public CFrameWnd
  3. {
  4. ...        
  5. protected:
  6.         CDialogBar m_wndAddressBar;
  7.         //{{AFX_MSG(CMainFrame)
  8.         afx_msg void OnGoSite();
  9.         afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
  10.                 // NOTE - the ClassWizard will add and remove member functions here.
  11.                 //    DO NOT EDIT what you see in these blocks of generated code!
  12.         //}}AFX_MSG
  13.         DECLARE_MESSAGE_MAP()
  14. };

(2) 메시지맵에 컨트롤의 ID와 연결되는 함수명을 정의하고

  1. // CMainFrame.cpp
  2. BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
  3.         ON_COMMAND(IDC_GO_SITE, OnGoSite)
  4.         ON_COMMAND_EX(CG_ID_VIEW_DLGBAR, OnBarCheck)
  5.         ON_UPDATE_COMMAND_UI(CG_ID_VIEW_DLGBAR, OnUpdateControlBarMenu)
  6.         //{{AFX_MSG_MAP(CMainFrame)
  7.                 // NOTE - the ClassWizard will add and remove mapping macros here.
  8.                 //    DO NOT EDIT what you see in these blocks of generated code !
  9.         ON_WM_CREATE()
  10.         //}}AFX_MSG_MAP
  11. END_MESSAGE_MAP()

(3) 실제 함수의 내용을 기술한다.

  1. #include "MyWebBrDoc.h"
  2. #include "MyWebBrView.h"
  3. void CMainFrame::OnGoSite()
  4. {
  5.         CComboBox *pCombo = (CComboBox*)(m_wndAddressBar.GetDlgItem(IDC_COMBO1));
  6.         if(pCombo)
  7.         {
  8.                 CString urlStr;
  9.                 pCombo->GetWindowText(urlStr);
  10.                 if(urlStr != "")
  11.                 {
  12.                         ((CMyWebBrView*)GetActiveView())->m_WebBr.Navigate(urlStr,NULL,NULL,NULL,NULL);
  13.                 }
  14.                 else
  15.                 {
  16.                         AfxMessageBox("input url\n");
  17.                 }
  18.         }
  19. }

5. 다이얼로그바의 토클 추가하기

메뉴를 추가하는 방법과 동일하게 ResourceView에서 작업하면된다.

  • 위치 : [보기]메뉴의 서브 메뉴로 추가 등록
  • ID : CG_ID_VIEW_DLGBAR
  • Caption : 주소 이동줄

DialogBar를 만들 때 사용된 ID를 그대로 사용하는 이유는 일반적으로 메뉴의 ID를 Toolbar가 그대로 사용하는 것과 동일하다. DialogBar에 주워진 자동처리 부분을 그대로 받아 사용하기 위해 메뉴의 ID를 DialogBar의 ID를 그대로 사용한다.

 

6. ActiveX 컨트롤 추가

웹문서를 보여주도록 프로그램은 매우 복잡한 프로그램으로, 컨트롤을 사용하지 않고는 거의 불가능하다고 볼 수 있다. 따라서 우리는 HTML문서를 보여주는 기능은 MS 익스플로에서 제공하는  ActiveX 컨트롤중 "웹브라우저 컨트롤"을 사용하겠다.

1) Microsoft웹브라우저 컨트롤 추가하기

Project -> Add To Project -> Components and Controls

로 이동하면 VC++이 제공하는 Gallery폴더로 이동하는데 그중에서

Resigtered ActiveX Controls -> Microsoft웹 브라우저

를 선택하여 아래와 같이 설정한후 "OK"버튼을 만든다.

그러면 ClassViewer에 "CWebBrowser2"  클래스가 추가된다.

7. Microsoft Control 제어하기

추가가된 컨트롤을 제어하기 위해 크게 두가지 작업을 해야 한다.

  • 웹 브라우저 컨트롤 생성하기
  • 웹 브라우저 컨트롤의 크기를 현재 View의 크기에 맞게 조정하기

1) 웹 브라우저 컨트롤 생성하기

웹 브라우저 컨트롤를 View클래스에서 사용하기 위해 헤더파일을 삽입하고 멤버 변수를 설정한다.

  1. #include "webbrowser2.h" //추가
  2. class CMyWebBrView : public CView
  3. {
  4. protected: // create from serialization only
  5.         CMyWebBrView();
  6.         DECLARE_DYNCREATE(CMyWebBrView)
  7. // Attributes
  8. public:
  9.         CMyWebBrDoc* GetDocument();
  10.         CWebBrowser2 m_WebBr; // 추가

2) ClassWizard 나 WizardBar에서 WM_CREATE와 WM_SIZE의 메시지 헨들러 함수를 만든다.

  1. int CMyWebBrView::OnCreate(LPCREATESTRUCT lpCreateStruct)
  2. {
  3.         if (CView::OnCreate(lpCreateStruct) == -1)
  4.                 return -1;
  5.         
  6.         // Source Append----------------------------------
  7.         CRect rc;
  8.         GetClientRect(rc);
  9.         if(m_WebBr.Create("Web Control", WS_CHILD|WS_VISIBLE,rc, this, 1010) == FALSE)
  10.         {
  11.                 AfxMessageBox("Fail \n");
  12.                 return -1;
  13.         }
  14.         m_WebBr.GoHome(); // 프로그램이 시작되면 자동으로 기본 페이지로 이동
  15.         // end Append--------------------------------------
  16.         return 0;
  17. }
  18. void CMyWebBrView::OnSize(UINT nType, int cx, int cy)
  19. {
  20.         CView::OnSize(nType, cx, cy);
  21.         
  22.         m_WebBr.MoveWindow(0,0,cx,cy); //추가(현재 View의 크기에 맞게 크기를 조정한다.
  23.         
  24. }

8. 메뉴 아이템 헨들러 추가하기

1) 메인메뉴-[이동]

이미 만들어진 각 메뉴에 해당하는 함수에 아래와 같은 내용으로 수정한다.

  1. void CMyWebBrView::OnMoveNext()
  2. {
  3.         m_WebBr.GoForward(); // 추가
  4.         
  5. }
  6. void CMyWebBrView::OnMoveBack()
  7. {
  8.         m_WebBr.GoBack(); // 추가
  9.         
  10. }
  11. void CMyWebBrView::OnMoveHome()
  12. {
  13.         m_WebBr.GoHome(); // 추가
  14.         
  15. }
  16. void CMyWebBrView::OnMoveStop()
  17. {
  18.         m_WebBr.Stop(); // 추가
  19.         
  20. }
  21. void CMyWebBrView::OnMoveRelaod()
  22. {
  23.         m_WebBr.Refresh(); // 추가
  24.         
  25. }

2) 업데이트 UI 핸들러 추가

다이얼로그바 중에 [앞으로][뒤로]에 해당 하는 화살표 도구의 활성화와 비활성화를 제어하도록 핸들러를 추가한다. 메뉴나 툴바의 버튼의 상태를 정하기 위해 아이템 ID에 연결된 업데이트 핸들러가 호출되는데 이를 "UPDATE_COMMAND_UI"라 한다.

(1) 먼저 ClassWizard에 ID_MOVE_BACK, ID_MOVE_NEXT에 해당하는 UPDATE_COMMAND_UI 메크로 함수를 작성한다.

(2) [뒤로][앞으로] 메뉴의 현재 상태를 저장하기 위한 변수를 선언하고, 위에서 만들어진 OnUpdateMoveBack(), OnUpdateMoveNext()함수의 내용을 수정한다.

  1. // CMyWebBrView.h
  2. class CMyWebBrView : public CView
  3. {
  4.  ...
  5. public:
  6.         BOOL m_bForward; // 추가
  7.         BOOL m_bBack; //---추가
  8.  ...
  9. };
  1. // CMyWebBrView.cpp
  2. CMyWebBrView::CMyWebBrView()
  3. {
  4.         m_bBack = FALSE;
  5.         m_bForward = FALSE;
  6. }
  1. void CMyWebBrView::OnUpdateMoveBack(CCmdUI* pCmdUI)
  2. {
  3.         pCmdUI->Enable(m_bBack);
  4.         
  5. }
  6. void CMyWebBrView::OnUpdateMoveNext(CCmdUI* pCmdUI)
  7. {
  8.         pCmdUI->Enable(m_bForward);
  9.         
  10. }

(3) ActiveX 컨트롤 이벤트

ActiveX 컨트롤은 컨트롤을 포함하고 있는 부모 윈도우에 자신의 정보를 넘겨주기 위해 이벤트를 발생시킨다. 부모 윈도우는 이 이벤트를 받기 위해 다음과 같은 매크로를 사용한다.

  1. // CMyWebBrView.h
  2. class CMyWebBrView : public CView
  3. {
  4. ...
  5.         DECLARE_MESSAGE_MAP()
  6.         DECLARE_EVENTSINK_MAP() // 추가
  7. };
  1. CMyWebBrView.cpp
  2. ...
  3. BEGIN_EVENTSINK_MAP(CMyWebBrView, CView)
  4.         ON_EVENT(CMyWebBrView, 1010,105, OnCommandStateChange, VTS_I4 VTS_BOOL)
  5. END_EVENTSINK_MAP()
  6. ...

(참고) ON_EVENT() 매크로

ON_EVENT(theClass, id, dispid, pfnHandler, vtsParams)

theClass

이벤트 맵이 정의된 클래스

id

이벤트를 보내는 ActiveX 컨트롤의 ID, 즉 웹 브라우저 컨트롤의 ID

dispid

받고자 하는 이벤트 ID로 컨트롤마다 정해져 있다.

ptnHandler

이벤트를 받을 때 호출되는 함수

vtsParams

이벤트 파라미터 타입

(4) 이벤트 핸들러 함수(OnCommandStateChange())

  1. // CMyWebBrView.h
  2. class CMyWebBrView : public CView
  3. {
  4. protected:
  5.         //{{AFX_MSG(CMyWebBrView)
  6.         afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
  7.         afx_msg void OnSize(UINT nType, int cx, int cy);
  8.         afx_msg void OnMoveNext();
  9.         afx_msg void OnMoveBack();
  10.         afx_msg void OnMoveHome();
  11.         afx_msg void OnMoveStop();
  12.         afx_msg void OnMoveRelaod();
  13.         afx_msg void OnUpdateMoveBack(CCmdUI* pCmdUI);
  14.         afx_msg void OnUpdateMoveNext(CCmdUI* pCmdUI);
  15.         afx_msg void OnCommandStateChange(long Command, BOOL Enable); // 추가할 핸들러 함수
  16.         //}}AFX_MSG
  17.         DECLARE_MESSAGE_MAP()
  18.         DECLARE_EVENTSINK_MAP()
  1. // CMyWebBrView.cpp
  2. void CMyWebBrView::OnCommandStateChange(long Command, BOOL Enable)
  3. {
  4.         switch(Command)
  5.         {
  6.         case CSC_NAVIGATEFORWARD:
  7.                 m_bForward = Enable;
  8.                 break;
  9.         case CSC_NAVIGATEBACK:
  10.                 m_bBack = Enable;
  11.                 break;
  12.         }
  13. }

9. URL 입력창의 Enter 키 처리

주소 입력창에 주소를 입력한후 엔터키를 쳤을 경우 이동 버튼을 클릭한 것과 같은 효과를 내면된다. 즉, 엔터키를 쳤을 경우 OnGoSite()함수를 Call 하면 될 것이다.

CMainFrame에서 엔터키를 쳤다는 얘기는 윈도우 메시지가 "IDOK" 발생했다는 말과 동일하다. 그럼, "IDOK"가 발생하면 OnGoSite()함수를 Call 할 수 있도록 메크로만 작성해 주면된다.

  1. // CMainFrm.cpp
  2. BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
  3.         ON_COMMAND(IDC_GO_SITE, OnGoSite)
  4.         ON_COMMAND(IDOK, OnGoSite)
  5.         ON_COMMAND_EX(CG_ID_VIEW_MYDIALOGBAR, OnBarCheck)
  6.         ON_UPDATE_COMMAND_UI(CG_ID_VIEW_MYDIALOGBAR, OnUpdateControlBarMenu)
  7.         //{{AFX_MSG_MAP(CMainFrame)
  8.         ON_WM_CREATE()
  9.         //}}AFX_MSG_MAP
  10. END_MESSAGE_MAP()

10. 파일 열기 메뉴 사용하기

VC++이 기본적으로 제공하는 OnFileOpen()함수를 Overriding(재정의)해서 사용하면된다. View Class에서 "ID_FILE_OPEN"을 사용하여 매크로 함수를 만들고 아래와 같이 소스를 입력하면 된다.

1) View Class에서 마우스 오른쪽 버튼을 클릭한후 "Add Windows Message hadler"를 선택한다.

2) Class or object to handle에서 "ID_FILE_OPEN"을 선택한후 Add Handler를 선택하여 함수를 생성한다.

3) 만들어진 함수에 아래의 코드를 추가한다.

  1. void CWebBrView::OnFileOpen()
  2. {
  3.         CString str="*.htm;*.html";
  4.         CFileDialog fileDlg(TRUE, NULL, str, OFN_HIDEREADONLY,str);
  5.         if(fileDlg.DoModal() == IDOK)
  6.         {
  7.                 m_WebBr.Navigate(fileDlg.GetPathName(),NULL,NULL,NULL,NULL);
  8.         }
  9.      

'C/C++/MFC' 카테고리의 다른 글

CWnd 클래스  (0) 2009.01.05
포인터 사용법  (0) 2009.01.05
[API]버튼만들기  (0) 2009.01.02
Invalidate() , OnDraw(CDC* pDC)  (0) 2009.01.02
MFC (디바이스 컨텍스트와 관련 클래스)  (0) 2008.12.30
posted by 유돌이