programming notes

View on GitHub
13 September 2007

MFC 버튼컨트롤에 비트맵 입히기

by

중간 프로젝트에 게임을 제작하면서 게임에 필요한 맵툴을 만들고 있었다.
맵툴에는 게임에 사용하는 맵에 충돌영역 설정과 맵안에 존재하는 사물 등 오브젝트를 박는 작업, 연결된 방으로 이동되는 지점을 설정하는
기능들이 필요했다.

오브젝트를 박는 작업을 할때 버튼으로 오브젝트를 선택하고 맵에 찍으면 간단하기에 그런형식으로 작업을 하는데 버튼에 오브젝트의 종류를 한글로
표현하면 직관적이지 않기때문에 버튼에 비트맵을 입히기로 했다.

근데 버튼에 비트맵을 입히는게 윈도우즈프로그래밍에 공부가 부족해서 많은 삽질을 해서 성공을 했다.

그 방법을 간략하게 적으려 한다.
흔적도 안남기고 까먹어 버리면 나중에 고생하니까.. - -;

mfc로 툴을 만들었기에 mfc클래스들을 사용해서 방법을 적으려한다.
이 작업을 할때는 다이얼로그 박스 스타일로 프로젝트를 만들어서 하였다. 그리고 CWnd를 상속받아 만들어지는 클래스 내부 함수에서 작성한
기준으로 적는다.
이런것까지 적는 이유는 CWnd상속 클래스 함수 내에서만 GetDC()함수가 바로 호출 되서이다.
똑똑하신분들은 아시겟지만..

그럼 천천히 허접한 설명을 시작한다.

리소스 편집기를 통해서 다이얼로그 박스에 버튼 컨트롤을 하나 만든다.

만든다음 이 버튼속성에 Bitmap이라는 속성을 true로 해준다.
false면 적용을 하더라도 이미지가 나오지 않는다.

그런 다음 이 버튼에대한 컨트롤 변수를 추가한다.
설명에서 이 변수의 이름은 m_buttonCtrl으로 하겠다.
그리고 아래와 같이 변수 2개를 더 선언한다.

CButton m_buttonCtrl // 컨트롤 변수임.
CBitmap m_ButtonBitmap ; // 이미지가 저장될 변수
CBitmap& m_pOldButtonBitmap ;

그런 다음 OnInitDialog에서 아래와 같이 코드를 적는다.

BOOL TestDlg::OnInitDialog()
{
    CDC MemDC ; // m_ButtonBitmap 에 이미지를 그리기 위해서임.
    CDC* pTempDC = GetDC() ;
    CImage cimage ;// atl클래스이다 이 클래스 사용을 위해서는 atlimage.h를 포함하면된다
    // 비트맵 파일 로드를 편하기위해서 이 클래스를 사용하였을뿐 다른 방법을 사용해도 된다.
    cimage.Load("파일이름.bmp") ;

    int nWidth = cimage.GetWidth() ;
    int nHeight = cimage.GetHeight() ;

    // --가상 DC와 가상비트맵을 만든다.
    MemDC.CreateCompatibleDC(pTempDC) ;
    m_ButtonBitmap.CreateCompatibleBitmap(pTempDC, nWidth, nHeight) ;
    m_pOldButtonBitmap = MemDC.SelectObject(&m_ButtonBitmap) ;

    cimage.Draw(MemDC.GetSafeHdc(), 0, 0) ; // 가상 비트맵에 로드한 비트맵을 그린다.
    MemDC.SelectObject(&m_pOldButtonBitmap) ; // 반드시 다리 셀렉트해야한다.
    // 안하면 버튼에 이미지 안나옴.
    m_buttonCtrl.SetBitmap(m_ButtonBitmap) ; // 완료!!
}

위와 같은 형식으로 하면된다.
본인은 SelectObject한다음 가상비트맵에 로드한 비트맵을 그린다음에 다시 SelectObject를 안해줘서 엄청 삽질을 했다!!ㅠㅠ
이렇게하면 완료다
그리고 더 간단하게할수도 있다.
멤버변수로 ATL클래스인 CImage를 두고

cimage.Load("파일이름.bmp");
m_ButtonCtrl.SetBitmap(cimage);

위와 같이 두줄이면 끝난다!!

근데 왜 좀 복잡하게 했냐면 본인은 비트맵 파일을 바로 불러온게 아니라 게임에 사용할 이미지들을 툴로 가공을 한 다음에 그 가공된 파일을
로드해서 버튼에 이미지를 입혔기때문이다.
그렇기 위해선 파일을 로드한다음 CBitmap에 이미지 데이터를 저장해야되기때문이다.
그럼 설명은 끝!

중요한것은 가상비트맵 비트맵을 그리기 위해서 SelectObject로 DC와 가상비트맵을 연결한다음 그렸다면 반드시 SetBitmap하기
전에 다시 SelectObject해야된다는것!
위에서도 한얘기지만 본인은 SelectObject을 안해줘서 엄청삽질했다.
본인은 SelectObject를 프로그램 종료시에 사용한 리소스를 삭제하면서 할려고 했기때문이다.

부디 본인과 같이 삽질하는 사람이 없길 바란다!

tags: