20160205 - MFC : 4. CPaintDC 를 살펴보던 중, 여러 DC 들 또한 잠시 살펴보자.

2016. 2. 5. 11:31·TEMP/내용 정리중인 글들..
DC란 Device Context의 약자이며, 요즘은 Display Context라고도 불립니다.
 
원래의 정확한 의미는 Device Context 안에 Display Context가 있는 것이 맞습니다.
 
여기서 Context란 동작을 위해 자기자신이 유지하고 있는 값을 의미하고, Context의 특성은 현재성이 강하며 휘발성이라는 점을 띕니다.
 
DC는 MFC Application에서 화면에 무언가 작업을 출력시켜야 할 때 Windows에서 권한을 갖고와야 사용이 가능한 객체입니다.
 
MFC에서 DC와 관련된 클래스는 대표이면서 부모 클래스인 CDC가 있고 그 자식 클래스로는 CClientDC, CWindowDC, CPaintDC 총 3가지가 존재합니다.
 
 
 
 
우선 CClientDC에 대해서 설명을 드리겠습니다.
 

<그림 1 Client Area>

 

 

CClientDC는 [그림 1]의 빨간 영역의 Client Area의 권한을 획득하는 클래스이며, 이 영역안에서만 작업을 할 수 있습니다.
 
기본적으로 Windows가 생성이 되면 CClientDC가 생성이 됩니다.
 
코드에서 사용하는 방법을 설명드리겠습니다.
 
//마우스 왼쪽 버튼을 클릭한 후 띄었을 때 들어오는 메세지는 WM_LBUTTONUP이다.
//ClassWizard에서 WM_LBUTTONUP을 선택하여 더블클릭하면 핸들러가 생성됩니다.
//첫번째 인자값 nFlags는 ctrl키나 shift키가 마우스 왼쪽 버튼과 동시에 눌렸는지
//확인 할 수 있는 값입니다.
//두번째 인자값 point는 마우스의 x, y좌표를 갖고있는 값입니다.
void CTestDCDlg::OnLButtonUP(UINT nFlags, CPoint point)
{
        //인자값의 this는 CClientDC가 어떤 Widnow가 사용할 것인지 알려야 하기 때문에,
        //현재 자신의 Window라는 의미로 this를 인자값으로 넘긴다.
        CClientDC dc(this);

        //사각형이나 원형을 그리는 함수를 사용하기 위해서는 dc객체가 꼭 필요하다.
        //Rectangle함수는 클릭된 마우스 포인터 x, y좌표로부터 사각형을 그리는 클래스이다.
        //클릭된 마우스 포인터 x, y좌표로부터 +20 만큼의 사각형을 생성한다.
        dc.Rectangle(point.x, point.y, point.x + 20, point.y + 20);

        //마우스 왼쪽 버튼과 동시에 눌린 키가 ctrl 일경우
        if ( nFlags & MK_CONTROL)
        {
             //Ellipse함수는 클릭된 마우스 포인터 x, y좌표로부터 원형을 그리는 클래스이다.
             //클릭된 마우스 포인터 x, y좌표로부터 +20 만큼의 원형을 생성한다.
             dc.Ellipse(point.x, point.y, point.x + 20, point.y + 20);
        }
}//OnLButtonUP
 
 
 
 
다음으로 소개드릴 클래스는 CWindowDC입니다.
 
CWindowDC는 CClientDC와 클래스의 사용 방법 등 모든것이 비슷하지만, 얻는 영역의 범위가 다릅니다.
 
CClientDC는 Client Area만 획득했다면, CWindowDC는 모니터 전체의 영역을 획득합니다.
 
즉, 자신의 Window를 포함하여 다른 Window의 영역도 건드릴 수 있다는 뜻이 됩니다.
 
코드에서 사용 하는 방법을 알려드리겠습니다.
 
