티스토리 뷰

MFC

MFC (Microsoft Foundation Classes)

열혈허슬러 상추님 2019.09.23 16:44
190715

 
매니패스트
형식메타데이터
CIL CODE
[리소스]
닷넷은 독립적인 라이브러리(.net 프레임워크)를 사용한다.
 
MFC : Windows os 의 바이너리만 만들 수 있다.
닷넷은 CLR만 있으면 다른 운영체제에서도 가능하다.
 
우리는 MFC를 공부해볼 것이다.
MFC는 c++을 사용해서 윈도우즈 개발을하는데 라이브러리 이름이 MFC인 것이다.
 

 
IL DASM
형식 데이터(?) (ctrl+m)
 

 
  • MFC (90년대 초) (프레임워크 프로그래밍 공부하기 좋다.)
- Afx 가 앞에 붙어있는 함수들은 전역함수다.
 
AfxGetApp() : 주소를 반환하는데 CWinApp 객체의 주소를 반환한다.
 
FrameWork 프로그래밍 : 이미 구조가 만들어져있고 그 위에서 하는 프로그래밍. (정형화)
 
먼저 구조를 이해 해야한다.
 
● 디자인 패턴 : 설계를 함에 따라 얻는 이점.

● 선언 : 미리알림, 간략한 정보, 컴파일러에게 알림
● 모든 정보 : 모든 정보, 컴파일러와 링크할 때 필요,
 
 
CFirstApp::ExitInstance(가상함수) 
CFirstApp::InitInstance(가상함수) 를 오버라이딩 하여 사용한다.\
가상함수가 아닌것을 오버라이딩하면 잘리는현상이 발생(슬라이스?)
 
재정의를 해보자
 
Run : 에서 getMessage, Dispatch가 된다.
 
- 부모클래스가 virtual이면 자식클래스에서 virtual은 생략가능
 
- 메세지 핸들러 함수 
WM_LBUTTONDOWN -> OnLButtonDown(...) 핸들러함수 (메세지에 대한 핸들러함수)
 
AfxMessageBox(_T("Click!")); // 전역함수를 사용한 메세지 박스 생성
 
void CFirstView::OnLButtonDown(UINT nFlags, CPoint point)
{
    // TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.
    CString str;
    str.Format(_T("click : %d, %d"), point.x, point.y);
    AfxMessageBox(str);
    CView::OnLButtonDown(nFlags, point);
}
 
AfxMessageBox(str.operator LPCWSTR()); // 사실 이 함수가 호출된 것이다.
 
- 메세지 맵 : 연결해준다.
 
Ctrl+Shift+x : 클래스에서 할 수 있는 모든 동작을 할 수 있다.
 
void CFirstView::OnLButtonUp(UINT nFlags, CPoint point)
{
    // TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.
    CClientDC dc(this); // this : view 객체 // 소멸자 있기에 ReleaseDC 안해줘도된다.
    dc.Ellipse(point.x - 50, point.y - 50, point.x + 50, point.y + 50);
    CView::OnLButtonUp(nFlags, point);
}
- 클릭하면 원 그리기
void CFirstView::OnLButtonUp(UINT nFlags, CPoint point)
{
    CDC* pDC = this->GetDC(); // (현재객체는 view) view의 DC객체를 얻는다
    pDC->Ellipse(point.x - 50, point.y - 50, point.x + 50, point.y + 50);
    this->ReleaseDC(pDC);
    CView::OnLButtonUp(nFlags, point);
}
- 위 코드와 동일한 기능을 함
void CFirstView::OnLButtonUp(UINT nFlags, CPoint point)
{
    {
        HDC hdc;
        HWND hwnd = m_hWnd;
        hdc = ::GetDC(hwnd); // 시스템 라이브러리에 있는 전역적인 GetDC() 사용
        ::Ellipse(hdc, point.x - 50, point.y - 50, point.x + 50, point.y + 50);
        ::ReleaseDC(hwnd, hdc);
    }
    
    CView::OnLButtonUp(nFlags, point);
}
- MFC를 전혀 안쓰고 쓴 코드(절대 이렇게 안함. 예시로서 참고)
    {
        HDC hdc;
        HWND hwnd = this->GetSafeHwnd; // getter 사용(안전)
        hdc = ::GetDC(hwnd); // 시스템 라이브러리에 있는 전역적인 GetDC() 사용
        ::Ellipse(hdc, point.x - 50, point.y - 50, point.x + 50, point.y + 50);
        ::ReleaseDC(hwnd, hdc);
    }
 
