[windowsAPI] 11주차(2), sub classing &윈도우 경계를 넘는 메시지 전달

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

 

 

 

1. SubClassing 작업하기

Enter키는 사용하는 플롯폼마다 다양한 역할로 쓰인다. 이 엔터키에 대해서 SubProc으로 분리시켜 작성하자.

=> 의문1: SubCalssing은 곧 상속을 이용한 작업을 의미하는데, 이게 상속 방법이라 보이지 않는다. 하위클래스가 아니라, 진짜 세부기능으로 조각내어 분리했다는 의미가 아닐까.

 

(1) 소스코드

포인트는 해당 기능을 별도의 함수로 분리시켰다는 것이다.

//edit컨트롤 사용하기(텍스트 편집을 위해)
#define ID_EDIT1 100
#define ID_EDIT2 101
HWND hEdit1, hEdit2;
WNDPROC OldEditProc;

// subClassing 하기
LRESULT CALLBACK EditSubProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) {
	switch (iMessage) {
	case WM_KEYDOWN:
		if (wParam == VK_RETURN) {
			MessageBox(hWnd, TEXT("엔터키가 입력되었음."), TEXT("Edit"), MB_OK);
			SetFocus(hWnd);
		}
	}
	return CallWindowProc(OldEditProc, hWnd, iMessage, wParam, lParam); // oldEditProc에 파라미터들을 넣어준다 (이벤트를 이쪽으로 실행시킨다)
}

//winProc
	PAINTSTRUCT ps;
	HDC hdc;
	TCHAR* Mes = TEXT("ENTER KEY 입력을 감시함");

	switch (iMessage) {
	case WM_CREATE:
		hEdit1 = CreateWindow(TEXT("edit"), NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL, 10, 10, 200, 25, hWnd, (HMENU)ID_EDIT1, g_hInst, NULL);
		hEdit2 = CreateWindow(TEXT("edit"), NULL, WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL, 10, 50, 200, 25, hWnd, (HMENU)ID_EDIT1, g_hInst, NULL);
		SetFocus(hEdit1);
		OldEditProc = (WNDPROC)SetWindowLongPtr(hEdit1, GWLP_WNDPROC, (LONG_PTR)EditSubProc); //처음에는 hEdit1 윈도우에 EditSubProc 함수를 작동시킨다
		return 0;
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		TextOut(hdc, 10, 100, Mes, lstrlen(Mes));
		EndPaint(hWnd, &ps);
		return 0;
	case WM_DESTROY:
		SetWindowLongPtr(hEdit1, GWLP_WNDPROC, (LONG_PTR)OldEditProc);
		PostQuitMessage(0);
		return 0;
	}
	return(DefWindowProc(hWnd, iMessage, wParam, lParam));

 

  • SetFocus(HWND hWnd) : 이전에 포커스를 갖고 있던 윈도우의 핸들을 리턴한다
    - hWnd: 포커스를 가질 윈도우의 핸들, 무효한 윈도우 혹은 같은 스레드에 있다면 리턴값이 NULL이 됨(키보드 입력 무시)
  • CallWindowProc(pOldProc, hWnd, uMsg, wParam, lParam) : 지정된 창 procedure에 메시지를 전달한다
    - pOldProc: 이전 창 프로시저 포인터
    - hWnd: 메시지 처리를 위한 창 procedure
    - Msg: 메시지를 지정
    - wParam, lParam 추가적인 메시지의 정보를 지정
  • SetWindowLong( HWND hWnd, int nIndex, LONG dwNewLong) : 윈도우 핸들의 속성을 변경함
    - hWnd: 속성을 변경하려는 윈도우 핸들
    - nIndex: 변경하고자 하는 속성을 지정 (ex. GWL_EXSTYLE, GWL_STYLE 등)
    - dwNewLong: 새로 변경할 32q비트값 (nIndex에 따라 값의 의미가 달라짐)
    => 여기서는 윈도우 프로시저의 번지(GWL_WNDPROC)을 EditSubProc로 바꿨다.

(2) 실행결과

첫번재 텍스트 박스에  Enter키를 누르면 눌렀음을 확인하는 메시지박스가 나타난다.

 

 

 

2. 윈도우 경계를 넘어서 메시지 전달하는 프로그램 만들기(ft. SubClassing작업)

(1) 소스코드

// WM_USER는 0x400이므로 0x401의 값을 가진 WM_SORI라는 메시지를 정의해서 사용 할 수 있다. 고 함.
#define WM_SORI WM_USER+1

// WinProc
	HDC hdc;
	PAINTSTRUCT ps;
	HWND hWndSori;
	TCHAR *Mes = TEXT("상대 프로그램에 메시지 발송");

	switch (iMessage) {
	case WM_LBUTTONDOWN:
		hWndSori = FindWindow(NULL, TEXT("UserMes"));
		if (hWndSori == NULL) {
			MessageBox(hWnd, TEXT(" 상대프로그램이 존재하지 않습니다."),
				TEXT("이런!"), MB_OK);
		}
		else {
			SendMessage(hWndSori, WM_SORI, 0, 0);
		}
		return 0;
	case WM_PAINT:
		hdc = BeginPaint(hWnd, &ps);
		TextOut(hdc, 50, 50, Mes, lstrlen(Mes));
		EndPaint(hWnd, &ps);
		return 0;
	case WM_DESTROY:
		PostQuitMessage(0);
		return 0;
	}
	return (DefWindowProc(hWnd, iMessage, wParam, lParam));

 

  • FindWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName): 윈도우 검색을 통해 핸들을 얻음
    - lpClassName: 검색에 사용할 윈도우 클래스 이름( 혹은 아톰값), NULL이 모든 윈도우 클래스 검색
    - lpWindowName: 검색에 사용할 윈도우의 캡션 문자열, NULL이면 모든 캡션의 윈도우를 검색

 

(2) 실행결과

좌에서 마우스 이벤트가 일어나면 우에서 메아리 애니메이션이 윈도우 내 해당 위치에 나타난다.