//CWindowDC는 어떤 하나의 Window가 사용 하는것이 아니기 때문에 NULL값을 인자로 넘긴다.
CWindowDC dc(NULL);
 
 
 
 
맨 위의 소스 중에서 CClientDC를 선언하는 부분만 지금의 소스처럼 변경하면 사각형이나 원형을 그리는 함수는 똑같이 사용됩니다.
 
그럼 CWindowDC와 CClientDC가 사용하는 소스가 선언부만 다르고 사용하는 방법이 똑같다면 비효율적이지 않느냐 라는 생각을 하실 수도 있을텐데요
 
그래서 MFC에서는 다형성을 위해 성격이 비슷한 두 클래스의 부모클래스인 CDC를 제공합니다.
 
다형성을 이용하여 코드에서 사용하는 방법을 알려드리겠습니다.

void CTestDCDlg::OnLButtonDOWN(UINT nFlags, CPoint point)
{
        //CWindowDC의 권한을 획득하고
        CWindowDC dc(NULL);

        //DrawMyShape() 함수를 호출합니다.
        DrawMyShape(&dc, point);
}//OnLButtonDOWN
 
void CTestDCDlg::OnLButtonUP(UINT nFlags, CPoint point)
{
        //CClientDC의 권한을 획득하고
        CClientDC dc(this);

        //DrawMyShape() 함수를 호출합니다.
        DrawMyShape(&dc, point);
}//OnLButtonUP

//DrawMyShape() 함수는 CDC의 포인터를 첫번째 인자로 넘겨받고
//두번째 인자로 마우스의 x, y좌표를 가진 CPoint함수를 넘겨받습니다.
void CTestDCDlg::DrawMyShape(CDC *paramDC, CPoint point)
{
        //CDC함수는 CWindowDC와 CClientDC의 다형성을 위해 만들어진 부모클래스 이므로, 
        //CDC클래스의 포인터로 접근하여 사용이 가능합니다.
        paramDC->Rectangle(point.x, point.y, point.x + 20, point.y + 20); 
}//DrawMyShape
 
 
 
 
다음으로 소개할 클래스는 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부터 다시 그려내는 방식이기 때문에 반복문이 길어질 경우 안좋은 결과를 낼 수도 있습니다.
 
 
 
 
다음은 Bitmap이라는 객체에 대해서 알아보겠습니다.
 
Bitmap은 그림을 그리는데 관련된 모든 정보를 갖고 있습니다.
 
도형을 그릴 때 색상이라던지 선의 굵기라던지 이런 정보는 모두 Bitmap 객체에 해당됩니다.
 
MFC에서는 선의 개념을 Pen이라 부르며, 채우는 개념을 Brush라 합니다.
 
이 두개의 개념 또한 클래스가 따로 존재하며, CPen과 CBrush로 제공됩니다.
 
 
 
 
CPen은 선에 관한 정보를 갖는 클래스이며, 선의 속성(점섬 또는 실선), 선 굵기, 선 색상을 관리합니다.
 
코드에서 사용 하는 방법을 설명드리겠습니다.
 
 //CPen 객체를 생성 하고 인자값으로 선의 속성과, 선의 굵기, 선의 색상을 넘깁니다.
//첫번째 인자(선의 속성)은 PS_SOLID(실선)와 PS_DOT(점선) 2개가 있습니다.
//두번째 인자(선의 굵기)는 숫자가 커질수록 굵기도 커지는 형태입니다.
//선의 속성이 PS_DOT일 때는 선의 굵기가 1이 아니면 점선으로 표현되지 않습니다.
//세번째 인자(선의 색상)은 RGB(0~255, 0~255, 0~255)로 표현됩니다.
CPen redPen(PS_SOLID, 1, RGB(255, 0, 0));
CPen greenPen(PS_SOLID, 2, RGB(0, 255, 0));
CPen bluePen(PS_DOT, 1, RGB(0, 0, 255));
 
 
 
 
CBrush는 채우기에 관한 정보를 갖는 클래스입니다.
 
코드에서 사용하는 방법을 설명드리겠습니다.
 
