교내 전공과목인 윈도우즈 API수업을 정리합니다
1. Timer프로그램을 기능개선 시켜보자.
목표: 쓸데없이 전체화면을 새로고침하지말고, 문구가 나오는 부분만 수정해주자.
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
SYSTEMTIME st;
static TCHAR sTime[128];
switch (iMessage) {
case WM_CREATE:
SetTimer(hWnd, 1, 1000, NULL);
SendMessage(hWnd, WM_TIMER, 1, 0);
return 0;
case WM_RBUTTONDOWN:
hdc = GetDC(hWnd);
Ellipse(hdc, 60, 60, 200, 300);
ReleaseDC(hWnd, hdc);
return 0;
case WM_TIMER:
GetLocalTime(&st);
hdc = GetDC(hWnd);
//wsprintf(sTime,TEXT("지금 시간은 %d:%d:%02d 입니다."),
wsprintf(sTime, TEXT("지금 시간은 %d:%d:%d 입니다."),
st.wHour, st.wMinute, st.wSecond);
GetTextExtentPoint(hdc, sTime, lstrlen(sTime), &size); //sTime의 크기 -> size에 대입
rt.bottom = 100 + size.cy; //문자열 높이
rt.right = 100 + size.cx; // 문자열 너비
// InvalidateRect(hWnd,NULL,TRUE);
InvalidateRect(hWnd, &rt, TRUE);
ReleaseDC(hWnd, hdc);
return 0;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
TextOut(hdc, 100, 100, sTime, lstrlen(sTime));
EndPaint(hWnd, &ps);
return 0;
case WM_DESTROY:
KillTimer(hWnd, 1);
PostQuitMessage(0);
return 0;
}
return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
- GetTextExtentPoint: 지정된 텍스 문자열의 너비와 높이를 계산함
sTime문자열의 길이를 size에 넣기
실행결과는 전과 같으나 좀 더 효율적임.
2. 무효화 영역을 한 번 더 알아보자
(1) 소스코드
BOOL bRect = TRUE;
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
RECT rt;
int i;
switch (iMessage) {
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
for (i = 0; i < 1024; i += 2) {
MoveToEx(hdc, 0, i, NULL);
LineTo(hdc, 1280, i);
}
for (i = 0; i < 1280; i += 2) {
MoveToEx(hdc, i, 0, NULL);
LineTo(hdc, i, 1024);
}
if (bRect) {
Rectangle(hdc, 10, 10, 200, 200);
}
else {
Ellipse(hdc, 10, 10, 200, 200);
}
EndPaint(hWnd, &ps);
return 0;
case WM_LBUTTONDOWN:
bRect = !bRect;
//SetRect(&rt,10,10,200,200);
SetRect(&rt, 10, 10, 100, 100);
InvalidateRect(hWnd, &rt, TRUE);
//InvalidateRect(hWnd,NULL,TRUE); // 심한 깜빡임 발생
//SendMessage(hWnd, WM_PAINT, 0,0); // 이렇게 하지 말자.
//UpdateWindow(hWnd);
//Sleep(1000);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
- MoveToEx(HDC hdc, int X, int Y, LPPOINT lpPoint);
x: x좌표, y: y좌표, lpPPoint: 이전 현재 좌표를 돌려받기 위한 POINT(필요없다면 NULL전달하기) - LineTo(HDC hdc, int nXEnd, int nYEnd);
nXEnd: 끝점의 X좌표, nYEnd: 끝점의 Y좌표 - EndPaint(HWND hWnd, CONST PAINTSTRUCT *lpPaint);
lpPaint: 그리기 정보를 갖고 있는 PAINTSTRUCT구조체의 포인터, BeginPaint함수에서 사용한 구조체를 전달 - UpdateWindow(HWND hWnd);
윈도우 프로시저로 WM_PAINT를 보내여 작업영역을 강제로 그리도록 한다
WM_PAINT자체는 우선 순위가 늦어서 무효 영역이 있어도 먼저 처리해야할 다른 메시지 때문에 즉시 처리되지 않을 수도 있다. 따라서 대기순서의 영향을 주고 싶지 않을 때 사용한다. - Sleep
스레드 실행을 잠시 정지시킴
(2)실행화면
3. KeyDown 이벤트를 유니코드 중점으로 봐보자
#include<tchar.h>
LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
static int x=100;
static int y=100;
static char *c = "A";
// 문자열 하나 정의//MultiBytes Character Set
// static wchar_t *c = L"A"; //Unicode Character Set
// static TCHAR *c = TEXT("A"); //Neutral Code
// static wchar_t c[] = (L"가abc"); //unicode
//static char c[] = "가abc";
// static TCHAR c[] = TEXT("가abc"); //Neutral Code
static bool s = false;
switch (iMessage) {
case WM_KEYDOWN:
switch (wParam) {
case VK_SPACE:
s ? c = "A" : c = "#"; //MBCS
//s ? c = L"A" : c = L"#"; //Unicode
//s ? c = TEXT("A"): c = TEXT("#");
//s ? strcpy(c, "가abc") : strcpy(c, "나abc") ; //MultiBytes Character Set
//s ? wcscpy(c, L"가abc") : wcscpy(c, L"나abc"); //Unicode
//s ? _tcscpy(c, TEXT("가abc")) : _tcscpy(c, TEXT("나abc"));
s = !s;
break;
case VK_LEFT:
x-=8;
break;
case VK_RIGHT:
x+=8;
break;
case VK_UP:
y-=8;
break;
case VK_DOWN:
y+=8;
break;
}
//InvalidateRect(hWnd,NULL,TRUE);
InvalidateRect(hWnd,NULL,FALSE);
return 0;
case WM_PAINT:
hdc=BeginPaint(hWnd,&ps);
TextOut(hdc,x,y,c,lstrlen(c)); //strlen() <-- c runtime library
EndPaint(hWnd,&ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return(DefWindowProc(hWnd,iMessage,wParam,lParam));
}
주석참고