본문 바로가기

카테고리 없음

[MFC] 마우스로 여러개의 사각형 그리기.

다음으로 소개할 클래스는 CPaintDC 입니다.
 
CPaintDC는 WM_PAINT라는 Flag성 메세지가 발생 했을 때 사용해야 하는 클래스입니다.
 
Window는 Message가 들어오는 곳이 Message Queue와 Message Table 2개가 있는데,
그 중 우선순위로 처리 되는 영역은 Message Queue부분이며, 이 영역의 메세지가 모두 처리되면 Message Table을 처리하게 됩니다.
 
WM_PAINT는 Invaild Area가 Vaild Area로 됐을 시 들어오는 메세지이며, 이 메세지에는 자신이 다시 그려야 할 영역의 값을 포함해서 들어옵니다.
 
WM_PAINT 메세지는 Message Table에 존재하며, 연속해서 발생된다고 그 때 마다 계속 처리되는 메세지가 아니고 메세지가 발생 했을 시 값을 1로 바꾸는 역할을 합니다.
 
CPaintDC는 Message Table의 WM_PAINT값을 확인하고 1로 설정되어 있으면 0으로 바꿔주는 함수입니다.
 
즉, WM_PAINT 메세지가 있을 경우 자신의 Window 화면을 다시 갱신하는 함수입니다.
 
코드에서 사용하는 방법을 알려드리겠습니다.
 
<TestDCDlg.h>
//마우스 좌표를 저장할 공간을 100으로 define한다.
#define MAX_COUNT 100

class CTestDCDlg : public CDialog
{
private :
        //마우스 x, y 좌표를 저장할 POINT 구조체를 생성한다.
        POINT mClickPos[MAX_COUNT];

        //마우스 좌표가 몇개가 저장되었는지 확인하기 위해 Count변수를 생성
        int mClickCount;
}
 

<TestDCDlg.cpp>
BOOL CTestDCDlg::OnInitDialog()
{
        CDialog::OnInitDialog();

        //전역변수인 mClickCount를 0으로 초기화 시켜준다.
        mClickCount = 0;
}//OnInitDialog
 

void CTestDCDlg::OnPaint()
{
        //예전 윈도우는 작업표시줄이 없어 최소화 창을 누르면 아이콘 형식으로 배치됬었다.
        //지금은 작업표시줄이 있어 아이콘 형식으로 배치 되지않는다.
        //아이콘 형식이면 if문 실행
        if ( IsIconic())
        {
                ...
        }
        //아이콘 형식이 아니면 else문 실행
        else
        {
                //CPaintDC 권한을 얻어온다.
                CPaintDC dc(this);

                //저장된 마우스 좌표의 갯수만큼 반복한다.
                for ( int i=0; i<mClickCount; i++ )
                {
                        //DrawMyShape() 함수를 호출한다.
                        DrawMyShape(&dc, mClickPos[i];
                }
        }
}//OnPaint

void CTestDCDlg::OnLButtonUP(UINT nFlags, CPoint point)
{
        //CClientDC의 권한을 획득한다.
        CClientDC dc(this);

        //DrawMyShape() 함수를 호출한다.
        DrawMyShape(&dc, point);

        //전역변수인 mClickPos의 해당하는 index배열에 마우스 x, y좌표를 저장하고,
        //Count수를 증가시킨다.
        mClickPos[mClickCount].x = point.x;
        mClickPos[mClickCount].y = point.y;
        mClickCount++;

        CDialog::OnLButtonUP(nFlags, point);
}//OnLButtonUP

//DrawMyShape() 함수는 CDC의 포인터를 첫번째 인자로 넘겨받고
//두번째 인자로 마우스의 x, y좌표를 가진 CPoint함수를 넘겨받는다.
//OnPaint() 영역에서 두번째 인자로 POINT 구조체를 넘겨받았는데, 
//CPoint() 함수는 원래 POINT 구조체이기 때문에 인자로 받는것이 가능하다.
void CTestDCDlg::DrawMyShape(CDC *paramDC, CPoint point)
{
        //CDC클래스의 포인터로 접근하여 사각형을 그려낸다.
        paramDC->Rectangle(point.x, point.y, point.x + 20, point.y + 20);
}//DrawMyShape
 
 
 
 
OnPaint() 영역에서 도형을 그릴 시 CPaintDC 권한을 얻어 작업을 할 수도 있지만, invalidate() 함수를 사용하여 그려낼 수도 있습니다.
 
하지만 invalidate() 함수는 도형을 그릴 시 해당하는 index 좌표의 도형을 하나씩 하나씩 그려나가는 방식이 아닌, 처음 index부터 다시 그려내는 방식이기 때문에 반복문이 길어질 경우 안좋은 결과를 낼 수도 있습니다.