//Brush 객체를 생성 하고 인자값으로 RGB(0~255, 0~255, 0~255)값을 넘겨줍니다.
CBrush redBrush(RGB(255, 0, 0));
CBrush greenBrush(RGB(0, 255, 0));
CBrush blueBrush(RGB(0, 0, 255));
 
 
 
 
CPen과 CBrush를 사용할 때의 주의 할 점은 지역변수로 선언 했을 시 범위를 벗어나게되면 dc로 객체를 그려 낼 시 색상이 사라져 표현해내지 못합니다.
 
이런 문제점을 해결하기 위해 CDC의 SelectObject() 라는 함수를 사용하게 됩니다.
 
이 함수는 CPen이나 CBrush 객체를 인자로 넘겨 색상을 변경하게 하고 반환값으로 이 전 색상값을 줍니다.
 
코드에서 사용하는 방법을 설명드리겠습니다.
 
void CTestDCDlg::DrawMyShape(CDC *paramDC, CPoint point)
{
        //CPen객체를 굵기 1의 빨간색 실선으로 생성합니다.
        CPen redPen(PS_SOLID, 1, RGB(255, 0, 0));

        //이 전 색상을 저장하기 위해 CPen의 포인터 객체를 생성합니다.
        //CDC의 포인터에 접근하여 SelectObject() 함수를 호출하고,
        //인자값으로 redPen변수의 주소를 넘깁니다.
        //현재 선의 색상은 빨간색으로 지정되었고, oldPen에는 이 전 색상이 저장되어있습니다.
        CPen *oldPen = paramDC->SelectObject(&redPen);

        //사각형의 선부분을 빨간색으로 지정하며 그려낸다.
        paramDC->Ractangle(point.x, point.y, point.x + 20 point.y + 20);
        
        //CDC의 포인터에 접근하여 oldPen의 주소를 넘깁니다.
        //이 전의 색상으로 돌려놓는 작업입니다.
        paramDC->SelectObject(oldPen);
}//DrawMyShape
 
 
 
CPen이나 CBrush는 그래픽 리소스를 사용하기 때문에 GDIObject라고도 부르는데 이 GDIObject들은 리소스를 사용하고 나서는 다시 반환을 해줘야합니다.
 
시스템 리소스는 제한이 되어 있기 때문에 사용 후에 명시적으로 해지를 해줘야하며, 리소스가 부족하게 되면 자신의 Application에서만 사용을 못하는 것이 아니라 OS 자체에 피해를 끼치기 때문에 꼭 반환을 해줘야 합니다.
 
 
코드에서 사용하는 방법을 알려드리겠습니다.
 
바로 위의 DrawMyShape함수 중 paramDC->SelectObject(oldPen); 코드 이후에 사용을 하면 됩니다.
void CTestDCDlg::DrawMyShape(CDC *paramDC, CPoint point)
{
        ...

        //GDI Object인 CPen을 사용한 후 리소스를 해지한다.
        redPen.DeleteObject();
}//DrawMyShape
 
 
 
GDI 객체를 지역변수로 사용 할 시 항상
 
객체 생성 -> 이전 색상 백업 -> 도형 그리기 -> 이전 색상 설정 -> 객체 파괴
 
순서로 코딩을 하시면 됩니다.
 
항상 이 순서를 기억하고 습관을 들이는게 중요하겠죠 
 
 
 
 
그리고 GDI 함수중에서 SelectStockObject() 함수라는 것이 있는데, 이 함수는 Brush를 그리는지 Pen을 그리는지 구분을 할 수 없어 캐스팅 작업을 해줘야 합니다.
 
이 함수는 색상을 RGB(0~255, 0~255, 0~255)로 색상을 지정하는 것이 아닌 Stock의 의미로 지정된 색상을 사용하는 방식입니다.
 
코드에서는 아래의 소스처럼 사용하시면 됩니다.
 
//CClientDC 권한을 획득하고
CClientDC dc(this);

