'RegisterWindowMessage'에 해당되는 글 2건

  1. 2010.07.21 [ WPF ] RegisterWindowMessage 를 이용한 프로그램 간 메시지 보내기 178
  2. 2010.07.11 [ WPF ] 윈도우 이벤트 4
Window/WPF2010. 7. 21. 21:22

서로 다른 응용 프로그램 사이에 메시지를 전달하는 방법에 대해 알아보겠습니다.

API 함수인 RegisterWindowMessage PostMessage 를 활용하면 되는데요.

 

RegisterWindowMessage 메시지를 등록하여 사용하기 때문에 서로 다른 프로그램에서 메시지를 약속하여야 합니다.

 

다음과 같은 원형을 가지고 있고 송수신 하는 프로그램에서 모두 실행하여야 합니다.

 uint RegisterWindowMessage (string lpString);

 

이 후에 PostMessage 함수를 사용하여 메시지를 보내주면 됩니다.

 bool PostMessage (IntPtr hWnd, uint Msg, uint wParam, uint lParam);

 

PostMessage 의 첫 번째 인자로 HWND_BROADCAST(0xffff) 값을 넣어주어야

다른 프로그램으로 메시지를 전송할 수 있습니다.

 

두 번째 인자로는 RegisterWindowMessage 함수를 실행한 반환 값을 넣어 주면 됩니다.

 

세 번째와 네 번째 인자를 사용하여 추가적으로 정보를 보낼 수 있습니다. (wParam : 2Byte, lParam : 4Byte)

이 방법은 4Byte 이상의 정보를 보낼 수 없다는 단점이 있습니다.

 

이 두 함수를 통해서 다른 프로그램으로 메시지를 보낼 수 있게 되었습니다.

 

그럼, 이제 메시지를 수신하는 방법을 알아보겠습니다.

윈도우 메시지를 수신해야 하는데요.

지난 번 포스팅 방법을 사용하겠습니다. ( http://shine10ee.blog.me/10089908443 )

 

다음과 같이 조건문을 거친 후 사용하시면 되겠습니다.

 void ComponentDispatcher_ThreadFilterMessage(ref MSG msg, ref bool handled)

{

    if (msg.message == 메시지 반환 값 && msg.wParam != 윈도우 핸들)

    {

       // To do ( msg.lParam 값으로 정보 확인 )

    }

}

 

이로써 WPF 에서 약속한 메시지를 수신할 수 있게 되었습니다.

 

간단한 예제로써 MFC 와 WPF 사이에 메시지를 송 수신하는 프로그램을 만들어 보았습니다.

MFC 프로그램의 코드에서도 위와 마찬가지 과정을 포함하고 있습니다.

 

소스는 다음과 같습니다.

 

[ WPF ]

 public partial class Window1 : Window

{

    private uint message;

    private IntPtr handle;

 

    public const uint HWND_BROADCAST = 0xffff;

 

    [DllImport("user32.dll", CharSet = CharSet.Unicode)]

    public static extern uint RegisterWindowMessage(string lpString);

 

    [DllImport("user32.dll", CharSet = CharSet.Unicode)]

    public static extern bool PostMessage(IntPtr hWnd, uint Msg, uint wParam, uint lParam);

 

    public Window1()

    {

        InitializeComponent();

    }

 

    protected override void OnSourceInitialized(EventArgs e)

    {

        base.OnSourceInitialized(e);

 

        handle = new WindowInteropHelper(this).Handle;

        message = RegisterWindowMessage("User Message");

        ComponentDispatcher.ThreadFilterMessage += new ThreadMessageEventHandler(ComponentDispatcher_ThreadFilterMessage);

    }

 

    void ComponentDispatcher_ThreadFilterMessage(ref MSG msg, ref bool handled)

    {

        if (msg.message == message && msg.wParam != handle)

        {

            MessageBox.Show("MFC Message : " + msg.lParam.ToString());

        }

    }

 

    private void Button_Click(object sender, RoutedEventArgs e)

    {

        PostMessage((IntPtr)HWND_BROADCAST, message, (uint)handle, 100);

    }

}


 

[ MFC ]

BOOL CRegisterWindowMessage_MFCDlg::OnInitDialog()

{

    CDialog::OnInitDialog();

 

    // 이 대화 상자의 아이콘을 설정합니다. 응용 프로그램의 주 창이 대화 상자가 아닐 경우에는

    //  프레임워크가 이 작업을 자동으로 수행합니다.

    SetIcon(m_hIcon, TRUE);            // 큰 아이콘을 설정합니다.

    SetIcon(m_hIcon, FALSE);        // 작은 아이콘을 설정합니다.

 

    // 메시지 등록

    message = RegisterWindowMessage(_T("User Message"));

 

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

}

 

void CRegisterWindowMessage_MFCDlg::OnBnClickedButton1()

{

    // 메시지 보내기

    ::PostMessage(HWND_BROADCAST, message, (WPARAM)this->GetSafeHwnd(), 200);

}

 

LRESULT CRegisterWindowMessage_MFCDlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)

{

    // 메시지 수신

    if(message == this->message && (HWND)wParam !=this->GetSafeHwnd())

    {

        char buf[256];

 

        sprintf_s(buf, "WPF Message : %d", lParam);

        MessageBox(buf);

    }

 

    return CDialog::WindowProc(message, wParam, lParam);

}

 

[ 실행 화면 ]

               [ WPF ]                                                       [ MFC ]

 

 

                                              [ MFC -> WPF ]

 

 

                                             [ WPF -> MFC ]

 

'Window > WPF' 카테고리의 다른 글

[ WPF ] Custom Slider  (4) 2010.08.13
[ WPF ] ClickOnce로 배포하기  (9) 2010.08.03
[ WPF ] BackgroundWorker  (2) 2010.07.11
[ WPF ] 윈도우 이벤트  (4) 2010.07.11
[ WPF ] OpenCV로 캠 화면 띄우기  (3) 2010.06.20
Posted by 열ㅇl
Window/WPF2010. 7. 11. 15:26

윈도우 이벤트를 가로채기 위해서 HwndSource.AddHook 방법을 많이 사용하지만 이 방법은

조금 느린 반응과 HwndSource.FromHwnd 로 얻어낸 HWND 윈도우에서 발생하는 메시지만 수신된다는 단점이 있는데요.
 
이 단점이 없는 방법으로 ComponentDispatcher.ThreadMessage 가 있습니다.

사용법은 다음과 같습니다.
 

  private void Window_Loaded(object sender, RoutedEventArgs e)

 {

    ComponentDispatcher.ThreadFilterMessage +=

       new ThreadMessageEventHandler(ComponentDispatcher_ThreadFilterMessage);

 }



void ComponentDispatcher_ThreadFilterMessage(ref MSG msg, ref bool handled)

{

   switch (msg.message)

   {

        // To do

   }

}

 
Win32의 메시지와 동일한 값으로 필요한 메시지들을 다음과 같이 정의하여 비교하시면 됩니다.
 

uint WM_CREATE = 0x0001;

uint WM_DESTROY = 0x0002;

uint WM_MOVE = 0x0003;

uint WM_SIZE = 0x0005;

 

참고로 윈도우의 핸들은 다음과 같이 얻어 올 수 있습니다.

IntPtr hwnd = new WindowInteropHelper(this).Handle;

Posted by 열ㅇl