posted by nsakura 2010. 7. 22. 18:03

솔직히 지루함을 느꼈을것이다.

해봤자 원 선 점 사각형밖에 더 그렸나.

지금 부터 할것은 그림을 출력하는것이다.

일단 출력하고싶은 그림을 준비하고. [단 bmp파일]

비트맵 리소스를 준비한다.

임포트 버튼을 눌러 준비한 bmp파일을 선택하면되는데.

에러가 뜬다. 그런데 이 에러난 색상때문인데.

256이상이면 이런 에러가 뜬다 정확히는 vc++에서 지원하는 비트맵 에디터로 편집을 못한다 라는것이지 사용을 못한다는건 아니다.

일단 바로 예제로 넘어가 보자.

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam){
 HDC hdc,memDC;
 PAINTSTRUCT ps;

 HBITMAP testBitmap, saveBitmap;

 switch(iMessage){
 case WM_PAINT:
  hdc=BeginPaint(hWnd,&ps);
  
  memDC=CreateCompatibleDC(hdc);
  testBitmap=LoadBitmap(wndnsakura,(TCHAR *)IDB_BITMAP1);
  saveBitmap=(HBITMAP)SelectObject(memDC,testBitmap);
  BitBlt(hdc, 0,0,827,837,memDC,0,0,SRCCOPY);
  SelectObject(hdc,saveBitmap);
  DeleteObject(testBitmap);
  DeleteDC(memDC);

  EndPaint(hWnd,&ps);

  return 0;
 
 case WM_DESTROY:
  PostQuitMessage(0);
  return 0;
 }

 return (DefWindowProc(hWnd,iMessage,wParam,lParam));
}

지금까지 그래픽에 대한 코드를 실습해왔지만 이번에는 조금 다르다라고 생각하지 않는가?

솔직히 말하지만.

그림은 우리가보기에는 단순히 그림이지만 컴퓨터로 따지만 꾀 큰 자료이고 복잡하다.

그렇기 때문에 바로 선,사각형 원을 그리듯 바로 화면에 출력하는 함수는 제공하지 않는다.

그래서 그림을 출력하기위해서는 준비가 필요하다.

메모리DC를 이용하는 방법인데. 메모리 DC는 화면과 동일한 특성을 가지는데.

그림을 1차적으로 메모리 dc먼저 그린후 사용자 눈에 그려지는 과정은 보여주지 않고 그 결과만 화면으로 고속 복사하는 방법

인것이다. 뭐 전문 용어로 더블 버퍼링이라 한다.

그럼 메모리DC를 만드려면 어떻게 해야할까?

memDC=CreateCompatibleDC(hdc);

이 부분이 메모리 DC를 만드는 라인이다.

함수 원형은 HDC=CreateCompatibleDC(HDC);

인수로 화면 DC의 핸들을 주면 리턴값으로 화면 dc와 동일한 특성을 가진 메모리 dc를 만들어 반환한다.

역시 비트맵 출력역시 GDI 오브젝트임으로 SelectObject함수를 사용한다 .

비트맵을 읽어올때는

HBITMAP LoadBitmap(HINSTANCE hInstance,LPCTSTR lpBitmapName);

함수를 사용하며 첫번째 인수는 비트맵 리소스를 가진 인스턴스 핸들

두번째 인수는 비트맵 리소스의 이름 이다.

그리고 고속 복사를 하기위한 함수가.

BitBlt(hdc, 0,0,827,837,memDC,0,0,SRCCOPY); 이며

원형은

BOOL BitBlt(HDC hdcDest,int nXDest, int nYDest, int nWidth, int nHeight,HDC hdcSrC, int nXsrc,int nYsrc, DWORD dwRop);

첫번째 인자는 복사 대상이 DC이며  그다음 4개의 인수는 복사 대상의 위치 높이와 폭을 말한다.

hdcSrc가  복사원의 DC이다 nXSrc,nYSrc는 복사원의 좌표이되 bitblt은 비트맵의 크기를 변경하지 않고

