我正在编写一个windows api包装器库。但我遇到了问题:每当我尝试在“包装”窗口过程中使用this
指针时,就会抛出读取访问冲突 - 从静态版本调用的过程。这是库接口
class widget {
protected:
HWND hwnd;
public: // instinfo is class that represents WNDCLASS structure
widget(instinfo ii, const WCHAR *text,
DWORD styles = WS_OVERLAPPEDWINDOW,
point ul = DEFUL,
int cx = CW_USEDEFAULT,
int cy = CW_USEDEFAULT,
HWND parent = NULL,
HMENU hm = NULL);
};
class olwindow : public widget {
// static window proc: It registered by WNDCLASS structure
static LRESULT CALLBACK baseWinProc(HWND hwnd, UINT wm, WPARAM wp, LPARAM lp);
LRESULT CALLBACK winproc(UINT wm, WPARAM wp, LPARAM lp);
protected:
virtual void LButtonDown(int, int) { } // an example event, is override by classes that inherit and wanna customize
public:
friend class instinfo;
olwindow(instinfo ii, const WCHAR *cap, point ul = DEFUL,
int cx = CW_USEDEFAULT, int cy = CW_USEDEFAULT);
};
相关功能为baseWinProc
和winproc
,我将在下面显示:
LRESULT olwindow::baseWinProc(HWND hwnd, UINT wm, WPARAM wp, LPARAM lp)
{
olwindow *w;
if (wm == WM_NCCREATE)
SetWindowLong(hwnd, GWL_USERDATA, (LONG) ((CREATESTRUCT *) lp)->lpCreateParams);
w = (olwindow *) GetWindowLong(hwnd, GWL_USERDATA);
if (w)
w->winproc(wm, wp, lp);
return DefWindowProc(hwnd, wm, wp, lp);
}
LRESULT olwindow::winproc(UINT wm, WPARAM wp, LPARAM lp)
{
switch (wm) {
case WM_LBUTTONDOWN:
// on line below is crash
this->LButtonDown(GET_X_LPARAM(lp), GET_Y_LPARAM(lp));
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return 0;
}
错误消息是
抛出异常:读取访问冲突。
这 - >是0x12A07E0。
这意味着什么?
编辑:这是widget
类的构造函数,它由olwindow
的构造函数调用
widget::widget(instinfo ii, const WCHAR * text, DWORD styles, point ul,
int cx, int cy, HWND parent, HMENU hm)
{
this->hwnd = CreateWindow(ii.getClassName(), text, styles,
ul.x, ul.y, cx, cy, parent, hm, ii.getHinst(), this);
if (this->hwnd == NULL)
MessageBox(NULL, getErrMsg(), L"", 0);
ShowWindow(this->hwnd, SW_SHOW);
}
olwindow::olwindow(instinfo ii, const WCHAR * cap, point ul, int cx, int cy) :
widget(ii, cap, WS_OVERLAPPEDWINDOW, ul, cx, cy)
{ }
答案 0 :(得分:1)
问题是由两个因素共同造成的:
在返回之前,CreateWindow会向窗口过程发送WM_CREATE消息。对于重叠,弹出窗口和子窗口,CreateWindow会向窗口发送WM_CREATE,WM_GETMINMAXINFO和WM_NCCREATE消息。
由于CreateWindow
在基类(widget
)构造函数中执行,因此派生类' olwindow
消息处理程序运行时,尚未构造(WM_NCCREATE
)实例。将通过CREATESTRUCT
传递的指针转换为派生类'因此,类型是一个错误。
要解决此问题,您需要将指针强制转换为其原始类型,即widget*
。如果需要在窗口过程中访问派生对象,则需要将窗口创建移动到完全构造它的位置。
作为替代方案,您可以继续从基类构造函数中调用CreateWindow
,但只有在完全构造后才转换为派生对象,例如:通过在派生类的基类中存储一个布尔值'构造