【问题标题】:WinAPI, Posting/Sending Messages with 64 bit values (wParam, lParam)WinAPI,使用 64 位值(wParam、lParam)发布/发送消息
【发布时间】:2016-04-11 22:18:54
【问题描述】:

我编写了一个使用 MFC 的程序,因此使用了诸如 PostMessage 之类的 WinAPI 函数。它主要只是一个窗口线程和一个网络客户端线程。 我创建了自己的消息,到目前为止它运行良好。 稍微解释一下程序:
我编写了一个客户端,它通过网络获取消息,对其进行解码,然后需要将消息发送到显示消息值的窗口。所有这些都有效 - 使用 32 位值。这肯定是某种不正确地使用 PostMessage 函数,因为 lParam 和 wParam 通常是指针。但是我不能只使用指针,因为我的客户端应用程序和我的窗口应用程序是两个不同的线程,并且客户端应用程序中的值会尽快被删除。 (客户端需要从服务端调用循环请求)

#define DEVICE_INFO_DATETIME 70000
long long date;
date = (value->serverTimestamp);
PostMessage(getWindowHandle(), WM_NEW_DATA, date, DEVICE_INFO_DATETIME);

问题是我得到了时间戳和其他编码为 64 位的数据。 wparam 和 lparam 只是 32 位,所以它总是截断我的值。好的,我可以用 64 位编译它,然后使用 64 位值,但这与 32 位系统不兼容(对吗?),而不是我想要的。这种代码的一种解决方法是设置一个临时的 64 位值或一个 64 位值的数组作为全局变量,但我不想将它们全部保存在与内存有关的单独值中。仅传递值将是这里的最佳解决方案。

你猜到我能在这里做什么吗?

【问题讨论】:

  • 您只需要传递指针的所有权。工作线程分配,UI线程可以清理。不要忘记检查 PostMessage 的返回值。
  • 如何传递所有权?你的意思是我可以在我的工作线程中分配一个 64 位变量(例如使用 malloc),通过 PostMessage 将指针传递给我的 UI,然后在使用值 free() 之后指针?我知道 C++ 中有类似 SmartPointers 之类的东西,但我正在为我的工作人员使用裸 C 环境。

标签: c windows mfc


【解决方案1】:

使用DEVICE_INFO_DATETIME作为WPARAM,传递数据地址为LPARAM。使用SendMessage 会更安全,因为它传递对堆栈数据的引用。

long long date = 123;
SendMessage(getWindowHandle(), WM_NEW_DATA, DEVICE_INFO_DATETIME, (LPARAM)&date);

此外,如果WM_NEW_DATA 定义正确,则DEVICE_INFO_DATETIME 不必是像70000 这样的大随机数。例如

#define WM_NEW_DATA WM_APP + 1
#define DEVICE_INFO_DATETIME 1


您也可以将long long 值作为两个整数传递,这将适用于PostMessage

#define WM_NEW_DATA2 WM_APP + 2

long long date = ...
int hi = date >> 32;
int lo = (int)date;
PostMessage(hwnd, WM_NEW_DATA2, (WPARAM)hi, (LPARAM)lo);

接收:

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    if (msg == WM_NEW_DATA2)
    {
        long long date = ((long long)wParam << 32) + lParam;
    }
}



使用指针和PostMessage:调用函数分配数据,接收函数删除数据(也可以使用mallocfree
//call:
long long *date = new long long;
PostMessage(hwnd, WM_APP + 3, DEVICE_INFO_DATETIME, (LPARAM)date);

//receive:
if (msg == WM_APP + 3)
{
    long long *date = (long long*)lParam;
    if (!date) return 0; //insufficient error check!
    delete date;//delete pointer when finished
}

但是这很容易出错。例如,如果调用者不小心发送了PostMessage(hwnd, WM_APP + 3, DEVICE_INFO_DATETIME, 1);,程序就会崩溃。接收者无法知道lParam 是好是坏(据我所知)

【讨论】:

  • 好的,谢谢!解决了这个问题。我有两个问题。首先使用 wParam,它是一个 UInt,它以某种方式将指针变成一个随机数,然后使用 PostMessage 导致当指针指向的内存为空时处理消息。 SendMessage 现在可以正常工作并完成其工作。这正是我想要的。
  • 我不确定投反对票的原因。将内存分配用于日期标记似乎有点过头了。我添加了另一种使用 PostMessage 传递 64 位整数的方法
  • 是的,我也想知道反对票。第二个版本也是我的想法,但我也需要发送定义。只是好奇:在这个例子中 date 是一个局部变量。使用 SendMessage 会导致 WinAPI 立即处理此消息,并且只有在此返回到 SendMessage 调用者之后,并且只有在处理调用函数之后,才会销毁日期。 PostMessage 导致随时处理消息并立即返回到调用函数,因此调用函数可能会完成并且日期丢失。我做对了吗?
  • SendMessage 类似于调用常规函数。它一直等到另一个函数完成。而PostMessage 立即返回并且不等待其他函数。另一个函数可能会在调用函数完成后尝试使用date,而date 超出范围并被销毁。 SendMessage 有它自己的缺点,在这里它可能会导致程序挂起(即使它是多线程的)。我为PostMessage 和指针添加了另一种方法。但是SendMessage 足够好,只要不引起问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-05-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-18
  • 2014-07-21
相关资源
最近更新 更多