'programing'에 해당되는 글 29건

  1. 2010.07.21 WinApi 그래픽 [색상][펜][브러쉬]
  2. 2010.07.21 WinApi 리소스 [String Table]
posted by nsakura 2010. 7. 21. 16:40

예전 dos시절의 프로그램을 생각해보자

색상을 WHITE YELLOW RED등 매크로 상수로 색상을 표현했었다.

해봤자 16개 색상밖에 사용을 못하니.

하지만 윈도우에서는 다르다.

윈도우는 최대 천육백만가지의 색상값을 정의할수있으니 말이다.

그래서 윈도우즈에서 색상값을 표현하기 위해서는 COLORREF라는 데이터형을 사용하는데 다음과같이 정의 되어있다

typedef DWORD COLORREF;

보다싶이 COLORREF 형은 부호없는 32비트 크기의 정수형이며 8비트씩 R G B의 농도를 나타내며 상위 8비트는 사용하지

않는다.

하지만 상당히 불편하기 때문에. RGB 매크로 함수를 사용하며 이 매크로는 다음과 같이 정의

되어있다.

#define RGB(r,g,b)((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|((((DWORD)(BYTE)(b))<<16)))

각각의 인수는 R G B의 농도 이고 이 값을 조립하여 하나의 32 비트의 색상값을 만들어 낸다.

그외에 제공하는 색상관련 메크로 함수가 3개가 있다.

#define GetRValue(rgb) ((BYTE)(rgb))
#define GetBValue(rgb) ((BYTE)(((WORD)(rgb))>>8))
#define GetGValue(rgb) ((BYTE)((rgb)>>16))


이 메크로 함수들은 각 색상을 분리하는데 사용한다.

색상에 대해서는 그만 설명하고

펜을 실습을 해보자.

펜을 만드는 함수는  다음과 같다.

HPEN CretePen(int fnPenStyle, int nWidth, COLORREF crColor);


fnPenStyle

PS_SOLID  일반 선 

PS_DASH ----

PS_DOT ........

PS_DASHDOT _._._.

PS_DASHDOTDOT_.._.._

등이 있다,

nWidth

선의 폭을 설정한다.

crColor

선의 색을 설정한다.

그럼 예제를 통해 사용해보자.

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam){
 HDC hdc;
 PAINTSTRUCT ps;
 HPEN testpen,savepen;
 switch(iMessage){
 case WM_DESTROY:
  PostQuitMessage(0);
  return 0;
 case WM_PAINT:
  hdc=BeginPaint(hWnd,&ps);
  testpen=CreatePen(PS_DASHDOTDOT,1,RGB(125,88,255));
  savepen=(HPEN)SelectObject(hdc,testpen);

  Rectangle(hdc,100,100,400,400);
  SelectObject(hdc,savepen);
  DeleteObject(testpen);
  EndPaint(hWnd,&ps);
 }

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

}

GDI 오브젝트는 스톡오브젝트와 달리

사용했으면 반납을 해야한다.

즉 메모리를 사용했으면 다사용하고 반납을 해야한다는 것이다.

그 반납하는 함수가 바로

DeleteObject(testpen);

가 되겠습니다.

BOOL DeleteObject(HGDIOBJ hObject);

즉 반납하고자하는 GDI오브젝트의 핸들만 인수로 넘겨주면 된다.

주의할점은 현재 선택되어있는 GDI Object는 반납할수 없다.

그래서 사용한게 savepen을 이용한 것이다. 삭제하긱전에 savepen으로 교체하고

반납하면 된다.

그래서

  SelectObject(hdc,savepen);
  DeleteObject(testpen);

 좀더 고급스럽게 바꾸면

DeleteObject(SelectObject(savepen));

무엇을 사용할건지는 편한것을 사용하도록.

참고로 위의 코드의 결과는 다음과 같다.


위의 코드는 썰렁한 부분이 있는데 바로... 안쪽. 안쪽의 빈공간을 채우고 싶다는.. 욕구가 안생기는가...

브러쉬를 이용하면 색을 칠할수있는데

브러쉬를 만드는 함수는 두가지가있다.

HBRUSH CreateSolidBrush(COLORREF crColor);

이 함수는 단색 브러쉬만 만들수있고 색상만 인수로 전달한다.

다음 함수는

HBRUSH CreateHatchBrush(int fnStyle, COLORREF clrref);

인데 특징으로서는 색상뿐만 아니라. 무늬도 같이 지정할수있다. 지정할수 있는 무늬의 종류는 다음과 같다.

 HS_BDIAGONAL  좌하향 줄무늬
 HS_CROSS  바둑판 모양
 HS_DIAGCROSS  좌하향 및 우하향 줄무늬
 HS_FDIAGONAL 우하향 줄무늬
 HS_HORIZONTAL  수평선
 HS_VERTICAL  수직선


