Sign in to follow this  
yckx

win32 dialog class access violation [solved]

Recommended Posts

I'm trying to write a reusable base modal dialog, but I'm getting an access violation error. I know where the problem is, but I'm not sure how to solve it. Here's the code. basedialog.h:
#include <windows.h>

class BaseDialog
{
	public:
		BaseDialog(int dialog_id, HWND hParent);
		~BaseDialog();
		
		LRESULT Do();
		
	protected:
		static LRESULT CALLBACK StaticDialogProc(HWND, UINT, WPARAM, LPARAM);
		virtual LRESULT Proc(HWND, UINT, WPARAM, LPARAM);
		
		HWND parent_wnd;
		int dlg_id;
};


basedialog.cpp:
BaseDialog::BaseDialog(int dialog_id, HWND hParent) :
	dlg_id(dialog_id), parent_wnd(hParent)
{
}

BaseDialog::~BaseDialog()
{
}

LRESULT CALLBACK BaseDialog::StaticDialogProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	if(msg == WM_INITDIALOG)
	{
		BaseDialog* dlg = reinterpret_cast<BaseDialog*>(lParam);
		SetWindowLongPtr(hWnd, GWLP_USERDATA,lParam);
	}
		
	BaseDialog* dlg = reinterpret_cast<BaseDialog*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
	dlg->Proc(hWnd, msg, wParam, lParam); //access violation occurs here
}

LRESULT BaseDialog::Proc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
}

LRESULT BaseDialog::Do()
{
	return DialogBoxParam(GetModuleHandle(NULL),
					  MAKEINTRESOURCE(dlg_id),
					  parent_wnd,
					  (DLGPROC)StaticDialogProc,
					  (LPARAM)this);
}


In the debugger, lParam is reported as being 0 in StaticDialogProc, which I'm guessing is why I'm getting an access violation when I call dlg->Proc, but I'm not sure about this. I'd be grateful for any help in resolving this. yckx [Edited by - yckx on May 31, 2005 11:22:01 PM]

Share this post


Link to post
Share on other sites
The 0 value in lParam is definitely part of the problem. The deeper problem is that you're not creating the dialog correctly with the expected parameter. Make sure you're using one of the functions listed in the lParam info section on WM_INITDIALOG to create the dialog, and make sure the pointer you pass is a valid pointer to a BaseDialog object.

Share this post


Link to post
Share on other sites
Are you sure that the dialog's hWnd has been initialized prior to the call you're having problems with? Check hWnd. lParam doesn't really seem to be doing anything so it shouldn't be causing an access violation itself.

-fel

Share this post


Link to post
Share on other sites
Easy, WM_INITDIALOG is NOT the first message that appears in your dialog proc.
It's probably WM_NCCREATE, but i'm not sure about that. If any message gets sent to your dialog proc before WM_INITDIALOG the user data isn't set yet.
In that case, just pass the message on to the DefDlgProc.

Share this post


Link to post
Share on other sites
Quote:
Original post by ApochPiQ
The 0 value in lParam is definitely part of the problem. The deeper problem is that you're not creating the dialog correctly with the expected parameter. Make sure you're using one of the functions listed in the lParam info section on WM_INITDIALOG to create the dialog, and make sure the pointer you pass is a valid pointer to a BaseDialog object.

Well, it's created in BaseDialog::Do(), which is this:

LRESULT BaseDialog::Do()
{
return DialogBoxParam(GetModuleHandle(NULL),
MAKEINTRESOURCE(dlg_id),
parent_wnd,
(DLGPROC)StaticDialogProc,
(LPARAM)this);
}



DialogBoxParam is one of the proper functions to use, and dlg_id and parent_wnd are set upon object creation, so the call looks fine to me.
Quote:
Original post by felisandria
Are you sure that the dialog's hWnd has been initialized prior to the call you're having problems with? Check hWnd. lParam doesn't really seem to be doing anything so it shouldn't be causing an access violation itself.

Well, lParam is supposed to contain a pointer to the actual object. The theory is this:

I want to derive dialogs from a base class. But the dialog proc must be static, so it can't be virtual. So, on the dialog's initmessage, get a pointer to the object (sent through the lParam of WM_INITDIALOG, via DialogBoxParam() ), and then route all messages to a virtual Proc().
Quote:
Original post by Endurion
Easy, WM_INITDIALOG is NOT the first message that appears in your dialog proc.

Well, there is no message handler in my realdialog proc, just the WM_INITDIALOG in the static one. BaseDialog::Proc() simply returns false (it is mistakenly shown as being an empty function above), as all good dialog procs not handling a message should do ;)

Or do you mean, WM_INITDIALOG is not the first message being sent? It's the message to handle to init the dialog. If you're saying messages are sent before WM_INITDIALOG, how do I send them to Proc() if I don't have the pointer to the object sent from Do()? (which I don't seem to be getting anyway :P )

Aargh. A pox upon callback functions and their contrariness. I shall resume my wrangling of this beast later today.

Share this post


Link to post
Share on other sites
If the casted dlg you get from the userdata simply assume that the data has not been set yet and return FALSE.
That should work for most cases.

Alternatively, you could try to get the lparam from WM_NCCREATE. This should be one of the first messages to arrive at the dialog.

Share this post


Link to post
Share on other sites
Well, I managed to get it straightened out. The dialog was being sent a WM_SETFONT message before the WM_INITDIALOG message, and then trying to process it through a pointer it didn't have (because the pointer comes in the WM_INITDIALOG). I added a check to see if GetWindowLongPtr returns a valid pointer, and if not, to return false, and it works peachy keen now ;)

Thanks for looking at it everybody.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this