복사를 수행하므로 폭과 높이는 복사 대상에서 한 번만 지정하고 복사원에서는 이 값을 그대로 사용한다.

마지막 인수는 dwRop는 래스터 연산 방법을 지정한다  dwRop의 값은 다음 표와 같다.

 BLACKNESS  대상 영역을 검정색으로 가득채운다 
 DSTINVERT  화면을 반전시킨다
 MERGECOPY  소스 비트맵과 대상 화면을 AND연산한다
 MERGEPAINT  소스 비트맵과 대상 화면을 OR연산한다
 SRCCOPY  소스 영역을 대상 영역에 복사한다.
 WHITENESS  대상영역을 흰색으로 채운다.


역시 사용을 다하면 메모리dc를 해제해야한다.

DeleteDC(memDC);

이부분이 되겠다.

참고로 BitBlt외에 

StrtchBlt도 있다.

BOOL StrtchBlt(HDC hdcDest,int nXOriginDest, int nYOriginDest, int nWidthDest, int nHeightDest,HDC hdcSrC, int nXOriginSrc,int nYOriginSrc,int nWidthSrc,int nHeightSrc DWORD dwRop);

이 함수는 BitBlt와 달리 비틈맵의 확대및 축소가 가능하다.

궁금하면

StretchBlt(hdc,0,0,827,837,memDC,0,0,8270,8370,SRCCOPY);

이렇게 사용해보자.

참고로 위의 소스는 효율적이 코드는 아니다.

이 점 알아두라.


아래 코드는 솔직히 말해서 귀찮지 않나? 매번 비트맵을 출력할때마다 귀찮게 선언했다 해제했다..

불편하다, 그래서 이렇게 비트맵을 그려주는 함수를 따로 만들었는데.

예전같으면 상당히 안좋았다. 그런데 지금은 하드웨어 기술이 너무 발전되서 이정도 코드는 허용 범위라고 한다.

void DrawBitmap(HDC hdc, int x, int y, HBITMAP hBit){

 HDC memDC;
 HBITMAP saveBitMap;
 int xSize,ySize;
 BITMAP bit;
 
 memDC=CreateCompatibleDC(hdc);
 saveBitMap=(HBITMAP)SelectObject(memDC,hBit);

 GetObject(hBit,sizeof(BITMAP),&bit);
 xSize=bit.bmWidth;
 ySize=bit.bmHeight;

 StretchBlt(hdc,0,0,827,837,memDC,0,0,827,837,SRCCOPY);

 SelectObject(memDC,saveBitMap);
 DeleteDC(memDC);

}

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam){
 HDC hdc;
 PAINTSTRUCT ps;

 static HBITMAP testBitmap;

 switch(iMessage){
 case WM_CREATE:
  testBitmap=LoadBitmap(wndnsakura,(TCHAR*)IDB_BITMAP1);
  return 0;
 case WM_PAINT:
  hdc=BeginPaint(hWnd,&ps);
  
  DrawBitmap(hdc,10,10,testBitmap);

  EndPaint(hWnd,&ps);

  return 0;
 
 case WM_DESTROY:
  DeleteObject(testBitmap);
  PostQuitMessage(0);
  return 0;
 }

 return (DefWindowProc(hWnd,iMessage,wParam,lParam));
}

그냥 알아두면 좋을것이라는 생각에 올린다. 개인적으로는 아래쪽 함수를 사용한 쪽을 선호하는 편이다.



'Computer > Win API' 카테고리의 다른 글

WinApi 그래픽 [TEXT COLOR]  (0) 2010.07.23
WinApi 그래픽[폰트]  (0) 2010.07.22
WinApi RopMode2 [확장]  (0) 2010.07.22
WinApi 그래픽 [DrawMode]  (1) 2010.07.22
WinApi 그래픽 [투명 오브젝트]  (0) 2010.07.22