'graphic'에 해당되는 글 10건

  1. 2010.07.21 WinApi 그래픽 [변수를 두개 두는 이유]
  2. 2010.07.21 WinApi 그래픽 [색상][펜][브러쉬]
posted by nsakura 2010. 7. 21. 18:29

언급은 잠깐했었지만 솔직히

실습하면서 굉장히 귀찮지 않았나?

메모리 할당받고. 그냥 반납을 하면 되는데. 왜 굳

귀찮게. 어째서 다른 팬으로 바꾸고 기존의 팬을 지우는가?

너무 귀찮지 않았나?

이유는 간단하다.

예를 하나 들겠다. A라는 게임이 실행중이다.

그런데 실행중에 A라는 게임을 지워보자 지워지는가?

이런 메세지가 뜨지 않는가?

"실행중인 프로그램이니까 삭제 못해"

라고 말이다.

마찬가지이다 펜이나 브러쉬를 선택한순간 "이건 사용중임"

되는겁니다. 사용중인데 빼앗으면 어떻게 될까요? 현실세계를 생각해보죠.

싸우지 않겠나요? 즉 pc도 마찬가지다. 그러므로 나름 안전 장치가 있는것이다.

그것이 선택중일때는 삭제를 못한다. 라는 것이다.

즉 사용중일때는 삭제를 못한다 와 같은거다.

책에는 코드를 몇개나 예를들어서 설명되어있지만 간단하게 추려 보았다.

한번 테스트를 해볼까 한다.

[PS : 이 코드는 상당히 안좋은 코드다 다른작업하고있었다면 작업을 끝내거나

저장하거나 만일의 사태를 준비하고 실습에 임하기 바란다. 만일 이에 대한 문제는

나에게는 책임이 없다! 정말 없다! 책임 안질거다.

솔직히 문제라고 해봤자 다운밖에 더 되겠냐만은..]


#include <windows.h>

HINSTANCE nsakuragfp;
LPCTSTR wndname=TEXT("GDI ERROR");
HWND hWndMain;

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
void TestResource(BOOL,BOOL,int);


int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd){
 HWND hWnd;
 MSG Message;
 WNDCLASS WndClass;
 nsakuragfp=hInstance;

 WndClass.cbClsExtra=0;
 WndClass.cbWndExtra=0;
 WndClass.hbrBackground=(HBRUSH)GetStockObject(WHITE_BRUSH);
 WndClass.hCursor=LoadCursor(NULL,IDC_ARROW);
 WndClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
 WndClass.hInstance=hInstance;
 WndClass.lpfnWndProc=WndProc;
 WndClass.lpszClassName=wndname;
 WndClass.lpszMenuName=NULL;
 WndClass.style=CS_HREDRAW|CS_VREDRAW;
 RegisterClass(&WndClass);

 hWnd=CreateWindow(wndname,wndname,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,(HMENU)NULL,hInstance,NULL);
 
 ShowWindow(hWnd,nShowCmd);

 hWndMain=hWnd;

 while(GetMessage(&Message,NULL,0,0)){
  TranslateMessage(&Message);
  DispatchMessage(&Message);
 }

 return (int)Message.wParam;

}

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam){
 HDC hdc;
 PAINTSTRUCT ps;
 
 TCHAR *information=TEXT("1:정상적인 경우 2:선택없이 삭제만 3:삭제 하지 않음");

 switch(iMessage){
 case WM_DESTROY:
  PostQuitMessage(0);
  return 0;
 case WM_PAINT:
  hdc=BeginPaint(hWnd,&ps);
  TextOut(hdc,10,10,information,lstrlen(information));
  EndPaint(hWnd,&ps);
  return 0;
 case WM_KEYDOWN:
  switch(wParam){
  case '1':
   TestResource(TRUE,TRUE,10000);
   break;
  case '2':
   TestResource(FALSE,TRUE,10000);
   break;
  case '3':
   TestResource(FALSE,FALSE,10000);
   break;
  }
  return 0;
 }

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

void TestResource(BOOL select, BOOL deleteOB, int ncnt){
 HDC hdc;
 HPEN hPen,savePen;
 int i;
 TCHAR str[256];

 hdc=GetDC(hWndMain);
 for(i=0; i<ncnt; i++){
  hPen=CreatePen(PS_SOLID,1,RGB(0,0,0));
  savePen=(HPEN)SelectObject(hdc,hPen);
  MoveToEx(hdc,rand()%300,rand()%200,NULL);
  LineTo(hdc,rand()%300,rand()%200+40);
  if(select){
   SelectObject(hdc,savePen);
  }
  if(deleteOB){
   DeleteObject(hPen);
  }

  wsprintf(str,TEXT("%d"),i);
  SetWindowText(hWndMain,str);
 }
 ReleaseDC(hWndMain,hdc);


}
 
참고로 메모리 누수가 생기거나 심하신분은 리붓을 하길 바란다.

함수의 인자에 따라 삭제만 할수도

팬만 바꿀수도

아니면 둘다 안할수도 있습니다.

참고로 NT계열 어느정도 이런 개발자의 실수를 백업을 해준다고 한다.

그래서 그런지  본인은 그렇게 문제가 생기지 않았다.

그러나! 절대 이런 실수는 하지말것.

메모리를 쓰면 돌려줘야한다.

독식하면 주빵을 맞는것이 세상의 진리이다.





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

WinApi 그래픽 [DrawMode]  (1) 2010.07.22
WinApi 그래픽 [투명 오브젝트]  (0) 2010.07.22
WinApi 그래픽 [색상][펜][브러쉬]  (0) 2010.07.21
WinApi 그래픽 [GetStockObject]  (0) 2010.07.21
WinApi 리소스 [String Table]  (0) 2010.07.21
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));

}

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

[그림판으로 스샷을 찍으니.. 색상이 많이 죽네요.]