윈도우간 통신
SendMessage() 와 PostMessage(), PostThreadMessage()





PostMessage()

1. 원형
BOOL PostMessage(
    HWND hWnd,     // 이 메시지를 받을 윈도우 핸들
    UINT Msg,      // 전달할 메시지
    WPARAM wParam, // 여분 데이터
    LPARAM lParam  // 여분 데이터
); 


2. 동작
   - Msg 인수로 지정된 메시지를 hWnd 윈도우의 메시지 큐에 집어 넣는다.
   - 메시지를 받은 윈도우는 윈도우 프로시저에서 이 메시지를 처리한다.
   - 메시지를 메시지 큐에 넣기만 하고 바로 리턴 한다.
   - 큐에 붙인 메시지는 GetMessage() 에 의해 읽혀지고, DispatchMessage() 에 의해 윈도우 프로시저로 보내짐

3. 리턴값에 대하여
    - TRUE : 메시지를 메시지 큐에 붙이기 성공
    - FALSE : 메시지를 메시지 큐에 붙이기 실패
    ※ 가급적이면 리턴값을 점검해 보는 것이 좋다.
        메시지 큐는 크기가 한정되어 있기 때문에 고속으로 전송되는 모든 메시지를 다 수용하지 못할 수도 있기때문

4. 장점
   - 메시지를 메시지 큐에 넣기만 하고 곧바로 리턴 하므로 보내는 쪽에서 "블록(Block)" 시키지 않는다.
      따라서 바로 다른 작업을 할 수 있다.

5. 단점
   - 메시지를 메시지 큐에 넣고 리턴한다. 이때 메시지 큐에 대기하고 있는 다른 메시지가 있으면 해당 메시지가
     바로 처리되지 않을 수도 있다.
   - 메시지가 언제 처리 될지도 예측할 수 없으므로 메시지의 wParam, lParam 에는 지역 포인터를 사용하지
     않아야 한다.

     (메시지를 붙일 시점에는 포인터가 존재했더라고 메시지가 처리될 시점에는 포인터가 무효해 질수도 있다.)
    
6. 활용
   - 급하게 처리할 필요가 없는 처리의 메시지
   - 지금 하고 있는 작업을(메시지를 보내는 입장에서) 완전히 끝내야만 처리할 수 있는 메시지

7. 첫 번째 인수 hWnd 가 NULL 인 경우
   - 특정 윈도우에게 신호를 보내기 위한 것이 아니라 응용 프로그램 전반에 걸친 작업 지시를 보낼 때 사용
   - 대상 윈도우가 없기 때문에 이 메시지는 윈도우 프로시저가 처리할 수 없으며 윈도우 프로시저로 가기전인
     메시지 루프에서 직접 처리해 주어야 한다.
while (GetMessage(&Message, 000)) {
    if (Message.message == WM_SOME) {
        // 직접 처리
    } else {
        TranslateMessage(&Message);
        DispatchMessage(&Message);
    }
}
 
   - GetMessage로 메시지를 꺼낸 후 곧바로 메시지 ID를 비교해 보고 스레드를 위한 메시지 인지 검사해 본다
   - 만약 스레드를 위한 메시지라면 메시지 루프에서 직접 처리해야 하며 DispatchMessage 함수로 보내지말것
   - 대상 윈도우가 지정되지 않은 메시지이기 때문에 이 메시지를 받아줄 윈도우 프로시저가 없기 때문.
   - PostMessage 함수가 메시지를 붙여넣는 큐가 윈도우를 위한 큐가 아니라 스레드를 위한 큐이기 때문에 가능




PostThreadMessage()

1. 원형
BOOL PostThreadMessage(
     DWORD idThread,    // 스레드 ID
     UINT Msg,          // 전달할 메시지
     WPARAM wParam,
     LPARAM lParam
);
  
2. 사용 목적
   - 다른 스레드의 메시지 큐에 메시지를 붙일 때 사용
   - 스레드 외부에서 특정 스레드로 메시지를 전달할 때

3. 한계
   - 작업자 스레드에선 사용할 수 없고, 사용자 인터페이스 스레드 에서만 사용 가능




SendMessage()

1. 원형
BOOL SendMessage(
    HWND hWnd,     // 이 메시지를 받을 윈도우 핸들
    UINT Msg,      // 전달할 메시지
    WPARAM wParam, // 여분 데이터
    LPARAM lParam  // 여분 데이터
); 


            ※ SendMessage() 와 PostMessage() 함수의 원형은 동일

2. 동작
   - 메시지를 메시지 큐에 넣는 것이 아니라 곧바로 윈도우 프로시저로 보내 즉각 처리하도록 한다.
   - 메시지가 완전히 처리되기 전에 리턴하지 않는다. (블록 시킴)

3. 장점
   - 보낸 메시지의 정확한 처리 보장

4. 단점
   - 보낸 메시지가 완전히 처리 될때까지 기다리므로, 메시지를 보낸쪽은 블록 상태에 머물게 된다.
     영영 블록되어 프로그램이 죽을 수도 있다.
   ※ 메인 스레드에서 다른 스레드로 메시지를 보낼때 SendMessage() 의 사용은 위험하다

5. 활용
   - 부모 윈도우와 차일드 컨트롤 간의 통신
   - 윈도우간 정확한 데이터 전송 및 처리를 위한 통신
   - 윈도우의 특정 메시지는 SendMessage() 만을 사용해야 하는 경우도 있다. (WM_COPYDATA)




cf)참고 - Windows API 정복 (김상형)


■  사용 예

1. SendMessage() 함수로 출력 시켰을때

2. PostMessage() 함수로 출력 시켰을때

※ SendMessage() 함수로 출력 시킨 결과가 올바른 값이다.
   하지만 PostMessage() 함수로 출력 시키면 제일 처음에 전송된 데이터가 처리 되기 전에 나중에 
   나중에 전송된 데이터로 값을 찍어 버려서 올바른 값이 출력되지 않는다.



##
Posted by six605
,