'programing'에 해당되는 글 29건

  1. 2010.07.22 WinApi 그래픽[폰트]
  2. 2010.07.22 WinApi 그래픽 [비트맵 bitmap]
posted by nsakura 2010. 7. 22. 22:53

이번에는 폰트에 대해서 실습을 해보자.

폰트도 페이나 브러시와 마찬가지로 gdi 오브젝트이다.

폰트를 만들기 위해서는 CreatePen 함수를 사용한다. 그런데 이 함수 원형은. 인수가 14개나 된다.

하지만 그중 쓰는건 거의 정해져있으니까 걱정할필요는 없다

포스팅하는 본인만 손가락이 아플 뿐 ...

HFONT CreateFont(int,int,int,int,int,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,DWORD,LPCTSTR)

 인수  내용 
 nHeight  폰트의 높이를 논리적인 단위로 지정 값이0이면 디폴트값
 nWidth  폰트의 폭을 지정하되 이값이 0이면 nHeight에서 지정한 높이에 따라 폭을 자동으로 결정.
 nEscapement  폰트의 각도를 0.1도 단위로 설정
 nOrientation  글자 한 자와 x축과의 각도를 지정한다. nEscapement는 전체의 문자열의 기울기를 지정하지만 이 인수는 개별 문자의 기울기
 fnWeight  폰트의 두께를 설정한다.
 fdwltalic  기울임체, DWORD지만 True False 사용가능
 fdwUnderline  밑 줄,DWORD지만 True False 사용가능
 fdwStrikeOut  관통선,DWORD지만 True False 사용가능
 fdwCharSet  문자 코드와 문자의 대응관계를 정하는 문자셋
 fdwOutputPrecision  출력 정확도를 설정한다
 fdwClipPrecision  클리핑 정확도를 설정한다
 fdwQuality  논리적 폰트를 물리적 폰트에 얼마나 근접시킬 것인가 지정한다.
 fdwPitchAndFamily  폰트의 피치와 그룹을 설정한다
 lpszFace  글꼴의 이름을 나타내는 문자열을 설정한다.

많은 인자가 있찌만 이중 실질적으로 변경해 야 할 필요가 있는 인수는 문자의 크기를 지정하는 nHeight와 글꼴 모양을 지정하는

lpszFace정도이다. 나머지 인수는 디폴트나 폰트 열거툴로 조사한 정보를 사용하면 일단은 큰 무리 없이 사용 가능.

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam){
 HDC hdc;
 PAINTSTRUCT ps;
 HFONT hFont,saveFont;
 
 TCHAR *str=TEXT("GFP입니다.");

 switch(iMessage){
 case WM_PAINT:
  hdc=BeginPaint(hWnd,&ps);
  hFont=CreateFont(50,0,0,0,0,0,0,0,HANGEUL_CHARSET,0,0,0,VARIABLE_PITCH|FF_ROMAN,TEXT("궁서"));
  saveFont=(HFONT)SelectObject(hdc,hFont);
  TextOut(hdc,10,10,str,lstrlen(str));
  DeleteObject(SelectObject(hdc,saveFont));
  EndPaint(hWnd,&ps);
  return 0;
 case WM_DESTROY:
  PostQuitMessage(0);
  return 0;
 }
 
 return (DefWindowProc(hWnd,iMessage,wParam,lParam));

}


그런데 저렇게 인수를 적어나가는건 상당히 헛갈리기도 한다.

그래서 저 인수를 하나로 묶어서[구조체로] 인자를 던져주는 방법이 있다.

함수명이 바뀌긴하는데 오히려 개인적으로는 이방법이 편하다.

이 함수의 인자는 LOGFNT구조체인데 폰트의 특을 다 정의하고 있기 때문에. 이 구조체에 값만 대입해서.

함수로 던져주면 된다.

한번 사용해보자.

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam){
 HDC hdc;
 PAINTSTRUCT ps;
 HFONT hFont,saveFont;
 
 TCHAR *str=TEXT("GFP입니다.");

 static LOGFONT lFont;

 switch(iMessage){
 case WM_CREATE:
  lFont.lfHeight=50;
  lFont.lfWidth=0;
  lFont.lfEscapement=0;
  lFont.lfOrientation=0;
  lFont.lfWeight=0;
  lFont.lfItalic=0;
  lFont.lfUnderline=0;
  lFont.lfStrikeOut=0;
  lFont.lfCharSet=HANGEUL_CHARSET;
  lFont.lfOutPrecision=0;
  lFont.lfClipPrecision=0;
  lFont.lfQuality=0;
  lFont.lfPitchAndFamily=VARIABLE_PITCH|FF_ROMAN;
  lstrcpy(lFont.lfFaceName,TEXT("궁서"));
 case WM_PAINT:
  hdc=BeginPaint(hWnd,&ps);
  hFont=CreateFontIndirect(&lFont);
  saveFont=(HFONT)SelectObject(hdc,hFont);
  TextOut(hdc,10,10,str,lstrlen(str));
  DeleteObject(SelectObject(hdc,saveFont));
  EndPaint(hWnd,&ps);
  return 0;
 case WM_DESTROY:
  PostQuitMessage(0);
  return 0;
 }
 
 return (DefWindowProc(hWnd,iMessage,wParam,lParam));

}

이렇게 구조체를 사용하는게 개발할때 편할것이다.

결과는 위와 동일합니다.

참고로 CreatePenIndirect,CreateBrushIndirect 등의 함수도 있다.

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

WinApi 컨트롤  (0) 2010.07.23
WinApi 그래픽 [TEXT COLOR]  (0) 2010.07.23
WinApi 그래픽 [비트맵 bitmap]  (0) 2010.07.22
WinApi RopMode2 [확장]  (0) 2010.07.22
WinApi 그래픽 [DrawMode]  (1) 2010.07.22
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