//oldBrush를 CBrush 포인터 객체로 생성한다.
CBrush *oldBrush = NULL;

//SelectStockObject() 함수를 사용하여 색상을 저장하기 위해 (CBrush *)로 캐스팅 해준다.
oldBrush = (CBrush *)dc.SelectStockObject(BLACK_BRUSH);

...

//dc작업을 완료 했으면 다시 원래 색상으로 지정한다.
dc.SelectObject(oldBrush);
 
 
 
 
다음은 지금까지 배운내용을 토대로 오목을 만들어 보겠습니다.
 
이 소스는 프로젝트의 Full 소스는 아니지만 어제 배운 모든 기능이 다 들어가있으니 프로젝트를 생성해서 한번 사용해 보세용. 
 
<MfcOmokDlg.h>
//바둑판의 x축과 y축의 칸을 10개로 지정
#define GRID_X_COUNT 10;
#define GRID_Y_COUNT 10;

class CMfcOmokDlg : public Dialog
{
        //전역변수로 바둑 돌을 몇개 놓았는지 확인하는 Count변수 선언
        private int mCount;

        //흰돌인지 검은돌이지 확인하기 위해 2차원 배열로 선언
        char mDolData[GRID_Y_COUNT + 1][GRID_X_COUNT + 1];
}
 
<MfcomokDlg.cpp>
BOOL CMfcOmokDlg::OnInitDialog()
{
        CDialog::OnInitDialog();

        ...

        //전역변수 mCount를 초기화 시킨다.
        mCount = 0;
        
        //mDolData의 모든 데이터를 초기화 시키기 위해 반복문을 실행한다.
        for(int y = 0; y <= GRID_Y_COUNT; y++)
        {
                for(int x = 0; x <= GRID_X_COUNT; x++)
                {
                        mDolData[y][x] = 0;
                }
        } 
}//OnInitDialog

void CMfcOmokDlg::OnPaint()
{
        if ( IsIconic())
        {
                ...
        }
        else
        {
                //WM_PAINT메세지가 발생 했을 시 다시 그려내기 위해 CPaintDC의 권한을 얻는다.
                CPaintDC dc(this);

                int x, y;
                
                //반복문을 돌며 y축부터 define한 칸 수 만큼 바둑판을 그려낸다.
                for ( y=0; y<GRID_Y_COUNT; y++)
                {
                        for ( x=0; x<GRID_X_COUNT; x++)
                        {
                                //Client Area의 (0, 0)부터 시작하면 바둑돌을 놓을 수 없는 현상이 발생할 수 있으니,
                                //Client Area의 x, y축에 20씩 더한 후 판을 그려나간다.
                                //선을 그리면서 판을 그릴 수도 있지만, 사각형을 여러개 그려 판을 그릴 수도 있따.
                                //하나의 사각형을 그린 후에 그 다음번 사각형과 겹치지 않게 *연산을 사용하여 그려나간다.
                                dc.Rectangle(20 + 20*x, 20 + 20*y, 20 + 20*x + 21, 20 + y*20 + 21);
                        }
                }

                //CBrush의 포인터객체를 생성한다.
                CBrush *pOldBrush = NULL;

                //define한 칸의 갯수만큼 반복한다.
                for(y = 0; y <= GRID_Y_COUNT; y++)
                {
                        for(x = 0; x <= GRID_X_COUNT; x++)
                        {
                                //해당 index의 데이터값이 1이면
                                if(mDolData[y][x] == 1)
                                {
                                        //이전 색상인 흰색을 저장하고 검은색으로 지정한다.
                                        pOldBrush = (CBrush *)dc.SelectStockObject(BLACK_BRUSH);

                                        //해당 좌표에 검은색 돌을 그려내고
                                        dc.Ellipse(20 + x*20 - 9, 20 + y*20 - 9, 20 + x*20 + 9, 20 + y*20 + 9);

                                        //이전 색상인 흰색으로 다시 지정한다.
                                        dc.SelectObject(pOldBrush);
                                }
                                //해당 index의 데이터 값이 2면
                                else if(mDolData[y][x] == 2)
                                {
                                        //해당 좌표에 흰색 돌을 그린다.
                                        dc.Ellipse(20 + x*20 - 9, 20 + y*20 - 9, 20 + x*20 + 9, 20 + y*20 + 9);
                                }
                        }
                }
        }
}//OnPaint

