Hello,

it is necessary to create a callback function to handle the messages of an windows dialog box. The DialogBox() Function call requires a function pointer to this callback function.

If I don't use classes my sample code works fine but when I try to encapsulate my code in classes something goes wrong.

Here's a little example:

void GUIControl::init(HINSTANCE hInst)
{
    InitCommonControls();
    // Display the main dialog box.
    DialogBox( hInst, MAKEINTRESOURCE(IDD_MOUSE), NULL, &GUIControl::dlgProc);
}

INT_PTR CALLBACK GUIControl::dlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
{
    //handle GUI components
}

And the compiler says:

error C2664: 'DialogBoxParamA' : cannot convert parameter 4 from 'INT_PTR (__stdcall GUIControl::* )(HWND,UINT,WPARAM,LPARAM)' to 'DLGPROC'

Where is my failure? I mess around with the code but it won't work and I am no Windows programmer.

Many thanks in advance!
fisch

The issue arises because a window/dialog procedure is an alias(typedef) for a pointer to a function taking four parameters and returning a non-void 'value'. Your non-static member class function does not match this type(it's encumbered with this), while a static function does. Obviously, you could also make the callback procedure global or better, if following this approach, limit its scope within a suitable namespace.

This is a common problem which is typically solved by making the callback member function static and providing a mechanism whereby a pointer to a specific class object is available to that static function to forward or otherwise handle the messages. There are other approaches such as using hooks or assembly thunks but they are much more complex in both terms of implementation and comprehension.

Consider the following code using a static dialog procedure; the process is analagous for windows but with CreatWindowEx's final parameter used to pass this with WM_NCREATE initially intercepted instead of WM_INITDIALOG:

//dlg.cpp
#include <windows.h>
#include <tchar.h>
#include "resources.h"

class Dialog
{
private:
  HWND hDlg;
protected:
public:
  Dialog():hDlg(0){};
  virtual ~Dialog(){};
  
  INT_PTR  Create(const int id,const HWND hParent = 0)
  {
  return DialogBoxParam(GetModuleHandle(0),MAKEINTRESOURCE(id),hParent,DlgProc,
                        reinterpret_cast<LPARAM>(this));
  }
  
  static  INT_PTR CALLBACK DlgProc(HWND hwnd,UINT uMsg,WPARAM wp,LPARAM lp)
  {
  Dialog *pDlg=reinterpret_cast<Dialog*>(GetWindowLongPtr(hwnd,GWLP_USERDATA));
  if (!pDlg)
    {
    if (uMsg == WM_INITDIALOG)
      {
      pDlg = reinterpret_cast<Dialog*>(lp);
      pDlg->hDlg = hwnd;
      SetWindowLongPtr(hwnd,GWLP_USERDATA,lp);
      }
    else
      {
      return 0; //let system deal with message
      }
    }
  //forward message to member function handler
  return pDlg->ClassDlgProc(uMsg,wp,lp); 
  }
  
  INT_PTR ClassDlgProc(UINT uMsg,WPARAM wp,LPARAM lp)
  {
  //handle messages normally
  if (uMsg == WM_COMMAND)
    {
    if (LOWORD(wp) == IDOK || LOWORD(wp) == IDCANCEL)
      {
      EndDialog(hDlg,LOWORD(wp));
      return 1;
      }
    }
  return 0;
  }
};

int WINAPI WinMain(HINSTANCE,HINSTANCE,LPSTR,int)
{
Dialog my_dlg;
INT_PTR ip = my_dlg.Create(IDD_DLG);

return 0;
}
//script.rc
#if !defined __BORLANDC__
#include <windows.h>
#endif
#include "resources.h"

IDD_DLG DIALOGEX 0, 0, 252, 149
STYLE DS_CENTER | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_POPUP | WS_VISIBLE | 
      WS_CAPTION | WS_SYSMENU | WS_THICKFRAME
CAPTION "Dialog Box: Modal"      
FONT 8, "MS Sans Serif"
  {
  DEFPUSHBUTTON   "OK",IDOK,22,62,50,14
  PUSHBUTTON      "Cancel",IDCANCEL,111,63,50,14
  }
//resources.h
#define IDD_DLG                200

Many thanks for your quick answer!
I had thought about the static solution and wasn't very happy with it. But as there isn't an other way to solve it, apart from the global scope solution, I will try to implement it as static.
Once again, many thanks!

fisch

hi.. i have a *.csv file .. now i want to relocate this file using windows saveas dialog box ..please reply if u have any solution thanks

This article has been dead for over six months. Start a new discussion instead.