[windowsAPI] 12주차, Thread사용하기

교내 전공과목인 윈도우즈 API수업을 정리합니다

 

 

* 참고용 주소: http://www.soen.kr/lecture/win32api/reference/Function/Alphabetic.htm

1. ButtonSubClassing

드디어 VS 2013버전으로 바꿨다. button반응에 대한 SubSystemClassing을 하자

(0). 프로펄티 설정

문자집합 설정해주기(Character set > user multi-Byte 선택

 

(1). 소스코드

/* 헤더파일 */
#include <string>


#define WM_SORI WM_USER +1// WM_SORI = 0x401값을 가지는 메시지임을 정의. (WM_USER가 0x400값임) 
/* 필요한 변수 */
HWND hButton, hWndSori; //버튼 핸들
WNDPROC OldButtonProc;
char buffer[20]; // 출력할 문구 공간

/* ButtonSubProc */
LRESULT CALLBACK ButtonSubProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam){
	switch (iMessage){
	case WM_LBUTTONDOWN:
		CallWindowProc(OldButtonProc, hWnd, iMessage, wParam, lParam);
		hWndSori = FindWindow(NULL, TEXT("UserMes")); //캡션이 UserMes인 Window를 찾는다
		if (hWndSori == NULL){
			MessageBox(hWnd, TEXT(" 상대프로그램이 존재하지 않습니다."),
				TEXT("이런!"), MB_OK);
		}
		else{
			int ret = SendMessage(hWndSori, WM_SORI, 0, 0);
			sprintf(buffer, "%d", ret);
			SetFocus(NULL); // Focus를 없앤다, 없애지 않으면 모든 메시지는 hButton으로 전달된다
			//hWndSori 윈도우의 윈도우 프록시져를 호출한다
		}
		return 0; // 즉, break
	}
	return CallWindowProc(OldButtonProc, hWnd, iMessage, wParam, lParam);
}

/* WndProc > case WM_CREATE */
		hButton = CreateWindow(TEXT("button"), TEXT("Click me"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 10, 10, 200, 25, hWnd, (HMENU)101, g_hInst, NULL);
		OldButtonProc = (WNDPROC)SetWindowLongPtr(hButton, GWLP_WNDPROC, (LONG_PTR)ButtonSubProc);
		break;
        
/* WndProc > case WM_PAINT */
		hdc = BeginPaint(hWnd, &ps);
		TextOut(hdc, 50, 50, Mes, lstrlen(Mes));
		TextOut(hdc, 50, 100, TEXT(buffer), lstrlen(buffer));
		EndPaint(hWnd, &ps);
		return 0;

 

(2). 실행결과

좌측창에서 버튼 누르면 우측창에서 반응함

 

2. ButtonSubClassing2

UserMes에서 리턴값을 가져와 출력하는 기능을 추가해보자

(1). 소스코드

//UserMes에서 리턴값 가져오기 위한 추가 변수
int ret;
HWND hStatic;//출력할 레이블 핸들

//SubProc작성
LRESULT CALLBACK ButtonSubProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam){
	TCHAR buffer[20]; // 출력 문구 공간을 이번에는 내부에다 선언
	
	switch (iMessage){
	case WM_LBUTTONDOWN:
		CallWindowProc(OldButtonProc, hWnd, iMessage, wParam, lParam);
		hWndSori = FindWindow(NULL, TEXT("UserMes")); //캡션이 UserMes인 Window를 찾는다
		if (hWndSori == NULL){
			MessageBox(hWnd, TEXT(" 상대프로그램이 존재하지 않습니다."),
				TEXT("이런!"), MB_OK);
		}
		else{
			/* ret = SendMessage(hWndSori, WM_SORI, 0, 0); //찾으면 Message를 전달했었다
			sprintf(buffer, "%d", ret);
			SetFocus(NULL); // Focus를 없앤다, 없애지 않으면 모든 메시지는 hButton으로 전달된다
			hWndSori 윈도우의 윈도우 프록시져를 호출한다 */

			ret = PostMessage(hWndSori, WM_SORI, 0, 0);
			wsprintf(buffer, TEXT("리턴값: %d"), ret);
			SetWindowText(hStatic, buffer);
		}
		return 0; // 즉, break
	}
	return CallWindowProc(OldButtonProc, hWnd, iMessage, wParam, lParam);
}



// WndProc > WM_CREATE
	case WM_CREATE:
		hButton = CreateWindow(TEXT("button"), TEXT("Click me"), WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 10, 10, 200, 25, hWnd, (HMENU)101, g_hInst, NULL);
		OldButtonProc = (WNDPROC)SetWindowLongPtr(hButton, GWLP_WNDPROC, (LONG_PTR)ButtonSubProc);
		
		//레이블 컨트롤 작성
		hStatic = CreateWindow(TEXT("static"), TEXT("-"), WS_CHILD | WS_VISIBLE, 10, 100, 200, 25, hWnd, (HMENU)102, g_hInst, NULL);
		break;

(2). 실행결과

UserMes(좌측) 내부 코드에는 클릭이 들어오면 리턴값을 1로 보내겠다고 미리 작성했었다.

해당 값을 우측창이 출력하고 있다.

 

 

 

3-1. Thread를 통해 색상변화-색칠하기 작업을 하기

스레드를 통해 색상이 변해가며 색을 채우는, 다중작업을 구현하자

(1) 소스 코드

DWORD WINAPI ThreadFunc(LPVOID temp){ 
	HDC hdc;
	BYTE Blue = 0; //
	HBRUSH hBrush, hOldBrush;
	hdc = GetDC(hWndMain);
	for (;;) {
		Blue += 5;
		Sleep(20);
		hBrush = CreateSolidBrush(RGB(0, 0, Blue)); // rgb색상 값중 b에 대한 값만 5씩 변화하도록 함
		hOldBrush = (HBRUSH)SelectObject(hdc, hBrush);
		Rectangle(hdc, 10, 10, 400, 200);
		SelectObject(hdc, hOldBrush);
		DeleteObject(hBrush);
	}
	ReleaseDC(hWndMain, hdc);
	return 0;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam){
	DWORD ThreadID; 
	HANDLE hThread;

	switch (iMessage) {
	case WM_CREATE:
		hWndMain = hWnd;
		hThread = CreateThread(NULL, 0, ThreadFunc, NULL, 0, &ThreadID); // 
		CloseHandle(hThread); // 
		return TRUE;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
  • DWORD: 32비트 부호 없는 정수, LPVOID:모든 형식에 대한 포인터
  • HANDLE CreateThread(
      [in, optional]  LPSECURITY_ATTRIBUTES   lpThreadAttributes,
      [in]            SIZE_T                  dwStackSize,
      [in]            LPTHREAD_START_ROUTINE  lpStartAddress,
      [in, optional]  __drv_aliasesMem LPVOID lpParameter,
      [in]            DWORD                   dwCreationFlags,
      [out, optional] LPDWORD                 lpThreadId
    );
    => 아무튼.. 프로세스에 대한 새 스레드를 생성함
  • CloseHandle(HANDLE hObject)
    - 열려진 핸들을 닫음, 실패시 0을 리턴(성공은 0이 아닌 값), 이 함수로 핸들을 닫는단들 스레드가 파괴되는 건 아님

(2) 실행 결과

 

 

 

4. RandGrp

점을 찍는 일과, 랜덤하게 사각영역을 채워나가는 일을 동시진행하도록 스레드로 설계/구현하자.

(1) 실행 결과

결과만 보고, 구현은 13주차를 정리하는 내일의 내가.