【问题标题】:Casting pointers to/from LRESULT将指针投射到/来自 LRESULT
【发布时间】:2013-04-21 07:53:02
【问题描述】:

我正在寻找有关此 Windows 编程习惯的确认,我认为许多不同类型的“句柄”不仅作为 LRESULT 对象而且还作为 lParam 和 wParam 对象传递,这是否正确?

我猜只要我们知道 LRESULT 或 lParam/wParam 中的句柄类型是“什么”,我们就可以重新转换为它。

例如

case WM_CREATE:
   ...
   //create a window
   //lParam is the CREATESTRUCT for new window created here
   ....
   return lParam;
...
...
CREATESTRUCT cStruct = (CREATESTRUCT)SendMessage(hwnd, msg /*WM_CREATE*/);
cStrcut.cx;//this is the width of the new window?

正确吗?

这是“正确的”吗?谁能为我和 StaticOverflow 社区提供一份关于这种技术/习语的简短论文?

问题: 我们应该只返回 lParam(或只返回 wParam)值吗? 有没有应该知道的陷阱? LRESULT 和 LPARAM 都是 LONG_PTR 类型,它们是 32 位或 64 位整数。我不是一个经验丰富的 C 程序员,但看起来这些整数只是被用作“缓冲区”,程序员后来在使用之前将其转换为“真实”类型......听起来准确吗?

【问题讨论】:

  • 对于初学者来说,进入假设是错误的。 WM_CREATE 接收一个 LPCREATESTRUCT 转换为 WndProc 的 LPARAM 参数;它不会返回 CREATESTRUCT 形式的SendMessage,这将我们带到第二个无效假设:您从不发送 WM_CREATE,窗口管理器会这样做。你处理它。编程风格本质上是通过文档进行改进的抽象。 LPARAM 之类的东西在各种不同的窗口消息中扮演了许多 角色,包括您可以定义的自定义消息,但您无法通过阅读代码“了解”它们。您需要文档。
  • 我放弃了。没有代码块,我无法回复,也没有任何效果。 [code][/code] 也不是 也不是 'code' '/code' 所以我不能准确。但是 SendMessage 将 WindowProcedure 放在堆栈上并返回 WindowProc 作为 LRESULT 执行的操作。
  • 另外,您也可以使用 SendMessage 来触发 WM_CREATE 消息或任何其他消息。你可能“不应该”,但你可以。此外,WM_CREATE 可以很好地返回一个 CREATESRUCT 到 SendMessage (它将返回给你),你是正确的,你必须捕获消息并处理它们,但是你可以让它们返回你想要的,只要编译器可以强制转换为 LRESULT。可能没有人会以这种方式使用 WM_CREATE,这可能就是您怀疑它的正确性的原因。我只为这个例子选择了它,因为它是每个 Windows 程序员都熟悉的消息。
  • 当然,您也受到文档的约束。 API 的某些部分“期望”来自某些消息的某些返回值。很好地返回 WM_CREATE 消息的 LPARAM 可能会破坏可能期望 WM_CREATE 返回其他内容的 API 部分,这将导致段错误。我不知道,但将来我会避免使用糟糕的代码来传达有效的想法。
  • @TraeBarlow:read the documentation,它解释了如何在 cmets 中格式化代码。

标签: winapi casting lparam


【解决方案1】:

这种编程风格是“糟糕的”,因为在编译时无法知道真正是什么。也就是说,由于 WIN32 API 是一个 C API(而不是说,C++),当一个人想要使用相同的方法签名传递 any 类型的结构时,没有什么可以做的。

因此,API 设计团队决定使用两个参数来处理这个问题。一个 32 位 LPARAM 和一个 16 位 WPARAM

在使用 Win32 C API 时,您只需要确保正确阅读文档,并确保您按照文档所说正确的方式进行转换。

所以要回答你的问题,你是对的——但这只是因为你别无选择。为了在这里更完整,MFC 出现了(针对 C++ 程序员),但这并不被认为是一个好的面向对象的库——它更像是一个包装器。还有其他的做得更好(例如 wxWidgets)。

【讨论】:

  • 我想知道为什么你没有使 LRESULT 和 LPARAM 空指针?这正是我过去使用它们的目的。我猜他们想要一个比 void 指针分配的更大的“缓冲区”。我也猜想 int32/64 更标准化一点。
  • 哦,顺便说一句。如今,LPARAM 和 WPARAM 都是 32 位或 64 位整数的 typedef,但是 WPARAM 是无符号的。
  • @Trae 因为远指针和近指针之间的差异,在编写 16 位 Windows 时必须区分。是的,LPARAM、WPARAM、LRESULT 和其他数据类型随着时间的推移发生了变化。这就是您使用#defines 的原因。就像 Moo 说的,它不再被认为是好的风格,但在 1980 年代初期它非常活泼,现在仍然很好用。唯一的缺点是您绝对必须阅读文档。但回到 1980 年代,您还可以期望程序员阅读文档。那时他们还没有 Stack Overflow,所以这很辛苦。
  • @CodyGray,“当时没有 Stack Overflow”+1 ;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-18
  • 1970-01-01
  • 2014-04-24
  • 1970-01-01
  • 2014-09-05
  • 1970-01-01
相关资源
最近更新 更多