본문 바로가기
개발 이야기/개발자 이야기

[MFC] Copydata IPC 구현하기

by 런던살자 2019. 7. 2.

안녕하세요 마블랑입니다.

 

윈도우 프로세스들을 구현하다보면 프로세스간의 내부통신을 해야할때가 있습니다.

 

이러한 내부통신은 공유메모리를 이용하여 구현할수 있지만 그것보다 더 간단한 윈도우메시지를 이용하여 내부통신을 구현하려고 합니다. 

 

이번 포스팅은 MFC 프로세스로 내부통신을 구현하는 방법에 관한 포스팅입니다.

 

현재는 MFC프로세스들간의 내부통신이지만 MFC 프로세스와 C# 프로세스간의 내부통신도 가능합니다.

 

 

 

먼저 MFC 프로젝트를 생성해주시기 바랍니다. SDI나 MDI도 가능하지만 개인적으로 Dialog가 편해 대화상자기반으로 구현하였습니다.  (SDI나 MDI도 가능하니 처리부분만 보시면 될거 같습니다.)

 

화면 UI를 꾸며주세요. 마블랑은 수신되는 프로세스와 메시지내용을 입력할수 있게 이미지와 같이 꾸몄습니다.

 

샘플을 제작한 거라서 모두 동적으로 입력받게 하였지만 내부적인 처리만 원한다면 프로세스명과 메시지를 고정으로 할수 있습니다.

 

UI가 꾸며진 다음에 클래스 마법사(폼 우클릭 - 클래스 마법사)에서 메시지 탭 - WM_COPYDATA를 추가하여 주세요 

 

Copydata 메시지는 프로세스의 제목표시줄 이름을 따라가니 폼을 선택하고 Caption을 변경해주시기 바랍니다.

그리고 이부분은 선택사항입니다. 코드를 붙여넣기 헀을때 에러가 나는 부분에 대해 참고를 위해 추가하였습니다.

 

MFC는 문자열 처리 방식이 멀티바이트코드와 유니코드 두가지 방식이 있는데 마블랑은 멀티바이트 코드를 사용하므로 프로젝트 속성창에서 문자집합을 멀티바이트로 수정하여 주었습니다.

이제 코드를 추가하겠습니다.

 

"전송" 버튼을 클릭했을때 내부메시지가 송신되는 부분입니다. 

 

CWnd::FindWindow 함수를 통해 프로세스가 있는지 확인한 다음 프로세스가 있으면 텍스트박스의 내용을 윈도우 메시지로 전송합니다. 

 

구조체 COPYDATASTRUCT 에 대해 설명을 하겠습니다.


cpd.dwData : 메시지 코드 
cpd.cbData : 메시지의 길이 
cpd.lpData : 메시지 내용

 

메시지 코드나 메시지 길이를 활용해서 데이터가 많은 경우 구분을 할수 있습니다. 

void CMFCCopyDataTestDlg::OnBnClickedBtSend()
{
	CString strRecvProcess = _T("");
	CString strMsg = _T("");

	GetDlgItem(IDC_TB_RECV)->GetWindowTextA(strRecvProcess);
	GetDlgItem(IDC_TB_MSG)->GetWindowTextA(strMsg);

	CWnd* cWnd = CWnd::FindWindow(NULL, strRecvProcess);

	if (cWnd)
	{
		COPYDATASTRUCT cpd;
		cpd.dwData = 0x9999;
		cpd.cbData = strMsg.GetLength();
		cpd.lpData = (void*)strMsg.GetBuffer(cpd.cbData);

		cWnd->SendMessage(WM_COPYDATA, (WPARAM)AfxGetApp()->m_pMainWnd->GetSafeHwnd(), (LPARAM)& cpd);
	}
	else {
		AfxMessageBox("수신프로세스가 없습니다.");
	}
}

 

다음은 수신부의 코드입니다. 

 

위에서 추가했던 WM_COPYDATA 부분에 내용을 추가하면 됩니다.

 

현재는 메시지 코드가 0x9999 만 있어 Switch 문의 case가 하나 밖에 없군요.

BOOL CMFCCopyDataTestDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
	switch (pCopyDataStruct->dwData) {
	case 0x9999:
	{
		CString strRecvMsg = (LPCSTR)(pCopyDataStruct->lpData);

		AfxMessageBox(strRecvMsg);
	}
	break;
	}
	return CDialogEx::OnCopyData(pWnd, pCopyDataStruct);
}

 

모든 구현이 끝났다면 빌드를 해주세요

 

 

 

여기까지 완성이 되었다면 또다른 주고 받는 역활을 하기위해 또다른 프로젝트를 생성해 줍니다.

 

위에 구현했던 프로젝트와 똑같이 진행해주시면 되는데 프로세스 제목만 변경해주시기 바랍니다.

코드도 동일하게 해주시기 바랍니다.

 

그리고 두번째 프로젝트도 빌드를 해주시기 바랍니다.

 

 

빌드가 완료 되었다면 두개의 프로세스를 실행하여 테스트를 진행해 보겠습니다.

 

정상적으로 동작하는 것을 확인하였습니다.

 

안되시는 분들은 수신프로세스의 명을 다시 확인해 주시기 바랍니다.^^

 

 

이상 마블랑이었습니다. 

 

읽어주셔서 고맙습니다.

댓글