SendMessage 함수는 지정된 윈도우로 메시지를 보내고, 메시지가 처리될 때까지 기다렸다가 메시지 핸들러가 반환한 값을 받아서 반환해주는 함수이다.
MFC에서는 OCX를 생성한 쓰레드가 아닌 다른 쓰레드에서는 OCX 이벤트를 발생시키는 FireXXX 함수를 호출할 수 없다. 따라서 OCX 안에서 작업 쓰레드를 따로 만들어서 작업하는 경우, 작업중에 OCX의 이벤트를 발생시키려면 OCX를 만든 쓰레드로 전환(컨텍스트 스위치)해야 하는데, 이 때 SendMessage 함수를 쓸 수 있다.
현재 쓰레드에서 만들지 않은 윈도우 핸들을 넣어서 SendMessage 함수를 호출하면, 현재 쓰레드는 block되고 그 윈도우를 만든 쓰레드로 작업이 전환된 후 이벤트 핸들러가 호출된다. 이벤트 핸들러가 결과를 반환하면 다시 SendMessage 함수를 호출한 쓰레드로 작업이 전환된다.
확인하기 위한 간단한 테스트 프로그램을 만들어봤다.
실행하면 이런 디버그 메시지가 나온다.
쓰레드 아이디는 실행할 때마다 바뀐다.
MFC에서는 OCX를 생성한 쓰레드가 아닌 다른 쓰레드에서는 OCX 이벤트를 발생시키는 FireXXX 함수를 호출할 수 없다. 따라서 OCX 안에서 작업 쓰레드를 따로 만들어서 작업하는 경우, 작업중에 OCX의 이벤트를 발생시키려면 OCX를 만든 쓰레드로 전환(컨텍스트 스위치)해야 하는데, 이 때 SendMessage 함수를 쓸 수 있다.
현재 쓰레드에서 만들지 않은 윈도우 핸들을 넣어서 SendMessage 함수를 호출하면, 현재 쓰레드는 block되고 그 윈도우를 만든 쓰레드로 작업이 전환된 후 이벤트 핸들러가 호출된다. 이벤트 핸들러가 결과를 반환하면 다시 SendMessage 함수를 호출한 쓰레드로 작업이 전환된다.
확인하기 위한 간단한 테스트 프로그램을 만들어봤다.
// 작업 쓰레드 본체
UINT ThreadFunc(LPVOID pParam)
{
HWND *wnd = ((HWND *)pParam);
TRACE(_T("thread id: %d -- sending message\n"), GetCurrentThreadId());
int ret = SendMessage(*wnd, WM_USER + 10, NULL, NULL);
TRACE(_T("thread id: %d -- "), GetCurrentThreadId());
TRACE(_T("SendMessageResult: %d\n"), ret);
delete wnd;
return 0;
}
void CThreadSendMessageTestDlg::OnBnClickedButton1()
{
TRACE(_T("thread id: %d -- "), GetCurrentThreadId());
TRACE(_T("begin new thread\n"));
// 작업 쓰레드를 만들어서 현재 윈도우의 핸들을 전해줌.
HWND *wnd = new HWND;
*wnd = this->GetSafeHwnd();
AfxBeginThread(ThreadFunc, (LPVOID)(wnd));
}
LRESULT CThreadSendMessageTestDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == WM_USER + 10)
{
TRACE(_T("thread id: %d -- "), GetCurrentThreadId());
TRACE(_T("got WM_USER + 10\n"));
return -10;
}
return CDialog::WindowProc(message, wParam, lParam);
}
실행하면 이런 디버그 메시지가 나온다.
thread id: 204 -- begin new thread
thread id: 3692 -- sending message
thread id: 204 -- got WM_USER + 10
thread id: 3692 -- SendMessageResult: -10
thread id: 3692 -- sending message
thread id: 204 -- got WM_USER + 10
thread id: 3692 -- SendMessageResult: -10
쓰레드 아이디는 실행할 때마다 바뀐다.