This article describes a kind of interprocess communication between a .Net-application and a native c++-application on WindowsCe/WindowsMobile-based devices.
The reason for this project was my current task, a set of native DLLs for an external hardware which should connected to the mobile device. The data structure from the DLLs is very complex and very hard to implement in a .NetCF-application, so I decided to build a native c++-application for the communication between the DLLs and .NetCF-application.
The communication between the DLLs and the c++-application was very easy, cause I got a good manual, how I could use the DLLs. It was much harder to find a way to communicate from the C++-application with the .NetCF-application.
The way, which I found, was to communicate via Windows Messages. If you want to transfer data between application with Windows Messages, you have to use the SendMessage()-function together with the WM_COPYDATA-message. Additionally, you have to use the COPYDATASTRUCT-struct from the Windows API.
In this article, I will explain it with a simple data struct, called ‘ownData’. Here is the definition of ‘ownData’ in C++.
|struct ownData |
The basic structure of the communication between both applications looks like that. Both apps have a receiver- and a sender function which handles all necessary steps.
On the C++ – side its quite simple. Everything you need is nearly build-in. You just have to include some header files and everything is OK.
For a short example, it is enough to include the “windows.h”-header file.
So, I create in Visual Studio a new C++-project for embedded devices as plain Win32-C++-project. The main.cpp-file looks like that…
|#include <windows.h> |
int WINAPI WinMain(HINSTANCE h, HINSTANCE, LPTSTR arg, int nCmdShow)
// define a new handle for the wndclass
HWND hMain = 0;
// create and define a new wndclass
// this function handles all Windows Messages
wc.lpfnWndProc = MainWndProc;
wc.hInstance = h;
wc.hbrBackground = (HBRUSH)(COLORWINDOW+1);
wc.lpszClassName = L”SENDER”;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
// register new wndclass wc
// create a new window from wc
hMain = CreateWindow(L”SENDER”, L”Sender”, WS_VISIBLE, 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, h, NULL);
// hide hMain
// creating a Message var
// joining the message pump
while (GetMessage(&msg, NULL, 0, 0))
// setting the return value for WinMain
In the MainWndProc-function, I will filter all Windows-Messages. My special interest is on the WM_COPYDATA-messages. They contains the sent data from the other application. Here is my function…
|LRESULT CALLBACK MainWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) |
// checking msg
// parse the lParam-parameter in a PCOPYDATASTRUCT
PCOPYDATASTRUCT pcds = (PCOPYDATASTRUCT)lParam;
// parse pcds->lpData in your own data structure
ownData* od = (ownData)(LPSTR)pcds->lpData;
// do whatever you want
// with your ownData od
//at last, your should run the DefWindowProc and setting the return value
return DefWindowProc(hwnd, msg, wParam, lParam);
So, now we have all functionality to get answers from another application. Now we need the functionality to send data to another application. I have create an own function for that. In this function, I used the FindWindow()-function from the Windows API. They normally need two parameters, a classname and a windowname. In this case, I want to find/contact a .NetCF-application.
‘Normal’ .NetCF-applications have ‘#NETCF_AGL_BASE_’ as classname and the windowtext as windowname.
In the case, I used a new class which inherits the WindowMessage-class from the ‘Microsoft.WindowsCE.Forms”-namespace. More to that aspect will follow later in this article. When I use the WindowMessage-class, you got a new entry in the the handle-list from WindowsCe or WindowsMobile. The new handle has a classname equal “#NETCF_AGL_MSG_” but no windowname. You can set the windowname manually by the classes property.
At next, I implemented a send function in my C++ application, which has a ownData-parameter. The function creates a new COPYDATASTRUCT which my own data, looks for the receiver window and sends the COPYDATASTRUCT to the window if its exists.
|static void Send(ownData data) |
// create a new COPYDATASTRUCT
// putting the data from ‘data’ in ‘cds’
cds.dwData = (WPARAM)0;
cds.cbData = sizeof(ownData);
cds.lpData = &data;
// creating a new HWND from a running application
HWND hReceiver = ::FindWindow(_T(“#NETCF_AGL_MSG_”), NULL);
// checking hReceiver
if (hReceiver != NULL)
// sending the cds
SendMessage(hReceiver, WM_COPYDATA, (WPARAM)0, (LPARAM)&cds);
.Net Compact Framework (C#)
On the receiver side, I had a managed .Net Compact Framework application which is written in C#.
At first, we need some things from the Windows API. We don’t have here in C# a build-in struct like COPADATASTRUCT, so we need to create it. It is nearly the same as in C++.
|public struct COPYDATASTRUCT |
public System.Int32 dwData;
public System.Int32 cbData;
public System.IntPtr lpData;
At next we need the FindWindow()-function from the Windows API. Here is the declaration that we can use it in C#.
Both things, COPYDATASTRUCT and FindWindow() are necessary in the application.
Here is the declaration of the ownData struct in C#. Here, it is very important that the byte-array will be declared manually with a defined size of 500 entries like in C++. If this will not be done, you will have a lot of trouble during runtime.
|public struct ownData |
public System.Int32 ID;
[System.Runtime.InteropServices. MarshalAs(System.Runtime.InteropServices. UnmanagedType.ByvalArray, SizeConst = 500)]
public byte data;
As I said above in this article, I created a new class which inherits the WindowMessage-class from the Microsoft.WindowsCE.Forms-namespace. In this new class, I’ve the WndProc-function overwritten. With my own function, I’m able to check and handle all incoming Windows Messages.
|protected override void WndProc(ref Microsoft.WindowsCE.Forms.Message m) |
// check m.Msg
case 0x4A: // 0x4A = WM_COPYDATA
// extract the own data from the Windows Message m
ownData data = this.ExtractDataFromMessage(m);
// do whatever you want with your data
// run base.WndProc
In the overwriten WndProc function I call a function named ExtractDataFromMessage(). This function extract the sended data from the Windows Message into my own data struct. These function works with pointers, so I had to declare her as unsafe. I also had to enable the unsafe flag in the project properties.
|unsafe private ownData ExtractDataFromMessage(Microsoft.WindowsCE.Forms.Message msg) |
// delcare all vars with are needed
ownData data = new ownData();
// create cds and extract the COPYDATASTRUCT data from the Windows Message
cds = (COPYDATASTRUCT)System.Runtime.InteropServices. Marshal.PtrToStructure(msg.LParam, typeof(COPYDATASTRUCT));
// get the targetPointer
targetPointer = &cds.lpData;
// get the data from the COPYDATASTRUCT
data = (ownData)System.Runtime.InteropServices. Marshal.PtrToStructure(cds.lpDAta, typeof(ownData));
// return the data
In the C#-application, I also have a Send-function, which encapsulate some functions. The send-functions has a ownData-parameter. In this function, I retrieve the addresspointer of ‘data’, create a new instance of COPYDATASTRUCT in my C#-application, retrieve the addresspointer of it and create a new Windows Message and send with Microsoft.WindowsCE. Forms.MessageWindow.SendMessage().
|private void Send(ownData data) |
Microsoft.WindowsCE.Forms.Message msg = new Microsoft.WindowsCE.Message();
COPYDATASTRUCT cds = new COPYDATASTRUCT;
// create a new pointer for ‘data’
System.IntPtr pData = System.Runtime.InteropServices. Marshal.AllocHGlobal(System.Runtime.InteropServices. Marshal.SizeOf(data));
System.Runtime.InteropServices.Marshal.StructureToPtr (data, pData, false);
// setting cds
cds.dwData = 0;
cds.cbData = System.Runtime.InteropServices.Marshal. SizeOf(data);
cds.lpDAta = pData;
// create a pointer for ‘cds’
System.IntPtr pCds = System.Runtime.InteropServices.Marshal.AllocHGlobal (System.Runtime.InteropServices.Marshal.SizeOf(cds));
System.Runtime.InteropServices.Marshal.StrucutreToPtr (cds, pCds, false);
// getting the server-application
System.IntPtr server = FindWindow(“SENDER”, “Sender”);
// checking server
if(server != null)
// setting ‘msg’
msg.HWnd = server;
msg.Msg = 0x4a; // 0x4a = WM_COPYDATA
msg.WParam = (System.IntPtr)0;
msg.LParam = pCds;
// sending msg
Microsoft.WindowsCE.Forms.MessageWindow.SendMessage (ref msg);
// clearing the allocated memory
SendMessage(), PostMessage(), SendNotifyMessage(), etc…
The Windows API contains a lot of functions to send Windows Message from on application to another. MSDN says that you have to use the SendMessage()-function. Correct! Why? For sure, you can use PostMessage() or SendNotifyMessage() as well, your receiver-application gets the Windows Message, but the encapsulated data pointers are corrupted and all your data is lost.
Transferring data with Windows Messages is a nice method to transfer data fast from an application to an other application. You can compute the data immediately in the receiver application. It also could be a way for a .Net developer to use external hardware on mobile devices, when the drivers are very difficult to use in .Net.