void CMfcOmokDlg::OnLButtonUP(UINT nFlags, CPoint point)
{
        //마우스의 포인터가 바둑판 영역 밖을 클릭 할 수 없도록 설정한다.
        //하지만 해당 좌표를 20으로 나눈 후 10보다 크면 오른쪽에 돌을 놓게 하고,
        //10보다 작으면 왼쪽에 돌을 놓게 하기 위해, 
        //마우스의 포인터도 바둑판의 바깥쪽으로 10만큼의 영역을 선택 할 수 있게 설정한다.
         if(point.x < 10 || point.y < 10 || point.x >= 20*GRID_X_COUNT + 30 || point.y >= 20*GRID_Y_COUNT + 30)
        {
                //이 범위가 아닐 경우 return한다.
                return;
        }


        //오목 돌을 좌표에 맞게 놓기 위해 바둑판 사각형 하나의 크기인 20으로 나눈다.
        int x = point.x/20;
        int y = point.y/20;

        //20으로 나눈 후 마우스의 포인터가 10보다 크면 x, y의 값을 1 증가시켜 오른쪽에 돌을 놓고, 
        //10보다 작으면 왼쪽에 돌을 놓는다.
        if(point.x%20 >= 10)
        {
                x++;
        }
        if(point.y%20 >= 10)
        {
                y++;
        }

        //index번호에 존재하는 돌의 값이 0보다 크면,
        //좌표에 돌이 놓아져 있을 경우 다시 돌을 놓을 수 없게 한다.
        if(mDolData[y - 1][x - 1] > 0)
        {
                return;
        }

        //돌을 놓은 후, 돌의 index번호에 존재하는 돌이 흑돌인지 백돌인지 구분하기 위해 +1을 한다.
        mDolData[y - 1][x - 1] = (mCount%2) + 1;

        //CClientDC의 권한을 획득하고
        CClientDC dc(this);

        //마우스의 좌표가 20으로 나눠져 있는 값에 다시 20을 곱한다.
        //정수값을 나누었다가 다시 곱하면 나머지 값이 버림연산이 되기 때문에, 
        //바둑판 좌표에 맞게 돌을 놓을 수 있다.
        x *= 20;
        y *= 20;

        //이전 바둑돌 색상(흰색)을 저장하기 위해 CBrush 포인터 변수를 생성
        CBrush *pOldBrush= NULL;

        //바둑돌의 카운트를 지정하는 mCount를 2로 나눠서 0이 아니면, 검은돌을 놓는다.
        if(!(mCount%2))
        {
                //oldBrush 변수에 이전 색상(흰색)을 저장 하고,
                //SelectStockObject() 함수로 검은색을 설정한다.
                p_old_brush = (CBrush *)dc.SelectStockObject(BLACK_BRUSH);

                //마우스 좌표 정 중앙으로부터 돌을 생성한다.
                dc.Ellipse(x - 9, y - 9, x + 9, y + 9);

                //이전 색상(흰색)으로 되돌린다.
                dc.SelectObject(pOldBrush);
        }
        else
        {
                //mCount를 2로 나눠서 0이 나오면 흰돌을 놓는다.
                dc.Ellipse(x - 9, y - 9, x + 9, y + 9);
        }

        //mCount를 증가시킨다.
        mCount++;

        CDialog::OnLButtonUp(nFlags, point);
}//OnLButtonUP
 
 
 
 
강좌들으면서 본 원래 오목 소스에서는 전역변수를 초기화를
 
