본문 바로가기
프로그래밍/API

API-RopMode

by 리뷰하는 (게임)프로그래머_리프TV 2010. 4. 24.


선을 그릴때, 반전 모드를 사용하는 예제,

#include <windows.h>

LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );
HINSTANCE g_hInst;
LPCTSTR lpszClass = TEXT("RopMode");

int APIENTRY WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
					 LPSTR lpszCmdParam, int nCmdShow )
{
	HWND hWnd;
	MSG Message;
	WNDCLASS WndClass;
	g_hInst = hInstance;

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

	hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
		NULL, (HMENU)NULL, hInstance, NULL );
	ShowWindow( hWnd, nCmdShow );

	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 )
{
	static int sx, sy, oldx, oldy;
	static BOOL bNowDraw = FALSE;
	HDC hdc;
	PAINTSTRUCT ps;
	TCHAR str[256];
	
	switch( iMessage )
	{
	case WM_LBUTTONDOWN:
		sx = LOWORD( lParam );	// 마우스 x,y를 가져온다.
		sy = HIWORD( lParam );
		oldx = sx;		// oldx, oldy에 현재 마우스의 x,y를 넣는다.
		oldy = sy;
		bNowDraw = TRUE;	// 현재 마우스 버튼이 클릭되어 있다는 것을 체크
		return 0;
	case WM_PAINT:
		hdc = BeginPaint( hWnd, &ps );
		wsprintf( str, TEXT("Oldx : %d Oldy :%d sX :%d sY :%d, bNowDraw : %d"),
			oldx, oldy, sx, sy, bNowDraw );
		TextOut( hdc, 0, 0, str, lstrlen(str) );
		EndPaint( hWnd, &ps );
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	case WM_MOUSEMOVE:
		if( bNowDraw )	// 마우스 왼쪽 버튼이 눌려 있는 상태에서 마우스가 이동하기 시작하면,
		{
			hdc = GetDC( hWnd );
			SetROP2( hdc, R2_NOT );		// 그림을 반전시킨다.
			MoveToEx( hdc, sx, sy, NULL );	// CP를 sx, sy의 위치로 변경 후
			LineTo( hdc, oldx, oldy );	// 라인을 지운다
			// 마우스 x,y를 갱신하여
			oldx = LOWORD( lParam );	
			oldy = HIWORD( lParam );
			// 선을 새로 그린다.
			MoveToEx( hdc, sx, sy, NULL );	// 최초 포인트로 CP를 변경
			LineTo( hdc, oldx, oldy );	// 라인을 그린다.
			ReleaseDC( hWnd, hdc );
			InvalidateRect( hWnd, NULL, FALSE );
		}
		return 0;
	case WM_LBUTTONUP:
		bNowDraw = FALSE;
		hdc = GetDC(hWnd );
		MoveToEx( hdc, sx, sy, NULL );	// 마우스 왼쪽 버튼을 때면 실질적으로 선을 그린다.
		LineTo( hdc, oldx, oldy );
		ReleaseDC( hWnd, hdc );
		return 0;
	}
	return( DefWindowProc( hWnd, iMessage, wParam, lParam));
}​


이 예제에서 가장 중요한 부분은, WM_MOUSEMOVE: 부분인데,
SetROP(hdc, R2_NOT); 은
그 부분에 대해서 NOT연산을 처리한다.
마우스를 왼쪽 버튼을 누른체 마우스를 움직이게 되면
이전 위치에 선을 지우고
다시 현재 이동된 마우스의 좌표를 가져온 다음,
다시 선을 그린다.
이런식으로 돌아 간다.
SetROP라는 함수는 이미지 비트연산을 하게 되는데,
R2_NOT 뿐만이 아니라 다양한 것들이 존재한다.

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

상황에 따라 적절한 비트연산을 해보자!?

// 실행 화면

마우스 왼쪽 버튼을 때기 전까진 선을 그리지 않고 선이 마우스 포인터를 따라다닌다?

'프로그래밍 > API' 카테고리의 다른 글

API-Control(1)  (0) 2010.04.24
API-BitMap  (0) 2010.04.24
API-GdiObject  (0) 2010.04.22
API-resource(3)  (0) 2010.04.21
API-resource(2)  (0) 2010.04.21