'graphic'에 해당되는 글 10건

  1. 2010.07.22 WinApi 그래픽 [DrawMode] 1
  2. 2010.07.22 WinApi 그래픽 [투명 오브젝트]
posted by nsakura 2010. 7. 22. 12:43
흑백에서의 그리기 모드

그리기 모드란 도형이 그려질 때 원래 그려져 있던  그림과 새로 그려지는 그림과의 관계를 말한다.

간단하게 그림을 만들어봤다.

참고로 간단하게 흑백의 그래픽 환경을 가정해서 만들었더.




OR
 0  1   0   1 
 0  1  1  0
 0  1  1  1
AND
 0  1  0  1 
 0  1  1  0
 0  1  0  0
XOR
 0  0   0   1
 0  0  1  0
 0  0  1  0

같은 이야기니까 편한걸로 이해하길 바란다.

그리기 모드의 종류

윈도우에서 사용하는 디폴트 그리기 모드는 R2_COPYPEN 모드이다. 그래서 그려지는 그림이 기존 그림을 덮어 버런다.

그리기 모드에 대한 함수는

int SetROP2(HDC,int fnDrawMode);

int GetROP2(HDC,hdc);

첫 번째 인수는 설정하거나 정보를 얻고자 하는 dc를 말한다.

두 번째 인수는 설정하고자하는 모드를 말한다. 그리모드는 다음표와 같다.

 R2_BLACK  항상 검정색이다
 R2_WHITE  항상 흰색이다
 R2_NOP  아무런 그리기도 하지 않는다.
 R2_NOT  원래의 그림을 반전시킨다.
 R2_COPYPEN  원래의 그림을 덮어버리고 새 그림을 그린다.
 R2_NOTCOPYPEN  새 그림을 반전시켜 그린다.
 R2_NOTXORPEN  XOR한 결과의 반대값을 써 넣는다
 R2_MERGENPEN  OR연산으로 두 그림을 합친다.
 R2_MASKPEN  AND.연산으로 겹치는 부분만 그린다.
 R2_XORPEN  XOR연산으로  겹치는 부부만 반전시킨다.


그 외에 몇가지 그리모드가 더있는데. 거의 안써서 설명에서 제외!

자 그럼 실습을 해보자.

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam){
 static int xpos,ypos;
 static int xposSave, yposSave;

 static BOOL buttonFlag=false;

 HDC hdc;
 
 switch(iMessage){
 case WM_DESTROY:
  PostQuitMessage(0);
  return 0;
 case WM_LBUTTONDOWN:
  
  xpos=LOWORD(lParam);
  ypos=HIWORD(lParam);
  
  xposSave=xpos;
  yposSave=ypos;

  buttonFlag=true;

  return 0;
 case WM_LBUTTONUP:
  buttonFlag=false;

  hdc=GetDC(hWnd);

  MoveToEx(hdc,xpos,ypos,NULL);
  LineTo(hdc,xposSave,yposSave);

  ReleaseDC(hWnd,hdc);

  return 0;
 case WM_MOUSEMOVE:
  if(buttonFlag){
  
   hdc=GetDC(hWnd);
   
   SetROP2(hdc,R2_NOT);
   
   MoveToEx(hdc,xpos,ypos,NULL);
   LineTo(hdc,xposSave,yposSave);

   xposSave=LOWORD(lParam);
   yposSave=HIWORD(lParam);

   MoveToEx(hdc,xpos,ypos,NULL);
   LineTo(hdc,xposSave,yposSave);

   ReleaseDC(hWnd,hdc);
   
  }
  
  return 0;
 }
 return (DefWindowProc(hWnd,iMessage,wParam,lParam));
}




자 궁금증이 생기지 않은가? 왜 반전을 시켰는가.

그렇다면 SetROP2(hdc,R2_NOT);

부분을 주석처리해서 프로그램을 돌려보자!.



간단하게 프로그램 분석을 해보자.

마우스 왼쪽 버튼을 누르는 순간 좌표가 변수에 저장되며 save변수에도 좌표를 저장한다.

왜냐하면 시작점과 끝점이 같기 때문이다.

그리고 플래그를 올려둔다.

마우스가 움직이면 플래그가 올라갔다면 마우스가

왼쪽버튼을 누른상태에서 움직이면 선이 그어지는데 왜냐하면 기본 좌표 xpos와 ypos는 고정되어있고 입력을받아 그어지는것은 끝점인