CMfcOmokDlg::CMfcOmokDlg(CWnd* pParent ) : CDialog(CMfcOmokDlg::IDD, pParent)
{
        ....
}
 
이 부분에서 했었는데, 제가 올린 오목 소스는
 
BOOL CMfcOmokDlg::OnInitDialog()
{
        ...
}
 
이 부분에서 초기화를 했습니다.
 
혹시 이 두 부분에서 초기화를 하면 다른점이 있나요?
설명을 못들은건지 기억이 잘 안나네요...
아시는분이 있다면 리플로 답변 달아주세요!
 
 
 
 
오늘 강좌는 여기까지입니다.
 
오목을 제대로 이해하고 주석을 달아야하는데, 설명하려고 주석을 달아보니 제가 완벽하게 이해를 못했다는걸 깨닫게 되는군요 
 
다들 즐코딩하세요!


'TEMP > 내용 정리중인 글들..' 카테고리의 다른 글

20160211 - MFC : 1. 33번 폼 리스트 값 처리 관련해서 좀 살펴보다가,  (0) 2016.02.11
20160205 - MFC : 5. WM_USER 메시지에 관해 수신 및 처리 에 대해서  (0) 2016.02.05
20160205 - MFC : 3. DDX_Control, 가상 함수 DoDataExchange 함수의 리스트 박스 컨트롤  (0) 2016.02.05
20160205 - MFC : 2. 재정의된 가상 함수.  (0) 2016.02.05
20151124 - 선배꺼 : 영상처리 함수 정리  (0) 2015.11.24
'TEMP/내용 정리중인 글들..' 카테고리의 다른 글
  • 20160211 - MFC : 1. 33번 폼 리스트 값 처리 관련해서 좀 살펴보다가,
  • 20160205 - MFC : 5. WM_USER 메시지에 관해 수신 및 처리 에 대해서
  • 20160205 - MFC : 3. DDX_Control, 가상 함수 DoDataExchange 함수의 리스트 박스 컨트롤
  • 20160205 - MFC : 2. 재정의된 가상 함수.
쭌의 숲 속 도서관
쭌의 숲 속 도서관
  • 쭌의 숲 속 도서관
    쭌의 숲 속 도서관
    쭌의 숲 속 도서관
  • 전체
    오늘
    어제
    • 분류 전체보기 (84)
      • [Programming] Language (13)
        • C (10)
        • JavaScript (2)
        • JavaScript (WEB) (0)
        • TypeScript (0)
        • 기술 면접 (1)
        • Python (0)
      • [Programming] Framework (1)
        • Nest.js (1)
        • Svelte (0)
      • [Cloud] Amazon Cloud (0)
        • AWS-SDK (0)
        • Architecture (0)
        • Lambda (0)
        • IoT Core (0)
        • RDS (0)
      • Language (1)
        • English (1)
      • OS (7)
        • Window (7)
        • Linux (0)
      • Certificate (3)
        • 네트워크 관리사 2급 (2)
        • [기본] AWS Certified Cloud Pr.. (1)
        • [준전문가] AWS Certified Soluti.. (0)
      • 유용한 사이트 (3)
      • 이벤트 및 행사소식 (0)
      • ETC (23)
        • 프로그램 (5)
        • 운동 (8)
        • IT (2)
        • 생활 (2)
        • 쇼핑몰 (3)
        • 제품 후기 (3)
        • 여행 (0)
        • 맛집 (0)
      • TEMP (33)
        • 내용 정리중인 글들.. (33)
  • 블로그 메뉴

    • 홈
    • 태그
    • 미디어로그
    • 위치로그
    • 방명록
  • 링크

    • WoWCat
  • 공지사항

  • 인기 글

  • hELLO· Designed By정상우.v4.10.3
쭌의 숲 속 도서관
20160205 - MFC : 4. CPaintDC 를 살펴보던 중, 여러 DC 들 또한 잠시 살펴보자.
상단으로

티스토리툴바