반응형

C# App(Winform이나 WPF App)에서 C++ MFC App으로 구조체 데이타를 전달하기 위해서는 각자 동일한 구조체를 정의해주고 마샬링시에 사이즈가 맞도록 C# 구조체에 MarshalAs를 정의해준다. 

그리고 마샬링한 구조체 데이타를 COPYDATASTRUCT 에 저장후 WM_COPYDATA 메세지로 SendMessage를 하면 MFC에서 동일하게 정의한 구조체에 값이 작 적용된것을 확인할 수 있다.

 

WPF에서 SendMessage로 구조체 데이타 전달

using System;
using System.Runtime.InteropServices;
using System.Windows;

namespace WpfApp4
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public struct SomeData
        {
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
            public string UserName;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
            public string Password;

            public bool IsAdmin;

            public int No;

            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
            public float[] Datas;

            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
            public string Memo;
        };

        [StructLayout(LayoutKind.Sequential)]
        public struct COPYDATASTRUCT
        {
            public IntPtr dwData;
            public int cbData;
            public IntPtr lpData;
        }

        private const int WM_COPYDATA = 0x4A;
        private const int WM_USER = 0x0400;
        private const int WM_TEST_MESSAGE = WM_USER + 500;

        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        public static extern int SendMessage(IntPtr hWnd, Int32 Msg, IntPtr wParam, ref COPYDATASTRUCT lParam);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr FindWindow(string strClassName, string strWindowName);

        public MainWindow()
        {
            InitializeComponent();
        }

        private void btnTest_Click(object sender, RoutedEventArgs e)
        {
            IntPtr targetWindowHandle = FindWindow(null, "MFC Window");

            SomeData data = new SomeData()
            {
                UserName = "Test",
                Password = "1234abcd",
                IsAdmin = true,
                No = 56,
                Datas = new float[10] { 2f, 1f, 1.5f, 1.2f, 35.0f, 1.2f, 1.2f, 1.2f, 1.2f, 1.2f },
                Memo = "aaaaaaa bbbbbbbbbb cccccccccc ddddddd eeeeeeeee ffffffff",
            };

            IntPtr pData = Marshal.AllocHGlobal(Marshal.SizeOf(data));
            Marshal.StructureToPtr(data, pData, false);

            COPYDATASTRUCT cds2 = new COPYDATASTRUCT();
            cds2.dwData = IntPtr.Zero;
            cds2.cbData = Marshal.SizeOf(data);
            cds2.lpData = pData;

            int result = SendMessage(targetWindowHandle, WM_COPYDATA, new IntPtr((int)WM_TEST_MESSAGE), ref cds2);
        }
    }
}

 

MFC App에서 전달받은 구조체를 변환저장후 데이타 확인

#define WM_TEST_MESSAGE WM_USER + 500
 
struct SomeData
{
	TCHAR UserName[128];
	TCHAR Password[128];
	bool IsAdmin;
	int No;
	float Datas[10];
	TCHAR Memo[128];
};
 
LRESULT CMFCApplication1Dlg::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
	if (message == WM_COPYDATA)
	{
		int subMessage = (int)wParam;
 
		if (subMessage == WM_TEST_MESSAGE)
		{
			COPYDATASTRUCT* pCopyDataStruct = (COPYDATASTRUCT*)lParam;
 
			SomeData data;
			data = *((SomeData*)pCopyDataStruct->lpData);
 
			CString message;
			message.Format(_T("%s , %s , %d ,%d,  %1f, %s"),
				data.UserName,
				data.Password,
				data.IsAdmin,
				data.No,
				data.Datas[3],
				data.Memo);
 
			AfxMessageBox(message);
		}
	}
	return CDialogEx::WindowProc(message, wParam, lParam);
}

 

테스트 결과 화면

반응형

+ Recent posts