본문 바로가기
MFC

[MFC] C# Windows Forms 컨트롤 라이브러리와 SendMessage 주고 받기 (C++ ↔ C#)

by Jcoder 2021. 3. 15.

 

작성 했던 방법과 동일한 방식으로 프로젝트 생성 및 빌드

 

[MFC] Dialog에서 C# Winform 불러오기 및 Chromium 사용, Dynamic Control Resize (tistory.com)

 

[MFC] Dialog에서 C# Winform 불러오기 및 Chromium 사용, Dynamic Control Resize

* Visual Studio 2019 16.9 * .NET Framework 4.8 * Nuget Package : CefSharp 제목에 있는 내용들이 섞여 있기에 차근차근 봐주시길 바랍니다. 1. C# Windows Forms 컨트롤 라이브러리 프로젝트 생성 2. .NET Fr..

jcoder1.tistory.com

 

1. C# Windows Forms 컨르롤 라이브러리

UserControl1
UserControl1 소스1
UserControl1 소스2

 

    public partial class UserControl1 : UserControl
    {
        const int WM_COPYDATA = 0x4A; // WM_COPYDATA 값 설정

        private string testMessage; // 변경할 값

        public string TestMessage // 값이 변하면 이벤트 발생할 프로퍼티
        {
            get { return testMessage; }
            set
            {
                testMessage = value;
                ChangeText();
            }
        }

        private void ChangeText() // 값이 변하면 발생할 함수 
        {
            MessageBox.Show(TestMessage);
        }

        // SendMessage 설정
        [System.Runtime.InteropServices.DllImport("user32.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
        public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, uint wParam, ref COPYDATASTRUCT lParam);

        // COPYDATASTRUCT 구조체 선언
        public struct COPYDATASTRUCT
        {
            public IntPtr dwData;
            public int cbData; // string 크기
            [System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPStr)]
            public string lpData; // 문자열
        }

        public UserControl1()
        {
            InitializeComponent();
            button1.Click += bnt_SendMessageEvent;
        }

        private void bnt_SendMessageEvent(object sender, EventArgs e)
        {
            string msg = textBox1.Text.Trim();

            if (string.IsNullOrEmpty(msg))
            {
                MessageBox.Show("메세지를 입력해주세요");
                return;
            }

            // MFC 프로젝트 명 찾기, FindWindow 사용시 caption 사용 가능
            System.Diagnostics.Process[] pro = System.Diagnostics.Process.GetProcessesByName("MFCApplication_SendMessage");

            if (pro.Length > 0)
            {
                byte[] buff = System.Text.Encoding.Default.GetBytes(msg);

                COPYDATASTRUCT cds = new COPYDATASTRUCT();
                cds.dwData = IntPtr.Zero;
                cds.cbData = buff.Length + 1;
                cds.lpData = msg;
                // 전달
                SendMessage(pro[0].MainWindowHandle, WM_COPYDATA, 0, ref cds);
            }
        }

        protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            if (m.Msg == WM_COPYDATA && m.WParam == this.Handle)
            {

                COPYDATASTRUCT cds = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));

                textBox1.Text = cds.lpData; //받을 데이터를 설정.
            }

            base.WndProc(ref m);
        } //WndProc
    }

 

2. MFC 프로젝트

 

클래스 마법사로 메시지 - WM_COPYDATA 생성

폼 클래스 마법사

에디트 컨트롤 변수 선언

MFC 코드

BOOL CMFCApplicationSendMessageDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
	// TODO: 여기에 메시지 처리기 코드를 추가 및/또는 기본값을 호출합니다.
	switch (pCopyDataStruct->dwData)
	{
	case 0 : // UserControl1에 있는 버튼 sendmessage 시 받을 문자열과 동작
	{
		CString strRecvMsg = (LPCSTR)(pCopyDataStruct->lpData);
		CString strTemp;
		strTemp.Format("%s\r\n", strRecvMsg);
		m_sEdit_Result.SetSel(-2, -1);   // 커서를 에디트박스 끝으로 이동     ( SetSel(-1,-1)은 선택영역해제....)
		m_sEdit_Result.ReplaceSel(strTemp);  //문자열 추가.
		UpdateData(FALSE);
		break;
	}
	case 1: // 
	{
		m_SendForm1.GetControl()->TestMessage = "test"; // UserControl에 선언한 프로퍼티 값 변경.
		//m_SendForm1.GetControl()->textBox1->Text = "test";
		break;
	}
	default:
		break;
	}
	
	return CDialogEx::OnCopyData(pWnd, pCopyDataStruct);
}


void CMFCApplicationSendMessageDlg::OnBnClickedButton1() // UserControl1에 보낼 sendmessage
{
	//CWnd* pChildHandle = GetDlgItem(IDC_STATIC_FORM)->GetSafeHwnd();
	//HWND test = pChildHandle->GetSafeHwnd();

	CString strMsg = "test";

	COPYDATASTRUCT cpd;
	cpd.dwData = 0x1;
	cpd.cbData = strMsg.GetLength();
	cpd.lpData = (void*)strMsg.GetBuffer(cpd.cbData);

	this->SendMessage(WM_COPYDATA, (WPARAM)GetDlgItem(IDC_STATIC_FORM)->GetSafeHwnd(), (LPARAM)&cpd);
	//this->SendDlgItemMessage(WM_COPYDATA, (WPARAM)GetDlgItem(IDC_STATIC_FORM)->GetSafeHwnd(), (LPARAM)&cpd);
//	m_SendForm1->
}

 

3. 결과

C# -> C++
C++ -> C#

 

4. 참고

C# SendMessage string 전달 (tistory.com)

 

C# SendMessage string 전달

서로 다른 프로그램으로 데이터를 전달하기 위해선 아래와 같이 하면 된다. 1. WM_COPYDATA 와 COPYDATASTRUCT 를 이용할 수 있도록 선언한다. using System.Runtime.InteropServices; ... ... public const Int32..

fallingstar.tistory.com

Develop++ :: SendMessage C++ to C# using WM_COPYDATA (tistory.com)

 

SendMessage C++ to C# using WM_COPYDATA

1. C++ (Sender)  typedef struct tagCOPYDATASTRUCT {      ULONG_PTR dwData;      DWORD    cbData;      CHAR*    lpData; } COPYDATASTRUCT; char strChar[] = "20150601130012.xml";..

yh0515.tistory.com

[MFC] Copydata IPC 구현하기 (tistory.com)

 

[MFC] Copydata IPC 구현하기

안녕하세요 마블랑입니다. 윈도우 프로세스들을 구현하다보면 프로세스간의 내부통신을 해야할때가 있습니다. 이러한 내부통신은 공유메모리를 이용하여 구현할수 있지만 그것보다 더 간단한

sosobaba.tistory.com

igotit :: WM_COPYDATA. (tistory.com)

 

WM_COPYDATA.

개요 2개의 프로세스 사이에 SendMessage 함수로 메시지 송/수신과 동시에 구조체자료형 COPYDATASTRUCT 를 전송가능한 것. 즉 메시지 송신측에서 SendMessage 함수인자를 아래처럼 호출하면 HWND 에 해당

igotit.tistory.com