본문 바로가기
프로그램 개발(분석, 설계, 코딩, 배포)/2.2 윈도우

MFC 객체간 통신

by 3604 2023. 12. 13.
728x90

출처: https://lumiroot.tistory.com/entry/MFC-%EA%B0%9D%EC%B2%B4%EA%B0%84-%ED%86%B5%EC%8B%A0

프로그램을 작성하다 보면 각 클래스들의 포인터가 필요한 경우가 있습니다. 다음과 같은 방법을 사용하면 각 클래스의 포인터를 얻을 수 있습니다.


App 

   App는 전역변수로 theApp라고 선언되어 있습니다. 만약 이를 사용하고자 한다면 Myprog.h파일의 끝부분에

   extern CMyprogApp theApp;

   라고 선언하면 프로그램의 어디서든 사용가능합니다.

   AfxGetApp()라는 함수를 사용하면 App의 포인터를 얻을 수 있습니다. 
CMyprogView * pView = (CMyprogView *)(pFrame -> GetActiveView ());
CMyprogDoc *pDoc = pView -> GetDocument ();

dlg 에서 Doc pointer 얻는 방법  
GetParent () -> GetSafeHwnd ()
이것은 현재의 윈도우가 속해있는 윈도우 (다시말해서 부모 윈도우) 의 포인터를 구해서 그것의 핸들을 얻는 것입니다.

MainFrame
   MainFrame을 얻는 방법중 가장 간단한 함수는 AfxGetMainWnd입니다.
   다음과같이 사용하면 됩니다.
   CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();

Doc
   Document를 얻는 방법은 View에서는 GetDocument입니다.
   다른 부분에서는 다음과 같이 합니다.
   CMyprogDoc *pDoc = (CMydoc*)(pFrame->GetActiveDocument());

View
   view를 얻어내는 방법은 sdi와 mdi가 약간 다릅니다.
   sdi같은 경우는 아래와 같이 간단히 되지만
   CMyView *pView = (CMyView *)(pDoc->GetActiveView());

   mdi같은 경우는 아래와 같은 복잡한 과정이 필요합니다.

  CMDIChildWnd *pChild =
             (CMDIChildWnd *) pFrame->GetActiveFrame();

   // or CMDIChildWnd *pChild = pFrame->MDIGetActive();
   CMyprogrogView *pView = (CMyprogView *) pChild->GetActiveView();

MDI의 경우 한개의 도큐먼트에 뷰가 여러개 있을 때 도큐먼트에서 뷰를 찾으려면 다음과 같이 합니다.

POSITION pos;
   pos = GetFirstViewPosition();
   for (;pos != NULL;)
   {
      CView *pView = (CView *)GetNextView(pos);
      if (pView->IsKindOf(RUNTIME_CLASS(CMyView)))
         break;
   }

dlg 에서 Doc pointer 얻는 방법

// MainDialog.cpp : implementation file
//
#include "stdafx.h"
#include "Test.h"
#include "MainDlg.h"
#include "Mainfrm.h"
#include "Testdoc.h"
#include "TestView.h"

//Doc 접근
void CMainDialog::OnTestDoc()
{
   //메인프레임을 통해서 CTestView 를 받는다.
    CTestView* pView =
        ( CTestView* )((CMainFrame*)AfxGetApp()->m_pMainWnd)->GetActiveView();

   //View 를 통해서 도큐먼트를 받는다.
    CTestDoc *pDoc;
        pDoc=pView->GetDocument();

    //도큐먼트의 m_strText안에 현재 대화상자의 m_strText를 연결시킨다.
    m_strText=pDoc->m_strText;
    //데이타를 다이얼로그 리소스로 전송
    UpdateData(FALSE);
}

//View 접근
void CMainDialog::OnTestView()
{
   //메인프레임을 통해 View를 받는다.
   CTestView* pView =
   ( CTestView* )((CMainFrame*)AfxGetApp()->m_pMainWnd)->GetActiveView();
    //View안에 있는 m_strText를 현재 m_strText로 저장한다.
    m_strText = pView->m_strText;    
    UpdateData(FALSE);
}

//MainFrame 접근
void CMainDialog::OnTestMainFrm()
{
   //메인트레임에서 m_strText를 받아 현재 대화상자의 m_strText에 연결시킨다.
     m_strText = ((CMainFrame*)AfxGetApp()->m_pMainWnd)->m_strText;    
    UpdateData(FALSE);
}


//View에서 Dialog 포인터 얻기
1.Dialog1을 호출할 View Class에서 MainDialog의 포인터 변수를 선언합니다.
//TestView.h
class CTestView : public CView
{
protected: // create from serialization only
   CTestView();
   DECLARE_DYNCREATE(CTestView)

// Attributes
public:
   CTestDoc* GetDocument();
   CString m_strText;

