[WinAPI] SendMessage, PostMessage

윈도우 메시지에 대한 개념은 이 블로그에서 익히길 추천합니다.

오늘은 MFC를 이용하여 메시지 사용법에 대해 알아보겠습니다.
메시지를 보내기 위해 SendMessage와 PostMessage를 사용하는데 이 둘의 차이는 동기냐 비동기냐 차이입니다.
SendMessage의 경우 메시지를 수신한 쪽에서 처리를 완료할 때까지 대기하는 함수이고, PostMessage는 수신한 쪽의 처리를 신경쓰지 않는 함수입니다.

Visual C++에서 MFC 프로젝트를 하나 생성 한 후 아래와 같이 Static Control, Edit Box를 만듭니다.

(Static : Align Text(Center), Border(True), Center Image(True))

각 컨트롤의 멤버 변수를 생성해 줍니다.

OnInitDialog에 아래와 같이 코딩합니다.

	// 이 대화 상자의 아이콘을 설정합니다.  응용 프로그램의 주 창이 대화 상자가 아닐 경우에는
	//  프레임워크가 이 작업을 자동으로 수행합니다.
	SetIcon(m_hIcon, TRUE);			// 큰 아이콘을 설정합니다.
	SetIcon(m_hIcon, FALSE);		// 작은 아이콘을 설정합니다.

	// TODO: 여기에 추가 초기화 작업을 추가합니다.
	HWND myHwnd = this->GetSafeHwnd();
	CString sMyHwnd;
	sMyHwnd.Format( _T("%x"), myHwnd );
	m_stMyHwnd.SetWindowText( sMyHwnd );

	return TRUE;  // 포커스를 컨트롤에 설정하지 않으면 TRUE를 반환합니다.

확인 버튼과, 취소 버튼을 더블 클릭하여 함수로 만들어줍니다.

확인 이벤트 처리 함수에 아래와 같이 코딩합니다.

void CMFCApplication1Dlg::OnBnClickedOk()
{
	// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
	// CDialogEx::OnOK();
	CString sTargetHwnd;
	m_edTargetHwnd.GetWindowText( sTargetHwnd );

	HWND hwnd = (HWND)_tcstol( sTargetHwnd, NULL, 16 );

	if ( NULL != hwnd )
		::SendMessage( hwnd, WM_USER + 1, 0, 0 );
}

받았으면 처리도 해야겠죠? 클래스 뷰에서 대화상자 클래스 -> 재정의 -> WindowProc를 만들어 줍니다.

그리고 아래와 같이 코딩을 해 줍니다.

LRESULT CMFCApplication1Dlg::WindowProc( UINT message, WPARAM wParam, LPARAM lParam )
{
	// TODO: 여기에 특수화된 코드를 추가 및/또는 기본 클래스를 호출합니다.
	switch ( message )
	{
	case WM_USER + 1:
		AfxMessageBox( _T("Receive") );
		break;
	}

	return CDialogEx::WindowProc( message, wParam, lParam );
}

이 상태로 아래와 같이 2개 실행 시키면 다른 프로세스에 메시지가 송수신 되는 것을 확인 해 볼 수 있습니다.

Edit Box에 상대 대화상자에 써있는 Hwnd 값을 입력해서 확인버튼을 누르면 Edit Box에 써져있는 대화상자로 메시지가 송신 됩니다. 하지만 처음에 말씀 드린 것처럼 SendMessage는 동기식이여서 Receive 메시지 박스의 확인 버튼을 누를 때까지 대기를 하게 됩니다.
대기를 주고싶지 않으시면 아래와 같이 확인 버튼 이벤트 처리 함수에 PostMessage를 입력하시면 됩니다.

void CMFCApplication1Dlg::OnBnClickedOk()
{
	// TODO: 여기에 컨트롤 알림 처리기 코드를 추가합니다.
	// CDialogEx::OnOK();
	CString sTargetHwnd;
	m_edTargetHwnd.GetWindowText( sTargetHwnd );

	HWND hwnd = (HWND)_tcstol( sTargetHwnd, NULL, 16 );

	if ( NULL != hwnd )
		::PostMessage( hwnd, WM_USER + 1, 0, 0 );
}

SendMessage와 PostMessage는 사용법은 같으니 상황에 맞게 사용하시면 됩니다.

WParam과 LParam의 값을 바꿔서도 테스트 해보세요.

SendMessage( 타겟, 메시지, WPARAM, LPARAM );
PostMessage( 타겟, 메시지, WPARAM, LPARAM );

이상으로 SendMessage, PostMessage에 대해 알아보았습니다.