유돌이

calendar

1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

Notice

2008. 12. 30. 23:14 C/C++/MFC

<윈도우 프로시저>

1. 윈도우 프로시저는 윈도우 클래스당 하나씩 배정된다
2. 같은 윈도우 클래스로 부터 만들어진 윈도우는 같은 윈도우 프로시저를 공유하며 동일한 동작을 한다

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);
- 운영체제에 의해 호출되는 콜백함수이므로 사용자가 호출할 수 없다. SendMessage함수 등으로 간접 호출 가능
- 관심없는 메시지는 DefWindowProc으로 보내 디폴트 처리한다

3. 윈도우 프로시저는 재진입(ReEntrant)이 가능하다. 즉 WndProc 실행 중에 또 WndProc이 호출될 수 있다
- 재진입이 가능하므로 가급적이면 지역변수를 적게 사용하는 것이 좋다


<메시지 큐>

1. 큐 메시지 : 메시지 큐로 들어가는 메시지
- 주로 사용자 입력으로 생성되는 메시지
- WM_KEYDOWN, WM_LBUTTONDOWN, WM_PAINT, WM_TIMER, WM_QUIT 등
- 발생 직후 시스템 메시지 큐에 저장되어 스레드 메시지 큐로 보내지며 최종적으로 윈도우 프로시저에 의해 입력된 순서로 처리된다

2. 비큐 메시지 : 큐로 들어가지 않고 곧바고 윈도우 프로시저로 보내지는 메시지
- 윈도우에게 특정 사실을 알리거나 명령을 보내기 위해서 보내지는 메시지
- 신속하게 처리된다
- API함수 실행 중이나 또느 큐 메시지를 처리하는 중에 추가로 발생한다
- WM_CREATE, WM_SIZE, WM_MOVE, WM_DESTROY, WM_ACTIVATE

3. 운영체제는 하나의 시스템 메시지 큐를 관리하며 각 스레드 별로 하나씩 메시지 큐를 생성한다

4. 시스템 아이들(System Idle)
- 시스템 큐의 메시지를 하나씩 꺼내 어떤 스레드로 보낼 것인지 판단하여 스레드 메시지 큐로 보내고 시스템 큐에서 메시지를 지운다

5. 스레드 메시지 큐에 들어온 메시지는 메시지 루프에 의해 꺼내지고 해당 윈도우의 윈도우 프로시저로 보내져 처리되고 스레드 메시지 큐에서 삭제된다

6. 스레드가 생성될 때 시스템은 디폴트로 메시지 큐를 생성하지 않으며 스레드가 최초 GDI함수나 User함수를 호출할 때 메시지 큐를 만들어 준다


<메시지 루프>

typedef struct tagMSG{
 HWND hwnd;
 UINT message;
 WPARAM wParam;
 LPARAM lParam;
 DWORD time;  // 발생한 시간
 POINT pt;  // 발생시의 마우스 좌표
} MSG;  // 메시지 구조체

DWORD GetMessagePos(VOID);
LONG GetMessageTime(VOID);
- 마우스 트리플 클릭 등을 검출할 때 시간과 위치 정보가 중요하게 사용된다

BOOL GetMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax);
- 스레드 큐에 대기중인 메시지를 꺼내 첫번째 인수로 전달된 MSG구조체에 복사하고 메시지를 큐에서 제거하고 TRUE를 리턴한다
- 가져온 메시지가 WM_QUIT이면 FALSE를 리턴한다
- hWnd에 윈도우 핸들을 주면 이 윈도우와 그 차일드로 보내지는 메시지만 가져오고 NULL이면 현재 스레드에 속한 모든 메시지를 가져온다
- 메시지 필터링을 하지 않을 경우 세네번째 인자는 0으로 한다
- 메시지 필터링은 프로그램 무한 대기 상태에 빠지거나 오작동 위험이 있으므로 사용하지 않는게 좋다

TranslateMessage함수
- 가상키 입력을 문자 입력(WM_CHAR)로 바꾸는 역할을 한다
- 가상키 입력이 아니면 아무 처리도 하지 않는다

