私はWin32ダイアログボックスラッパーを開発しています。GetWindowLongPtrがガベージを返します
.hファイル
class dlg {
static INT_PTR CALLBACK DlgProcTmp(HWND hwnd,
UINT wm, WPARAM wp, LPARAM lp);
INT_PTR CALLBACK DlgProc(HWND hwnd, UINT wm, WPARAM wp, LPARAM lp);
bool ismodal;
protected:
HWND hwndDlg;
int id;
public:
virtual void oncreate(const widget &w) { }
virtual void oncmd(const widget &w, int code, int idCntrl, HWND hwnd) { }
virtual void onclose(const widget &w) { }
dlg() { }
dlg(int id);
INT_PTR domodal(HWND hwndOwner = nullptr);
widget domodeless(HWND hwndOwner = nullptr, int cmdshow = SW_SHOW);
};
.cppファイル
INT_PTR dlg::DlgProcTmp(HWND hwnd, UINT wm, WPARAM wp, LPARAM lp)
{
dlg *This;
if (wm == WM_INITDIALOG) {
This = (dlg *) lp;
setwinlong(hwnd, DWLP_USER, This);
This->oncreate(widget(hwnd));
return TRUE;
}
if ((This = getwinlong<dlg *>(hwnd, DWLP_USER)) != nullptr)
return This->DlgProc(hwnd, wm, wp, lp);
return FALSE;
}
INT_PTR dlg::DlgProc(HWND hwnd, UINT wm, WPARAM wp, LPARAM lp)
{
this->hwndDlg = hwnd;
switch (wm) {
case WM_COMMAND:
this->oncmd(widget(hwnd), HIWORD(wp), LOWORD(wp), (HWND) lp);
if (this->ismodal)
EndDialog(hwnd, LOWORD(wp));
else
DestroyWindow(hwnd);
return TRUE;
case WM_DESTROY:
this->onclose(widget(hwnd));
return TRUE;
}
return FALSE;
}
ダイアログがDialogBoxParam
呼び出しでdomodal
に作成されます。最後の引数はthis
ポインタで、WM_INITDIALOG
メッセージのlparamから取得します。異なるメッセージ間でthis
を使用するには、this
をWM_INITDIALOGにHWNDで保存します。しかし、WM_INITDIALOGではないメッセージが到着し、GetWindowLongPtr
のthis
ポインタを取得すると、vtableが破損しているゴミのdlg
クラスが返されます。私は正しいハンドラ関数を呼び出すためにvtableを使用します。その結果、私のコードは、WM_COMMANDハンドラの最初の行でクラッシュします。ここでは、デバッガがthis
の値として示したものです:
GetWindowLongPtrがゴミを返しているのはなぜ?
BTW、getwinlong
はGetWindowLongPtr
のラッパーであり、setwinlong
はSetWindowLongPtr
のラッパーです。ここでは、実装されている:
template <class TYPE> static TYPE getwinlong(HWND hwnd, int idx)
{
return (TYPE) GetWindowLongPtr(hwnd, idx);
}
template <class TYPE> static void setwinlong(HWND hwnd, int idx, TYPE val)
{
SetWindowLongPtr(hwnd, idx, (LONG_PTR) val);
}
私はあなたがLONGの代わりLONG_PTRにキャスト場合GetWindowLongPtrはhttps://blogs.msdn.microsoft.com/oldnewthing/20131226-00/?p=2263のように、Win64のに失敗する方法については、多くの記事を見てきました。私は自分の問題が異なっていると信じています。
編集:私はあなたが私たちを示したコードをつなぎ合わせて、作業のサンプルを作成することができました
INT_PTR dlg::domodal(HWND hwndOwner)
{
this->ismodal = true;
return DialogBoxParam(gethinst(hwndOwner),
MAKEINTRESOURCE(id), hwndOwner, dlg::DlgProcTmp,
(LPARAM) this);
}
ダイアログテンプレートで実際にユーザーデータ用に余分なスペースが指定されていますか?ダイアログ自体がそのデータを独自の目的で使用していますか?常にあります:['SetProp'](https://msdn.microsoft.com/en-us/library/windows/desktop/ms633568%28v=vs.85%29.aspx) – theB
@theBこれはどういう意味ですか? https://msdn.microsoft.com/en-us/library/windows/desktop/ms645398(v=vs.85).aspx – user3144238
このダイアログのインスタンスを作成するコードを投稿できますか? – andlabs