xposSave와 yposSave가 이동 좌표가 되는것이다.

첫번째 Lineto함수는 기존에 선과 똑같은위치에 선을 그린다 반전모드이기때문에 선이 삭제 되겠죠.

그리고 다시 마우스 좌표를 받아

선을 그리는것이다.

마우스 버튼을 놓게 되면 마지막에 move에서 마지막에 그어졌던 선 위치 그위치에 똑같이 선을 그린다.

그렇다면 흰색팬으로 지운 후 검은색 펜으로 다시 그리는 방식을 사용하면 어떨까?

 if(buttonFlag){
  
   hdc=GetDC(hWnd);
   
   SelectObject(hdc,GetStockObject(WHITE_PEN));
   
   MoveToEx(hdc,xpos,ypos,NULL);
   LineTo(hdc,xposSave,yposSave);

   xposSave=LOWORD(lParam);
   yposSave=HIWORD(lParam);

   SelectObject(hdc,GetStockObject(BLACK_PEN));

   MoveToEx(hdc,xpos,ypos,NULL);
   LineTo(hdc,xposSave,yposSave);

   ReleaseDC(hWnd,hdc);
   
  }

이렇게 바꾸면 어떨까?



잘되는것 같지만.. 그건 위에 보이는 선만 그렇다 왜 저 코드가 안되는것일까?

간단하다 마지막에 그려진 선은 잘 처리가 되지만 지운걸 다시 그리기 때문에 지워지는 부분에서 다 원상복구 시켜주지 않기 때문에

깔려있는 선은 죽어나가는것이다.

이해가 안되면 돌려보도록.




posted by nsakura 2010. 7. 22. 00:21

오늘 마지막 포스트가 될것 같은데 마지막 포스팅을 장식할 내용은

NULL_BRUSH와 NULL_PEN 이다.

투명이라고 되어있지만 아무것도 그리지 않는다 라고 읽는것이 맞을 것이다.

그럼 바로. 코드로 확인을 해보자!

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam){
 HDC hdc;
 PAINTSTRUCT ps;
 int ncnt;
 HBRUSH hBrush,saveBrush;
 HPEN hPen,savePen;

 switch(iMessage){
 case WM_DESTROY:
  PostQuitMessage(0);
  return 0;
 case WM_PAINT:
  hdc=BeginPaint(hWnd,&ps);
  
  for(ncnt=0; ncnt<250; ncnt+=5){    //화면에 각격 5마다 선을 그린다.
   MoveToEx(hdc,0,ncnt,NULL);
   LineTo(hdc,600,ncnt);
  }
  
  hBrush=CreateSolidBrush(RGB(0,255,0)); //그린 브러쉬
  saveBrush=(HBRUSH)SelectObject(hdc,hBrush);
  
  hPen=CreatePen(PS_SOLID,1,RGB(255,0,0)); //레드 팬
  savePen=(HPEN)SelectObject(hdc,hPen);

  Ellipse(hdc,20,20,150,150);

  //NULL_BRUSH 설정.
  SelectObject(hdc,GetStockObject(NULL_BRUSH));
  Ellipse(hdc,220,20,350,150);

  //NULL_PEN 설정
  SelectObject(hdc,hBrush);
  SelectObject(hdc,GetStockObject(NULL_PEN));
  Ellipse(hdc,420,20,550,150);

  DeleteObject(SelectObject(hdc,savePen));
  DeleteObject(SelectObject(hdc,saveBrush));


  EndPaint(hWnd,&ps);
  return 0;
 }

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

}



첫번째 원은 붉은색 테두리의 초록색으로 채운다.

두번째 원은 테두리는 붉은팬이지만 내부는 색이 없는 브러쉬 즉 채색이 없다(NULL_BURSH)

세번째는 테두리가 NULL_PEN임으로 테두리가 없는 것이다.

없기 때문에 투명처럼 보이는것이다. 간단한 설명으로.

알이 없는 안경이나 테두리가 없는 안경

쯤으로 생각하면 된다.

투명과 없는거랑은 개념이 약간 틀리다고 난 생각한다.

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

WinApi RopMode2 [확장]  (0) 2010.07.22
WinApi 그래픽 [DrawMode]  (1) 2010.07.22
WinApi 그래픽 [변수를 두개 두는 이유]  (0) 2010.07.21
WinApi 그래픽 [색상][펜][브러쉬]  (0) 2010.07.21
WinApi 그래픽 [GetStockObject]  (0) 2010.07.21