DispatchMessage함수
- 메시지를 윈도우 프로시저로 보내 처리하도록 한다
- MSG 구조체의 hwnd를 보고 정확하게 목적 윈도우의 메시지 처리 함수로 메시지를 전달한다


<PeekMessage>

1. GetMessage함수가 스레드에서 메시지를 가져올 때 메시지가 없다면 메시지가 들어올 때까지 무한 대기한다
- 이 시간에 다른 프로세스가 CPU를 쓸 수 있도록 양보한다
- 멀티 태스킹의 핵심 함수이다
- GetMessage에서 놀고 있는 시간을 데드 타임이라고 한다
- GEtMessage함수는 메시지를 받기 전에는 리턴하지 않으므로 데드 타임을 사용할 수 없다

BOOL PeekMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax, UINT wRemoveMsg);
- 메시지 큐에서 메시지를 꺼내거나 검사하되 메시지가 없더라도 즉각 리턴한다
- 리턴값이 TRUE이면 메시지가 있다는 뜻이고 FALSE이면 메시지가 없다는 뜻이다
- wRemoveMsg 메시지가 있을 경우 큐에서 제거할 것이지 말것인지 지정(PM_REMOVE, PM_NOREMOVE)
- PM_NOREMOVE를 이용하여 살짝 엿보기만 할 수 있다

2. 메시지 펌프
- 다른 메시지를 처리하는 중에 큐에서 메시지를 꺼내는 코드
- PeekMessage를 이용한 메시지 펌프는 메시지 시스템을 이해하는데도 비중이 높은 주체이다


<아이들 타임>

1. 아이들 타임(Idle Time), 데드 타임(Dead Time)
- 응용 프로그램이 아무 것도 하지 않고 노는 시간
- 대부분 GetMessage함수에서 대기중이다

2. 아이들 타임 작업
- 아이들 타임에 할만한 작업은 툴바, 상태란 등의 상태 갱신, 사용하지 않는 자원 회수, 단순 장식을 위한 애니메이션
- 수시로 해야 하되 긴급하지 않고 속도를 희생하면서까지 정확할 필요 없는 작업을 한다

3. 아이들 타임을 찾는 방법
- 멀티 스레드나 타이머는 본질적이 아이들 타임이 아니다
- GetMessage함수를 경우 찾을 수 없고 PeekMessage함수를 써야 한다
- 아이들 타임 작업은 틈틈이 하되 꼭 필요할 때만 하도록 해야 한다

WaitMessage();
- 큐에 메시지가 들어올 때까지 대기하되 메시지가 없으면 다른 프로세스에게 실행 시간을 양보한다


<키 상태 조사하기>

WM_KEYDOWN
- 키가 눌러질 때 발생한다
- wParam을 읽어 어떤 키가 입력 되었는지 알 수 있다

SHORT GetKeyState(int nVirKey);
SHORT GetAsyncKeyState(int nKey);
- 키가 눌러져 있는지 떨어져 있는지 조사하는 함수
- 일반 키가 눌러졌을 경우 최상위 비트가 1, 그렇지 않으면 0. Caps Lock같은 토글키가 켜져 있으면 최하위 비트가 1, 아니면 0
- GetKeyState함수는 메시지가 발생했을 때 상황을 조사하고 GetAsyncKeyState함수는 메시지가 처리될 때 상황을 조사

BOOL GetKeyboardState(PBYTE lpKeyState);
- 모든 가상키의 상태를 한꺼번에 조사
- 256바이트의 배열을 넘겨주어야 한다

폴링(Polling)
- 입력 메시지를 받지 않고 자신이 원할 때 정보를 조사하는 방식
- 신호를 기다리는 것이 아니라 직접 조사한다


<트리플 클릭>
- 일정한 범위 내의 화면 좌표를 짧은 시간안에 연속으로 세번 누르는 동작


'C/C++/MFC' 카테고리의 다른 글

Invalidate() , OnDraw(CDC* pDC)  (0) 2009.01.02
MFC (디바이스 컨텍스트와 관련 클래스)  (0) 2008.12.30
API 기초??  (0) 2008.12.30
const 사용법  (0) 2008.12.30
C프로그래밍 별모양~  (0) 2008.12.30
posted by 유돌이