그럼 예제를 통해서 사용해보자 PEN에서 사용한 소스를 조금 수정해보자.

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam){
 HDC hdc;
 PAINTSTRUCT ps;
 HPEN testpen,savepen;
 HBRUSH testbrush,savebrush;

 switch(iMessage){
 case WM_DESTROY:
  PostQuitMessage(0);
  return 0;
 case WM_PAINT:
  hdc=BeginPaint(hWnd,&ps);
  
  testpen=CreatePen(PS_DASHDOTDOT,1,RGB(125,88,255));
  testbrush=CreateHatchBrush(HS_DIAGCROSS,RGB(225,128,150));
  
  savepen=(HPEN)SelectObject(hdc,testpen);
  savebrush=(HBRUSH)SelectObject(hdc,testbrush);
  
  Rectangle(hdc,100,100,400,400);
  
  DeleteObject(SelectObject(hdc,savepen));
  DeleteObject(SelectObject(hdc,savebrush));

  EndPaint(hWnd,&ps);
 }

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

}

코드의 결과는 다음과 같다.

[그림판으로 스샷을 찍으니.. 색상이 많이 죽네요.]
posted by nsakura 2010. 7. 21. 00:04

윈도우에서는 문자열도 리소스로 취급한다.

많은 문자열을 사용하는 프로그램은

문자열 테이블을 사용하는게 효율적일것이다.


코드는 그냥 이전 포스트에서 사용했던 리소스 예제의 코드를 사용했다.



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

 switch(iMessage){
 case WM_DESTROY:
  PostQuitMessage(0);
  return 0;
 case WM_COMMAND:
  switch(LOWORD(wParam)){
  case ID_NSAKURA:
   MessageBox(hWnd,TEXT("Nsakura 입니다."),TEXT("NSAKURA"),MB_OK);
   break;
  case ID_EXIT:
   MessageBox(hWnd,TEXT("종료 합니다.."),TEXT("EXIT"),MB_OK);
   DestroyWindow(hWnd);
  }
  case WM_PAINT:
   hdc=BeginPaint(hWnd,&ps);
   LoadString(g_Inst,IDS_NSAKURA,str,lstrlen(str));
   TextOut(hdc,10,10,str,lstrlen(str));
   EndPaint(hWnd,&ps);
  return 0;
 }
 
 return (DefWindowProc(hWnd,iMessage,wParam,lParam));
}

이렇게 코드를 추가하였는데 이번에도 뜸금없이 새로운 함수가 눈에 띄인다.

LoadString함수인데 간단하게 설명하겠다. 그냥 리소스의 문자열 테이블로부터 문자를 가지고 오는 함수이다.

그럼 원형을 살펴보자.

int LoadString(HINSTANCE hInstance, UINT uID, LPSTR lpBuffer, int nBufferMax);

엇! 첫번째 인자가 이상하다.

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam){

프록 함수를 보면 인자가 없지만.

우리는 HINSTANCE변수 하나를 전역으로 만들어 두었음을 잊지말며.

WinMain

g_Inst=hInstance;

이부분을 기억해야할 것이다.

요는 첫 번째 인자는 문자열 리소스를 가진 인스턴스 핸들

두 번째 인자는 읽어드릴 문자열 테이블의 ID를

세 번째 인자는 받아온 문자열을 저장할 변수

네 번째 인자는 저장할 변수의 크기를 말한다.

그런데 이렇게 문자열 테이블을 사용하는 이유는 뭘까 그냥 코드상으로 쓰면 안되나.

그냥 교재에서는 이러저래 설명은 되어있지만.

몇 가지 이유를 간추려보면 프로그램이라는건 혼자서 만들수있는 단위는 극히 적다. 있다고하더라도 난잡하다.

왜 난잡할까 특히 이런 문자열 같은경우 안내문인 경우가 많은데. 코딩하랴 저런 사용자적인 부분도 신경쓰랴

그렇다고 전문디자이너보고 코드를 줄수있는 노릇은 아니지 않은가.

그렇기 때문에 이렇게 일의 분담을 효율적으로 할수있으며 두번째는 언어의 버젼을 다르게 만들기 유용하다.

언어의 버젼은 [외국어]를 지칭한다. 지금 a라는 프로그램을 일본에 판다고 했을때 단순히 문자열 테이블만 수정하면

되기 때문이다.

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

WinApi 그래픽 [색상][펜][브러쉬]  (0) 2010.07.21
WinApi 그래픽 [GetStockObject]  (0) 2010.07.21
WinApi 리소스 [액셀러레이터]  (0) 2010.07.20
WinApi 리소스 [아이콘][커서]  (2) 2010.07.20
WinApi 리소스 [메뉴]  (0) 2010.07.20