ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • MDI(Multi Document Interface)
    프로그래밍/MFC 2005. 6. 24. 05:38

    오늘은.. 드디어 멀티 도큐먼트..

    먼저 SDI 때와 다른점을 살펴보면..

     

    CMainFrame 클래스가CMDIFrameWnd를 상속 받는다.

    그리고CChildFrame 클래스는CMDIChildWnd를 상속받는다.

    CMDIFrameWndCMDIChildWnd아버지 클래스는 CFrameWnd이다.

     

    App 클래스의InitInstance함수를 보면

    CMultiDocTemplate* pDocTemplate;
     pDocTemplate = new CMultiDocTemplate(
      IDR_BMPTYPE,                                  // 메뉴와 연결된다.
      RUNTIME_CLASS(CMDItest2Doc),
      RUNTIME_CLASS(CChildFrame),          // 차일드프레임..
      RUNTIME_CLASS(CMDItest2View));
     AddDocTemplate(pDocTemplate);

     // create main MDI Frame window
     CMainFrame* pMainFrame = new CMainFrame;       // 부모 프레임..
     if (!pMainFrame->LoadFrame(IDR_MAINFRAME))    // 부모 프레임의 메뉴
      return FALSE;
     m_pMainWnd = pMainFrame;

     // Enable drag/drop open
     m_pMainWnd->DragAcceptFiles();

     

    * PreCreateWindow 함수.

      프레임윈도우가 생성될때, 윈도우 속성을 바꿔주려면 PreCreateWindow함수를

      오버라이딩하여 넘어온 인자를 수정하면 윈도우 속성이 변경된다.

     

    그리고 차일드프레임의 한번 봐줘야 할 함수들은..

    BOOL CChildFrame::PreCreateWindow(CREATESTRUCT& cs)
    {
     // 여기서 cs를 변경시키면 윈도우 속성이 변경된다.

     if( !CMDIChildWnd::PreCreateWindow(cs) )
      return FALSE;

     cs.style = WS_CHILD | WS_VISIBLE | WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU
      | FWS_ADDTOTITLE | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX;

     return TRUE;     // CREATESTRUCT 구조체를 이용해 윈도 스타일을 셋팅..
    }

    void CChildFrame::ActivateFrame(int nCmdShow) // 활성화되었을때 실행되는거였던가 ㅡㅡa
    {
     // TODO: Modify this function to change how the frame is activated.

     nCmdShow = SW_SHOWMAXIMIZED;
     CMDIChildWnd::ActivateFrame(nCmdShow);
    }

     

    이제 창을 하나 더 추가 해보려면 우선..프레임과,독,뷰,  각각 클래스를 추가하여야한다.

    프레임은 CMDIChildWnd , Doc 는 CDocument , 뷰는 에디트 뷰로.. 상속을 받아 생성했다.

    그리고 밑에 부분을 App의 InitInstance 부분에 기본적으로 만들어진부분 밑에다가..끼어 넣는다.

    헤더파일 인클루드도 빼먹지말고..

    CMultiDocTemplate* pDocTemplate2;     ////////////////////////////////////
     pDocTemplate2 = new CMultiDocTemplate(
      IDR_TXTTYPE,                            // 요부분이 리소스의 메뉴와 연결..
      RUNTIME_CLASS(CMyEditDoc),    // 생성한 클래스를 만든다.
      RUNTIME_CLASS(CMyEditFrame),  

      RUNTIME_CLASS(CMyEditView));
     AddDocTemplate(pDocTemplate2);

     

    그리고 텍스트 창의 데이터를 저장하거나 불러오려면.. 텍스트 뷰에 대한 Doc클래스의 

    Serialize함수를 이용한다.CEditView클래스의 멤버함수인SerializeRaw함수만 호출하면

    텍스트 데이터를 저장하거나 읽기를 알아서 수행한다.

    void CMyEditDoc::Serialize(CArchive& ar)
    {
     ((CEditView*)m_viewList.GetHead())->SerializeRaw(ar);
    }

     

    이렇게 하면 창이 두개가 있어 처음에 골라줘야 한다. 귀찮다.. 없애버리자..

    암거나 고르면 기본적으로 창하나가 생성된다. 이것을 바꾸어 사용자가 새문서를 클릭했을때

    그때 창이 생성되게 하려면 App의 InitInstance함수에서

     CCommandLineInfo cmdInfo;
     ParseCommandLine(cmdInfo);

     cmdInfo.m_nShellCommand = CCommandLineInfo::FileNothing;  // 요기부분 추가..
     // Dispatch commands specified on the command line
     if (!ProcessShellCommand(cmdInfo))
      return FALSE;

     

    그럼이제 새파일을 눌르면 창이 생성되게 하려면..

    App에OnFileNew를 오버라이드 하여..

    void CMDItest2App::OnFileNew()
    {      // 오늘 소스에서는 나중에 만든 에디트뷰가 달린걸 생성하게 하였다.
     // TODO: Add your command handler code here
     POSITION pos = GetFirstDocTemplatePosition( ); // 첫번째 Docd의 Position 값을 갖고온다.
     CDocTemplate* pDocTemplate = GetNextDocTemplate(pos); //그값으로 DocTemplate 를 얻음.
     pDocTemplate = GetNextDocTemplate(pos);    // 에디트 뷰를 불러와야하니깐 한번더 간다.
     pDocTemplate->OpenDocumentFile(NULL);   // 오픈한다...NULL이면 새 파일..
    }

    그리고 일반뷰 창 생성 커맨드를 매뉴에다  만든다.

    창이 생성되어 활성화 될때마다메뉴가 바뀌니 곳곳마다 추가한다.

    그리고.. 밑에 함수..

    void CMDItest2App::OnBmp()  // 여기는 App
    {
     // TODO: Add your command handler code here
     POSITION pos = theApp.GetFirstDocTemplatePosition( );  //
     CDocTemplate* pDocTemplate = theApp.GetNextDocTemplate(pos);
     pDocTemplate->OpenDocumentFile(NULL); // NULL이면 새 파일..
    }

    전역변수theApp를 이용하여 EditFrame,일반프레임에도 똑같이 만든다..

    여기까지 대충 MDI 완료.. SDI에서 하던거 다 할수 있단다..

     

    * 분할 뷰에서 분할바 못움직이게 하기.

      CSplitterWnd 를 상속받아 나만의 CMySplitterWnd 클래스를 만들고 마우스 메세지를 가로챈다.

     

    * 클래스의 재사용..

      클래스들을 마우스로 선택후 마우스 오른쪽버튼을 눌러Add to Gallery항목을 선택하면

      겔러리에 등록이 된다.

      다른 프로젝트에서 사용하려면 컴포넌트 추가할때처럼.. Project - Add to Project -

      Components and Control 을 선택하면 추가했을때의 프로젝트명으로 폴더가 있는데

      그안에 파일들을 추가하면 된다.

    * 리소스의 재사용..

      메뉴의 파일 오픈하여 리소스파일을 불러오면 현재 리소스와 불러온 리소스가 양쪽으로 뜬다.

      그럼 남은건 카피 앤 페이스트..

    댓글