교내 전공과목인 윈도우즈 API수업을 정리합니다
1. 지난 실습코드에서 사각형의 브러쉬 색상을 지정해주자
(1) 코드소스
/* CALLBACK WndProc 함수 */
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
HBRUSH hBrush; // 내부 색상 설정
HPEN hPen; // 테두리 설정
int x, y;
switch (iMessage) {
case WM_CREATE:
hWndMain = hWnd;
return 0;
case WM_LBUTTONDOWN:
// 특정윈도우의 그리기 관련 정보
hdc = GetDC(hWnd); //모든 그리기 함수에세 cd를 전달
//x = LOWORD(lParam); // Macro
//x = (WORD)(lParam); //casting
x = (short)(lParam); //casting
//y = HIWORD(lParam);
y = ((lParam) >> 16); //bitwise oprator
p[iCount].x = x;
p[iCount].y = y;
iCount++;
/* 색 지정과 적용 */
hPen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0));
SelectObject(hdc, hPen);
hBrush = CreateSolidBrush(RGB(0, 0, 255));
SelectObject(hdc, hBrush);
Rectangle(hdc, x - 20, y - 20, x + 20, y + 20);
return 0;
case WM_PAINT: //BeginPaint()로 DB열기
hdc = BeginPaint(hWnd, &ps);
/* 다시 그릴 때도 색 지정과 적용 */
hPen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0));
SelectObject(hdc, hPen);
hBrush = CreateSolidBrush(RGB(0, 0, 255));
SelectObject(hdc, hBrush);
for (int i = 0; i < iCount; i++)
{
Rectangle(hdc, p[i].x - 20, p[i].y - 20, p[i].x + 20, p[i].y + 20);
}
EndPaint(hWnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
(2) 실행결과
2. KEY_DOWN, 키다운 이벤트를 사용하자
새로운 프로젝트(Key_Down)을 만들고 시작한다
(1) 사전에 속성을 건드려주자. (vs2017부터 코드안정성을 위해 오류가 일어난다)
프로젝트 > 속성 > C/C++ > 언어 > 준수모드 > 아니요 > 적용 및 확인
(2) 소스코드
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
static int x = 100;
static int y = 100;
switch (iMessage) {
case WM_KEYDOWN : // 0x0100:
switch (wParam) {
case VK_LEFT: // 37: // 0x25:
x -= 8;
break;
case VK_RIGHT:
x += 8;
break;
case VK_UP:
y -= 8;
break;
case VK_DOWN:
y += 8;
break;
case VK_SPACE:
if (toggle == TRUE) {
toggle = FALSE;
}
else toggle = TRUE;
break;
}
//InvalidateRect(hWnd,NULL,TRUE);
InvalidateRect(hWnd, NULL, FALSE); // hWnd handle을 가진 윈도우로 WM_PAINT message를 발생시키기
return 0;
case WM_PAINT:
if (toggle == TRUE) {
str = TEXT("#");
}
else str = TEXT("A");
hdc = BeginPaint(hWnd, &ps);
TextOut(hdc, x, y, str, 1); // 출력하는 문자(A)의 개수 = 1 표시
EndPaint(hWnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
- toggle변수는 스페이스바로 작동하며, 눌릴 때마다 A와 #을 번갈아서 출력함
- InvalidateRect( HAWD hwnd, const RECT *lpRect, BOOL bErase ). 무효영역 다루기
hwnd: 클라이언트 영역을 갱신할 윈도우 핸들 값
*lpRect: 클라이언트 영역에서 갱신하고 싶은 영역의 좌표(RECT구조체 형식)
bErase: 해당 영역의 배경까지 갱신할 것인지의 여부 (FALSE = 현재 상태 유지) - lnInvalidateRect(hWnd, NULL, TRUE) => A가 한 개씩만 출력
lnInvalidateRect(hWnd, NULL, FALSE) => A가 자취를 남기며 출력
(3) 실행결과
키보드에 따라 문자가 이동되면서 자취를 남김.
3. 무효영역을 이용하여 사각형그리기 파일을 다시 수정하자
(1) 소스코드
/* CALLBACK WndProc의 switch문 수정 */
switch (iMessage) {
case WM_CREATE:
hWndMain = hWnd;
return 0;
case WM_LBUTTONDOWN:
// 특정윈도우의 그리기 관련 정보
hdc = GetDC(hWnd); //모든 그리기 함수에세 cd를 전달
//x = LOWORD(lParam); // Macro
//x = (WORD)(lParam); //casting
x = (short)(lParam); //casting
//y = HIWORD(lParam);
y = ((lParam) >> 16); //bitwise oprator
p[iCount].x = x;
p[iCount].y = y;
iCount++;
InvalidateRect(hWnd, NULL, FALSE); //무효영역 지정
/*
hPen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0));
SelectObject(hdc, hPen);
hBrush = CreateSolidBrush(RGB(0, 0, 255));
SelectObject(hdc, hBrush);
Rectangle(hdc, x - 20, y - 20, x + 20, y + 20);
return 0; */
case WM_PAINT: //BeginPaint()로 DB열기
hdc = BeginPaint(hWnd, &ps);
hPen = CreatePen(PS_SOLID, 3, RGB(255, 0, 0));
SelectObject(hdc, hPen);
hBrush = CreateSolidBrush(RGB(0, 0, 255));
SelectObject(hdc, hBrush);
for (int i = 0; i < iCount; i++)
{
Rectangle(hdc, p[i].x - 20, p[i].y - 20, p[i].x + 20, p[i].y + 20);
}
EndPaint(hWnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
invalidate를 사용해줬다
실행결과는 정상적.
4. DC를 알아보자
(1) 용어
DC(Device Context): 출력에 필요한 모든 정보를 가지는 데이터 구조체다
(2) 쓰임
HDC hdc;
/* 방법2 */
hdc = GetDc(hWnd);
RelealseDC()ReleaseDC(hWnd,hdc);
/* 방법1 */
hdc = BeginPaint(hWnd, $ps);
EndPaint(hWnd, $ps);