DC객체를 그대로 써도 되고, pDC(포인터)를 써도된다.
- 앞에 C는 Class를 뜻한다.
 

 
- 눌렀다가 뗐을 때 원을 그려보자
눌렀을 때 좌표 데이터를 어디에 보관? 전역변수는 되도록 쓰지 않는다.
View멤버변수를 만든다.
 
초기화를 해야한다.
cf. 
 noexcept : 예외를 발생시키지 않는다.
 
void CEllipView::OnLButtonDown(UINT nFlags, CPoint point)
{
    m_rect.left = point.x;
    m_rect.top = point.y;
    CView::OnLButtonDown(nFlags, point);
}
 
void CEllipView::OnLButtonUp(UINT nFlags, CPoint point)
{
    m_rect.right = point.x;
    m_rect.bottom = point.y;
 
    CClientDC dc(this);
    dc.Ellipse(m_rect);
 
    CView::OnLButtonUp(nFlags, point);
}
- 이후에 멤버 변수를 활용하여 좌표를 저장해놓고 원을 draw할 수 있다.
 

 
객체를 생성하는 방법
1. 값으로 생성
2. 참조로 생성
 
 
- MFC는 캡슐화가 약한 라이브러리이다.
 
#CEllipDoc* pDoc = this->GetDocument();
doc 객체에 있는 ArrayList를 참조하여 여러개의 원을 그리는 작업
 
- 특별한 경우가 아니면 doc에 데이터를 보관하고, view에서는 draw 작업을 한다.
 
- 마우스 휠을 사용해 확대/축소 가능한 코드
void CEllipView::OnLButtonDown(UINT nFlags, CPoint point)
{
    m_rect.left = point.x;
    m_rect.top = point.y;
 
    
 
    CView::OnLButtonDown(nFlags, point);
}
 
void CEllipView::OnLButtonUp(UINT nFlags, CPoint point)
{
    m_rect.right = point.x;
    m_rect.bottom = point.y;
    
    CEllipDoc* pDoc = this->GetDocument();
    pDoc->m_ptList.Add(m_rect);
 
    CClientDC dc(this);
    DrawEllipse(&dc,m_rect);
 
    CView::OnLButtonUp(nFlags, point);
}
 
 
void CEllipView::OnPaint()
{
    CPaintDC dc(this); // device context for painting
                     // TODO: 여기에 메시지 처리기 코드를 추가합니다.
                     // 그리기 메시지에 대해서는 CView::OnPaint()을(를) 호출하지 마십시오.
    CEllipDoc* pDoc = this->GetDocument();
 
    for (int i = 0; i < pDoc->m_ptList.GetSize(); i++)
    {
        //dc.Ellipse(pDoc->m_ptList[i]);
        DrawEllipse(&dc, pDoc->m_ptList[i]);
    }
}
 
void CEllipView::DrawEllipse(CDC* pDC, const CRect& rt) {
    
    CRect drt = CRect(
        rt.left - m_scaleSize,
        rt.top - m_scaleSize,
        rt.right + m_scaleSize,
        rt.bottom + m_scaleSize);
    pDC->Ellipse(drt);
    
}
 
BOOL CEllipView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
    if (zDelta>0) {
        m_scaleSize += 2;
    }
    else {
        m_scaleSize -= 2;
    }
    this->Invalidate();
    return CView::OnMouseWheel(nFlags, zDelta, pt);
}
 
댓글
댓글쓰기 폼