카테고리 없음

win32의 SendMessage 함수와 쓰레드

wafe 2007. 5. 24. 13:01
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

쓰레드 아이디는 실행할 때마다 바뀐다.