Is It Possible To Pass Additional Parameters to DialogProc()?

Started by
4 comments, last by Evil Steve 19 years ago
My DialogProc() function needs the ability to modify variables that are outside of its domain. Ideally, I want the ability to pass additional data to the DialogProc() function without using globals. Is DialogBoxParam() the proper way to do this? I want the ability to modify that parameter too. Should I pass a pointer to DialogBoxParam()? How can I retrieve and edit that value in DialogProc()?
.:<<-v0d[KA]->>:.
Advertisement
One solution would be to pass a pointer to a structure or class to the DialogBoxParam function. Then on dialog init, you can save that variable to a static variable in the dialog proc.

Another would be to register a user-defined window message (RegisterWindowMessage) and use SendMessage to pass whatever you want in wParm/lParm. This is probably a cleaner solution than the local static. However, the custom message is only useful if you are using a modeless dialog.
As Dave said, you can pass a pointer to a struct if you want more than one parameter.
I always use SetWindowLong() to set the user data long to whatever I need. For example:
struct MyParams{   int n;   CClass* p;   string str;};MyParams* pParams = new MyParams;pParams.n = 42;pParams.p = this;pParams.str = "Hello World!";DialogBoxParam(hInstance,MAKEINTRESOURCE(IDD_DIALOG),NULL,StaticProc,(LPARAM)pParams);BOOL CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam){MyParams* pParams;BOOL bRet;   // Store the data on WM_INITDIALOG //   if(uMsg == WM_INITDIALOG)   {      pParams = (MyParams*)lParam;      SetWindowLong(hWnd,GWL_USERDATA,lParam);   }    // Get pointer to struct //   pParams = (MyParams*)GetWindowLong(hWnd,GWL_USERDATA);   if(pParams)   {      bRet = pParams->p->DialogProc(hWnd,uMsg,wParam,lParam);      // Call delete on WM_DESTROY //      if(uMsg == WM_DESTROY)      {         delete pParams;         SetWindowLong(hWnd,GWL_USERDATA,0);      }      return bRet;   }   // Some message before WM_INITDIALOG //   return FALSE;}

That's not actual tested code, it's just an example. In my code I often just store the this pointer in the user data, and I don't need to delete it obviously.
I forgot about GWL_USERDATA. That's a much better solution than the local static.
Sorry for the late respone, but I just didn't get around to this by now.

After taking Evil Steve's code and tweaking it around to fit my program, I'm getting a few warnings. I'm not sure if they're serious or not. Other than that, my code is starting to look a bit freakish with all those pointers to vectors, so I'd like criticism on my code design too.

Here's my DialogProc(). I put comments around the lines where I get warnings:
INT_PTR CALLBACK PromptVerticesDialogProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ){	switch( uMsg )	{		case WM_INITDIALOG:			{                                /////////////////////////// WARNING 1				SetWindowLongPtr( hDlg, GWL_USERDATA, lParam );                                /////////////////////////////////////				PostMessage( hDlg, WM_NEXTDLGCTL, (WPARAM)(GetDlgItem( hDlg, IDC_PROMPTVERTICES_X )), TRUE );			}			break;		case WM_DESTROY:			{				SetWindowLongPtr( hDlg, GWL_USERDATA, 0 );			}		case WM_COMMAND:			{				switch( LOWORD( wParam ) )				{					case IDOK:						EndDialog( hDlg, IDOK );						break;					case IDCANCEL:						EndDialog( hDlg, IDCANCEL );						break;					case IDC_PROMPTVERTICES_ADDVERTEX:						{							POINT pt;							pt.x = GetDlgItemInt( hDlg, IDC_PROMPTVERTICES_X, NULL, TRUE );							pt.y = GetDlgItemInt( hDlg, IDC_PROMPTVERTICES_Y, NULL, TRUE );					                ////////////////////// WARNING 2                                        		std::vector<POINT>* TmpVertexList = (std::vector<POINT>*)GetWindowLongPtr( hDlg, GWL_USERDATA );                                                        ///////////////////////							TmpVertexList->push_back( pt );							char NotificationText[ 1024 ];							wsprintf( NotificationText, "Added vertex ( %d, %d ).", pt.x, pt.y );							SetDlgItemText( hDlg, IDC_PROMPTVERTICES_X, NULL );							SetDlgItemText( hDlg, IDC_PROMPTVERTICES_Y, NULL );							SetWindowText( GetDlgItem( hDlg, IDC_PROMPTVERTICES_NOTIFICATIONTEXT ), NotificationText );							PostMessage( hDlg, WM_NEXTDLGCTL, (WPARAM)(GetDlgItem( hDlg, IDC_PROMPTVERTICES_X )), TRUE );						}						break;				}			}			break;		default:			return FALSE;	}	return TRUE;}


If it matters, here's where I call the dialog box:
std::vector<POINT> TmpVertexList;	INT_PTR nResult = DialogBoxParam( g_hInst, MAKEINTRESOURCE( IDD_PROMPTVERTICES_MAIN ), g_hWnd,		reinterpret_cast<DLGPROC>(PromptVerticesDialogProc), (LPARAM)&TmpVertexList );


The warnings I receive are:
warning C4244: 'argument' : conversion from 'LPARAM' to 'LONG', possible loss of datawarning C4312: 'type cast' : conversion from 'LONG' to 'std::vector<_Ty> *' of greater size        with        [            _Ty=POINT        ]


1) Do these warnings matter?
2) Is there a better way to restructure my code?
.:<<-v0d[KA]->>:.
1) Nope. That's MSVC going crazy over 64-bit portability issues. It's extremely annoying, since that warning is actually completely wrong.
2) Your code looks fine really, that's pretty much how I'd do it.

This topic is closed to new replies.

Advertisement