【发布时间】:2020-04-14 08:23:13
【问题描述】:
我有这个功能:
GwBoolean win95_draw_button(DRAWITEMSTRUCT *pDrawParam, GwCore *pCore)
{
...
assert(pDrawParam);
HDC hDC = pDrawParam->hDC;
...
}
我得到了这个例外:
抛出异常:读取访问冲突。
pDrawParam 是 0x2B4FE760。异常指向HDC hDC = pDrawParam->hDC;
HDC 是这样定义的:
HANDLE HDC
value: void*
这个hDC在正确的站点上是这样的:
HDC hDC in struct tagDRAWITEMSTRUCT 函数win95_draw_button在这里被调用:
GwBoolean GwPushButton::EventHandler(GwEvent *ev)
{
long long lParam;
GwWord wParam;
GwWindowParams(&wParam, &lParam);
...
// Painting in Win95 Style
win95_draw_button ((DRAWITEMSTRUCT*)(long long)(lParam),this);
}
GwWindowParams 是这样定义的(如果有帮助的话):
PREEXPORT void POSTEXPORT GwWindowParams(GwWord* nwParam, long long* nlParam);
声明如下:
void GwWindowParams(GwWord *nwParam, long long *nlParam)
{
GwFUNCTION_TRACE(GwWindowParams(GwWord *,long long*), 0)
*nwParam = paramw;
*nlParam = paraml;
}
paraml 定义如下:static long paraml = 0L;
我强烈认为这里的问题是 lParam。 lParam 是 long 类型。我已经尝试过并将其更改为 long long 但我仍然遇到了异常。我想这也不是(DRAWITEMSTRUCT*)(long long)(lParam) 转换为DRAWITEMSTRUCT* 的正确方法。
【问题讨论】:
-
将
long long转换为DRAWITEMSTRUCT*的正确方法是reinterpret_cast<DRAWITEMSTRUCT*>(lParam),只要您知道lParam 中的整数表示DRAWITEMSTRUCT的地址。(DRAWITEMSTRUCT*)lParam也可以,但不推荐,因为这是 C 风格。 -
我用 reinterpret_cast 试过了,但是没有用
-
异常指定给定指针不是有效指针(读取访问冲突)。所以我假设存储在
lParam中的整数不代表DRAWITEMSTRUCT的地址。由于paraml被定义为long而不是long long,因此指针信息在64 位系统上可能会丢失,因为long可能被定义为32 位整数。用于表示地址的整数的正确类型是std::uintptr_t。这保证足够大以包含地址。 -
您是否正在尝试为
WM_DRAWITEM编写消息处理程序?您确定在此代码运行时正在处理该消息而不是其他消息吗?每条消息都以不同的方式使用其wParam和lParam值。 (例如,WM_NCHITTEST使用lParam作为光标坐标,而WM_SETTEXT使用它指向字符串的指针。)
标签: c++ winapi type-conversion 64-bit