First attempts and ideas
If you read the MSDN help about WM_COYDATA
you can see that it is possible to use it in order to communicate between 16-bit and 32-bit apps, but not how. My Problem was the following: I had to include a 16-bit-dll into a 32-bit-Application, as there is no newer version of the dll available. If you really want to solve this problem, you have to either build a real thunk using the thunk compiler (see other articles for details) or cheat a little using the function QT_Thunk()
which has been described on the web several times. Both ideas are rather complicated since you have to write at least a few lines of assembly code. I didn't dare to do this, because I thought it would be too complicated.
My next approach to the problem was to build up a DDE-Client-Server-Architecture. But also this possibility seemed to be too great an effort. When I first saw the documentation of WM_COPYDATA
I thought it couldn't work between 16-bit and 32-Bit apps and first tried another thing: I let two apps communicate via Windows Messages and sent pointers pointing to data arrays via this channel. This lead to the problem of the translation between flat 32-bit Pointers and generic far 16-bit-Pointers. I advise you to never try a thing like that, it's really awful!
How it works
At last I tried just to use WM_COPYDATA
, even though I thought there were still two problems to solve, which I saw no solution for: The first one is the same problem I encountered trying to use my own Windows Messages. I thought it would be necessary to translate the pointers. But to my surprise this seems to be done automatically. The second problem I expected was the following: I thought it would not be possible to get access to a pointer outside the adress space of an application by directly dereferecing it. Normally this leads to Windows exceptions, but it does not in the case of using WM_COPYDATA
. The pointer you send by this message is allowed to be dereferenced by some magic way.
So what do you have to do? I can only answer this question for my special case. I used Visual C++ 6.0 for the 32-bit-app and Visual C++ 1.52 for the 16-bit-App on Windows 2000. As my solution works for running the 16-bit-app in both a shared and a seperate virtual dos machine, I guess that it also works on Windows 98 / ME, but I have not tested that. In order to have the two apps communicate I have them get handles to each other using the API-Function FindWindow(NULL,"name")
. When they have handles, they can send messages to each other using the API-Function (NOT the CWnd
-member) SendMessage()
. In order to avoid timing problems you should never use PostMessage()
instead of SendMessage()
. It's a good idea to choose a small set of common messages for the two apps and have them register by the API-Function RegisterWindowMessage()
. I only built up a data transfer from 16-bit to 32-bit but not vice versa. For that pupose I had to include the following piece of code in my 16-bit-app, as WM_COPYDATA
and COPYDATASTRUCT
are not defined in the headers of the old 16-bit-API:
#define WM_COPYDATA 0x004A
typedef struct tagCOPYDATASTRUCT {
DWORD dwData;
DWORD cbData;
LPVOID lpData;
} COPYDATASTRUCT, *PCOPYDATASTRUCT;
In order to transfer data I just had to create an instance of the COPYDATASTRUCT
(let's call it cpstruct
), assign values to its members and then send the message WM_COPYDATA
like
::SendMessage(handle, WM_COPYDATA, 0, (LPARAM) (LPVOID) &cpstruct);
The receiving 32-bit-app needn't do any pointer translation and can directly get access to the data by dereferencing the pointer in the MessageHandler
. The MessageHandler
for WM_COPYDATA
in the 32-bit-app looks like:
BOOL CCCDClient::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
memcpy(m_pReceiveData, pCopyDataStruct->lpData,
pCopyDataStruct->cbData);
return CFrameWnd::OnCopyData(pWnd, pCopyDataStruct);
}
It is necessary to copy the data (e.g. using memcpy()
as shown here) within the MessageHandler
. I first tried to store the pointer and copy the data in a different function, but this doesn't work. So as you can see it's quite easy to communicate and exchange data between 16-bit and 32-bit-apps.