-
Encapsulating DlgProc
Main.cpp
Code:
#include <windows.h>
#include "Resource.h"
#include "utils.h"
#include "main.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
CDlg *pDlg = new CDlg(hInstance);
pDlg->SetTemplate(MAKEINTRESOURCE(IDD_DIALOG1));
if (!pDlg->AllocDlg())
{
MessageBox(0, "No dlg", "Error", 16);
}
pDlg->FreeDlg();
delete pDlg;
return 0;
}
main.h
Code:
class CDlg
{
public:
CDlg(HINSTANCE hInstance) : g_hInstance(hInstance){}
~CDlg()
{
delete[] pTemplate;
}
void SetTemplate(const char *lpTemplate)
{
int iSize = _lstrlen(lpTemplate);
pTemplate = new char[iSize+1];
_lstrcpy(pTemplate, lpTemplate);
}
bool AllocDlg()
{
hDlg = CreateDialog(g_hInstance, pTemplate, 0, DLGPROC(DlgProc));
return (hDlg ? true : false);
}
void FreeDlg()
{
if (hDlg) DestroyWindow(hDlg);
}
static LRESULT CALLBACK DlgProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
MessageBox(NULL, NULL, "Call 1", 0);
CDlg *Obj = reinterpret_cast<CDlg*>(GetWindowLong(hwnd, GWL_USERDATA));
if (Obj)
{
switch(Msg)
{
case WM_INITDIALOG:
{
SetWindowLong(hwnd, GWL_USERDATA, (LONG)Obj);
return Obj->DlgProc(hwnd, Msg, wParam, lParam);
}
case WM_CLOSE:
{
DestroyWindow(hwnd);
return Obj->DlgProc(hwnd, Msg, wParam, lParam);
}
case WM_DESTROY:
{
PostQuitMessage(0);
return Obj->DlgProc(hwnd, Msg, wParam, lParam);
}
}
return Obj->DlgProc(hwnd, Msg, wParam, lParam);
}
else
{
return Obj->DlgProc(hwnd, Msg, wParam, lParam);
}
}
protected:
private:
HINSTANCE g_hInstance;
char *pTemplate;
HWND hDlg;
};
My executable crashes...any ideas?
-
You return Obj->DlgProc(..) regardless of whether it's valid or not?
-
Code:
CDlg *Obj = reinterpret_cast<CDlg*>(GetWindowLong(hwnd, GWL_USERDATA));
if (Obj)
{
//...
}
else
{
return Obj->DlgProc(hwnd, Msg, wParam, lParam);
}
So if Obj is null, you try to use it? What you are trying to do simply doesn't make sense. I assume you want to associate an instance of the CDlg class with the hwnd of the dialog.
You should either pass a pointer to a CDlg object as the lParam of the WM_INITDIALOG message (probably using the CreateDialogParam function instead of the CreateDialog macro) or you can create a CDlg object locally in your Dialog procedure. I actually prefer to use a std::map (untested since I don't have access to a compiler atm):
Code:
static LRESULT CALLBACK DlgProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
static std::map<HWND,CDlg> hDlg;
switch (msg)
{
case WM_INITDIALOG:
hDlg[hwnd] = new CDlg;//also free this before the window is destroyed
break;
}
}
-
Hi JaWiB
Maybe you can help...
If I'm change to CreateDialogParam, how can I fix the DlgProc?
Thanks
-
You would replace CreateDialog with this:
Code:
hDlg = CreateDialogParam(g_hInstance, pTemplate, 0,DLGPROC(DlgProc),reinterpret_cast<LPARAM>(this));
Then you have to fix your DlgProc:
Code:
if (Obj)
{
//...
}
else if (Msg==WM_INITDIALOG)
{
SetWindowLong(hwnd,GWL_USERDATA,static_cast<LONG>(lParam));
}
And take a look at these lines:
Code:
return Obj->DlgProc(hwnd, Msg, wParam, lParam);
You're calling DlgProc recursively (it won't ever return).
-
Ok, thanks..
and thanks everyone for helping me seeing that error... lol :)
-
Ok, this compiles correctly, but..always returns "Obj is invalid" :(
Code:
static LRESULT CALLBACK DlgProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
CDlg *Obj = NULL;
switch(Msg)
{
case WM_INITDIALOG:
{
Obj = reinterpret_cast<CDlg*>(GetWindowLong(hwnd, GWL_USERDATA));
break;
}
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case IDC_BUTTON1:
{
if (Obj)
{
char *p;
int iSize = GetWindowTextLength(Obj->GetCtrlHandle(IDC_EDIT1));
p = new char[iSize+1];
GetWindowText(Obj->GetCtrlHandle(IDC_EDIT1), p, iSize+1);
MessageBox(hwnd, p, "Mensaje", 64);
delete[] p;
}
else
{
// Error Handler
MessageBox(hwnd, "Obj is invalid", "Beep", 16);
}
break;
}
}
break;
}
case WM_CLOSE:
{
delete[] Obj;
DestroyWindow(hwnd);
break;
}
case WM_DESTROY:
{
PostQuitMessage(0);
break;
}
}
return 0;
}
bool AllocDlg()
{
hDlg = CreateDialog(g_hInstance, MAKEINTRESOURCE(id), 0, DLGPROC(DlgProc));
SetWindowLong(hDlg, GWL_USERDATA, reinterpret_cast<LONG>(this));
return (hDlg ? true : false);
}
/Edit: Never mind... I solved it :D
-
Ok, I have a final question here:
Code:
static LRESULT CALLBACK DlgProc(HWND hwnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
CDlg *Obj = reinterpret_cast<CDlg*>(GetWindowLong(hwnd, GWL_USERDATA));
switch(Msg)
{
case WM_INITDIALOG:
{
if (!IfFileExists("C:\\joel\\dev\\Projectos\\ini_1\\ini.ini"))
{
MessageBox(hwnd, "No ini found", "Beep", 16);
}
else
{
char *s = new char[28];
ReadINIStr("C:\\joel\\dev\\Projectos\\ini_1\\ini.ini", "info", "msg", s);
Obj->SetCtrlText(s, IDC_EDIT1); // Crash :(
delete[] s;
}
break;
}
// so on..
Why Obj is not valid on WM_INITDIALOG and after that works propertly? Is it possible to change this?
Thanks :)