교내 전공과목인 윈도우즈 API수업을 정리합니다
1. Rand-Key-BackGround, 스레드로 구현하기
기본적으로 바탕에서 랜덤색상의 점찍기가 진행된다 // ThreadFumc
그리고 사용자가 동적으로 키이벤트(문구 작성), 마우스이벤트(큰 점 찍기)를 일으킬 수 있게한다 // WndProc
(1) 소스코드
/*필요한 변수 */
HWND hWndMain; //주 핸들
TCHAR str[256]; //문자 출력할 공간
/* 스레드함수 */
DWORD WINAPI ThreadFunc(LPVOID temp){
HDC hdc = GetDC(hWndMain);
for (;;){
SetPixel(hdc, rand() % 500, rand()% 400, //랜덤 위치에
RGB(rand() % 256, rand() % 256, rand() % 256)); //랜덤 색상으로
}
ReleaseDC(hWndMain, hdc);
return 0;
}
/* 윈프록 내부 */
HDC hdc;
PAINTSTRUCT ps; //문자
int i, len; //문자 담기
DWORD ThreadID;
HANDLE hThread;
switch (iMessage){
/* 키 입력 받기 */
case WM_CHAR:
len = lstrlen(str);
str[len] = (TCHAR)wParam;
str[len + 1] = 0;
InvalidateRect(hWnd, NULL, FALSE);
return 0;
case WM_CREATE:
hWndMain = hWnd;
hThread = CreateThread(NULL, 0, ThreadFunc, NULL, 0, &ThreadID);
CloseHandle(hThread);
return 0;
/* 점 찍기 */
case WM_LBUTTONDOWN:
hdc = GetDC(hWnd);
Ellipse(hdc, LOWORD(lParam) - 10, HIWORD(lParam) - 10, LOWORD(lParam) + 10, HIWORD(lParam) + 10);
ReleaseDC(hWnd, hdc);
return 0;
/* 입력된 문자 출력 */
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
TextOut(hdc, 100, 100, str, lstrlen(str));
EndPaint(hWnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return(DefWindowProc(hWnd, iMessage, wParam, lParam));
(2) 실행결과
안 예뻐.
2. Rand-Key-BackGround2, 문자 카운트 기능 추가하기
백그라운드의 자동 점찍기는 제거하고, 점찍기도 가능하면서
키 입력때마다 문장의 a개수를 세는 기능을 추가하자
(1) 소스코드
/* 변수는 이전처럼 그대로 쓰고 있음 */
HWND hWndMain;
TCHAR str[256]; //입력할 문구 공간
/* '카운트 및 카운트 출력' 스레드, 원래는 백그라운드 점찍기기능 */
DWORD WINAPI ThreadFunc(LPVOID temp){
int iCount;
TCHAR buf[256];
HDC hdc = GetDC(hWndMain);
// a에 대하여 카운트 시키기
iCount = 0;
for (int i = 0; i < lstrlen(str); i++){
if (str[i] == TCHAR('a')) iCount++;
Sleep(10); //Complex BackGorund Job (네?)
}
// 카운트 한 내용 출력
wsprintf(buf, TEXT("%c의 개수 : %d"), TCHAR('a'), iCount);
TextOut(hdc, 10, 10, buf, lstrlen(buf));
ReleaseDC(hWndMain, hdc);
return 0;
}
/* 윈프록 > switch > case WM_CHAR */
case WM_CHAR:
len = lstrlen(str);
str[len] = (TCHAR)wParam;
str[len + 1] = 0;
/* 키 입력 발생 시 스레드 작동*/
hThread = CreateThread(NULL, 0, ThreadFunc, NULL, 0, &ThreadID);
InvalidateRect(hWnd, NULL, FALSE);
return 0;
/* 윈프록 > switch > case WM_CREATE */
case WM_CREATE:
hWndMain = hWnd;
//CloseHandle(hThread);
return 0;
(2) 실행결과
안 예뻐.
1. Rand-Key-BackGround2, 멀티스레드 적용하기
인자전달을 통해 A,B,C,D 각각을 세는 스레드를 만들자
(0) 우선, 포인터를 다시 정리해보자
int *a, *b, c = 6, d; //메모리 잡음
a = &c;
b = &d;
*b = *a // 왼측: 위치, 오른쪽: 값, => b가 가리키는 위치에 a가 가리키는 값을 넣겠다.
int *a *b, c = 6, d;
a=&c
b=%d;
/* 까지 진행했을 때는 다음과 같음 */
주소 1000 [ ] d // 1000번 자리에 빈 값을 d가 차지한다
주소 1004 [6] c // 1004번 자리에 6값을 c가 차지한다
주소 1008 [주소 1000] b //1008번 자리에 주소1000을 가리키는 b가 있다
주소 1012 [주소 1004] a // 1012번 자리에 주소1004를 가리키는 a가 있다
*b = &a
/*위 코드까지 진행했을 때는 다음과 같음 */
주소 1000 [5] d // 2) b가 가리킨 1000(d)자리에 a가 가리킨 값(c=5)을 넣는다
주소 1004 [5] c
주소 1008 [주소1000] b // 1)b는 주소 1000(d)을 가리키고
주소 1012 [주소1004] a
(1) 소스코드
//스레드로 넘길 인수 구조체 추가
struct Threadparam {
int x, y;
TCHAR ch;
} Param[4] = {
{ 10, 10, TCHAR('a') },
{ 10, 30, TCHAR('b') },
{ 10, 50, TCHAR('c') },
{ 10, 70, TCHAR('d') }
};
DWORD WINAPI ThreadFunc(LPVOID temp) {
int iCount = 0;
TCHAR buf[256];
HDC hdc = GetDC(hWndMain);
/* 각 문자에 대하여 문자 수 카운팅 */
Threadparam* tp = (Threadparam*)temp;
for (int i = 0; i < lstrlen(str); i++){
if (str[i] == tp->ch) iCount++;
Sleep(10);
}
wsprintf(buf, TEXT("%c의 개수 ; %d"), tp->ch, iCount);
TextOut(hdc, tp->x, tp->y, buf, lstrlen(buf));
ReleaseDC(hWndMain, hdc);
return 0;
}
/* 윈프록 > WM_CHAR */
case WM_CHAR:
len = lstrlen(str);
str[len] = (TCHAR)wParam;
str[len + 1] = 0;
//한 번 입력 > 문자 각각에 대한 스레드 발생
for (i = 0; i < 4; i++){
CloseHandle(CreateThread(NULL, 0, ThreadFunc, &Param[i], 0, &ThreadID));
}
InvalidateRect(hWnd, NULL, FALSE);
return 0;
case WM_CREATE:
hWndMain = hWnd;
return 0;
(2) 실행결과
그러나 문제가 있다. WM_CHAR케이스에 넣어놨으니, 키를 누를 때마다 스레드를 생성하는 비효율적인 작업이 일어난다