   CMainDialog* pDlg;

}

void CTestView::OnTestDlg()
{
   2.선언된 포인터 변수에 MainDialog의 포인터를 정의합니다.(메모리에 할당)
    pDlg=new MainDialog;

   3.Dialog Box를 띄웁니다.
    pDlg->DoModal();

   *1.2.3의 과정으로 Dialog1의 포인터는 구해졌습니다
}


//메뉴에서 다이얼로그 박스(MainDialog)를 하나 부릅니다..
//이 다이얼로그 박스에서 버튼을 눌러 또 다른 다이얼로그 박스를 부릅니다
//이걸 다이얼로그 SubDialog라고 하죠..
//SubDialog에서 자신을 부른 다이얼로그 박스의 변수를 억세스하기


//MainDialog에서 SubDialog를 생성했으면 SubDialog에서 View Class의 포인터를 구합니다.
//MainDialog의 포인터는 View Class에 존재하므로 SubDialog에서 View의 포인터를
//먼저구해야 합니다.
void CSubDialog::OnTestMainDialog()
{
         CTestView* pView;
        pView=(CTestView*)((CMainFrame*)(AfxGetApp()->m_pMainWnd))->GetActiveView();
 
    //View Class pointer가 구해졌으면 다끝난거나 다릅없습니다.
      //MainDialog의 int j의 변수에 3을입력하고 싶다면 싶다면..SubDialog에서.
         (pView->pDlg)->j=3;
}


//MainDialog에서 MainFram, View, Doc 클래스를 부르려면
void CMainDialog::GetTest()
{
   CMainFrame* pFrame;
   pFrame  = AfxGetApp()->m_pMainWnd;

   CTestView* pView;
   pView = pFrame->GetActiveView();

   CTestDoc* pDoc;
   pDoc = pView->GetDocument();
}


참고...

// BallSrvrDoc.h : interface of the CBallSrvrDoc class
//
/////////////////////////////////////////////////////////////////////////////
#include "lstnsock.h"
#include "clntsock.h"

class CBallSrvrDoc : public CDocument
{

// Attributes
public:
   CListeningSocket* m_pSocket;

.......
}




BOOL CBallSrvrDoc::OnNewDocument()
{
   CPortDlg Dialog;
   
   if (Dialog.DoModal() == IDOK)
   {
       m_pSocket = new CListeningSocket(this); //클라이언트의 접속 요구를 기다림
   }
   return FALSE;
}



// lstnsock.h : header file
//
class CBallSrvrDoc;

class CListeningSocket : public CSocket
{
public:
   CListeningSocket(CBallSrvrDoc* pDoc);           // protected constructor used by dynamic creation
   DECLARE_DYNAMIC(CListeningSocket);
// Attributes
public:
   CBallSrvrDoc* m_pDoc;
// Operations
public:

// Overrides
   // ClassWizard generated virtual function overrides
   //{{AFX_VIRTUAL(CListeningSocket)
   //}}AFX_VIRTUAL

// Implementation
public:
   virtual ~CListeningSocket();
   virtual void OnAccept(int nErrorCode);
#ifdef _DEBUG
   virtual void AssertValid() const;
   virtual void Dump(CDumpContext& dc) const;
#endif

   // Generated message map functions
protected:        
};
#endif


// lstnsock.cpp : implementation file
//

#include "stdafx.h"
#include "ballsrvr.h"
#include "lstnsock.h"
#include "srvrdoc.h"

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

/////////////////////////////////////////////////////////////////////////////
// CListeningSocket

CListeningSocket::CListeningSocket(CBallSrvrDoc* pDoc)
{
   m_pDoc = pDoc;
}

/////////////////////////////////////////////////////////////////////////////
// CListeningSocket Overridable callbacks

void CListeningSocket::OnAccept(int nErrorCode)
{
   CSocket::OnAccept(nErrorCode);
   m_pDoc->ProcessPendingAccept();
}

**참고************************************************

다이얼로그의 핸들이란 곧 윈도우의 핸들이죠.
CWnd에서 상속받아 만들어진 모든 것들은 다 윈도우입니다.
그렇기 때문에 CWnd에 있는 m_hWnd를 갖고 있죠.
다이얼로그도 마찬가지로 하나의 윈도우이기 때문에 m_hWnd를 갖고 있습니다.
따라서 다이얼로그의 m_hWnd를 사용하시면 됩니다.
예)   CTestDlg dlg;
      HWND hDialog = dlg.m_hWnd;

출처: https://lumiroot.tistory.com/entry/MFC-객체간-통신 [Lumiroot:티스토리]

728x90
반응형