使用 WM_COPYDATA 而不是 thunk 在 32 位应用程序和 16 位应用程序之间构建客户端-服务器架构





4.00/5 (8投票s)
2003 年 3 月 14 日
3分钟阅读

58567
本文介绍了如何在使用 Windows 消息 WM_COPYDATA 在 32 位应用和 16 位应用之间进行通信。这非常简单,但据我所知,到目前为止还没有对此问题进行详细描述。
初步尝试和想法
如果您阅读有关 WM_COYDATA
的 MSDN 帮助,您会看到可以使用它在 16 位和 32 位应用之间进行通信,但没有说明如何操作。 我的问题如下:我必须将一个 16 位的 dll 包含到 32 位的应用程序中,因为没有更新版本的 dll 可用。如果您真的想解决这个问题,您必须使用 thunk 编译器构建一个真正的 thunk(有关详细信息,请参见其他文章),或者使用 Web 上多次描述过的函数 QT_Thunk()
稍微作弊。 这两种想法都相当复杂,因为您至少需要编写几行汇编代码。 我不敢这样做,因为我认为这太复杂了。
我对这个问题的下一个方法是构建一个 DDE 客户端-服务器架构。 但是这种可能性似乎也需要付出太大的努力。 当我第一次看到 WM_COPYDATA
的文档时,我认为它无法在 16 位和 32 位应用之间工作,因此首先尝试了另一件事:我让两个应用程序通过 Windows 消息进行通信,并通过该通道发送指向数据数组的指针。 这导致了 32 位平面指针和 16 位通用远指针之间的转换问题。 我建议您永远不要尝试这样的事情,这真的很糟糕!
工作原理
最后,我尝试直接使用 WM_COPYDATA
,即使我仍然认为有两个问题需要解决,但我没有找到解决方案:第一个问题与我尝试使用自己的 Windows 消息时遇到的问题相同。 我认为有必要翻译指针。 但是令我惊讶的是,这似乎是自动完成的。 我期望的第二个问题是:我认为无法通过直接取消引用来访问应用程序地址空间之外的指针。 通常,这会导致 Windows 异常,但在使用 WM_COPYDATA
的情况下不会发生这种情况。 通过此消息发送的指针可以通过某种神奇的方式被取消引用。
那么你需要做什么?我只能回答我特殊情况下的这个问题。我在 Windows 2000 上将 Visual C++ 6.0 用于 32 位应用,将 Visual C++ 1.52 用于 16 位应用。由于我的解决方案可以在共享和单独的虚拟 dos 机器中运行 16 位应用,因此我猜它也可以在 Windows 98 / ME 上运行,但我没有对此进行测试。为了使两个应用程序进行通信,我使用 API 函数 FindWindow(NULL,"name")
让他们获取彼此的句柄。当他们有句柄时,他们可以使用 API 函数(不是 CWnd
成员) SendMessage()
相互发送消息。为了避免时间问题,您不应使用 PostMessage()
代替 SendMessage()
。为两个应用程序选择一小组通用消息并通过 API 函数 RegisterWindowMessage()
注册它们是个好主意。我只建立了从 16 位到 32 位的数据传输,反之则不然。为此,我必须在我的 16 位应用程序中包含以下代码段,因为 WM_COPYDATA
和 COPYDATASTRUCT
未在旧的 16 位 API 的标头中定义
// taken from 32-bit-file winuser.h and modified slightly ///////////为了传输数据,我只需要创建
/////////////////////////////////////////////////////////////////////
#define WM_COPYDATA 0x004A
typedef struct tagCOPYDATASTRUCT {
DWORD dwData; //an obsolete parameter for additional information
DWORD cbData; //number of bytes to be transferred
LPVOID lpData; //pointer to the data array to be transferred
} COPYDATASTRUCT, *PCOPYDATASTRUCT;
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
COPYDATASTRUCT
的实例(我们称之为 cpstruct
),为其成员分配值,然后像这样发送消息 WM_COPYDATA
::SendMessage(handle, WM_COPYDATA, 0, (LPARAM) (LPVOID) &cpstruct);
接收 32 位应用程序不需要进行任何指针转换,并且可以通过取消引用 MessageHandler
中的指针直接访问数据。 32 位应用程序中 WM_COPYDATA
的 MessageHandler
看起来像BOOL CCCDClient::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
memcpy(m_pReceiveData, pCopyDataStruct->lpData,
pCopyDataStruct->cbData);
return CFrameWnd::OnCopyData(pWnd, pCopyDataStruct);
}
必须在
MessageHandler
中复制数据(例如,使用此处显示的 memcpy()
)。我首先尝试存储指针并在不同的函数中复制数据,但这不起作用。因此,如您所见,在 16 位和 32 位应用程序之间进行通信和交换数据非常容易。