Tech Support > Microsoft Windows > Development Resources > DialogBox function and C++ classes in WinAPI
DialogBox function and C++ classes in WinAPI
Posted by Nick on December 23rd, 2003


Hi there,

At the risk of totally embarrasing myself for my stupidity I thought
this question will at least put my mind to rest.

Right. I'm writing an application in plain WinAPI and have started
to get problems to keep track of all the bits 'n bobs due to the
increasing size of the project.

So as I total beginner I thought maybe I could apply an object oriented
approach to get back on track...

Here's the problem.
I'm just trying to put a Dialogprocedure inside a class but cannot get
it to compile because the DialogBox() function doesn't seem to recognise
classes. Here's a snippet:


class myclass
{
private: // whatever

public:

BOOL CALLBACK DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
/* ... lots of other stuff goes here */
}
};


LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{

/* ... lots of other stuff goes here */

myclass dialogclass;

case WM_CREATE:

DialogBox (hInstance, TEXT ("Hello"), hwnd, dialogclass.DlgProc);
^^^^^^^^^^^^^^^^^^^
}

This is the error I'm getting with MS Visual Studio 6.0:

error C2664: 'DialogBoxParamA' : cannot convert parameter 4 from 'int
(struct HWND__ *,unsigned int,unsigned int,long)' to 'int (__stdcall *)
(struct HWND__ *,unsigned int,unsigned int, long)'
None of the functions with this name in scope match the target type

---

Have I totally misunderstood the concept of classes or is this a limitation
of the DialogBox function?

Thanks in advance,
Nick








Posted by Elias Fotinis on December 23rd, 2003


Nick wrote:
Just make DlgProc 'static' and it should work. The way you've written it
now, DlgProc is a normal member function of 'myclass'. This means that
DlgProc always needs to be called using an object of 'myclass', like
dialogclass.DlgProc . This object is implicitly passed as a hidden
parameter ('this'), which DialogBox can't handle. By making DlgProc
static, you can use it without any particular object; you only need to
denote the class name, like myclass:lgProc .

All this, of course, beats the purpose of using an object to hold your
data, since you can't use its functions directly with DialogBox. You'll
have to use DialogBoxParam and pass a pointer to the object
(&dialogclass). Then, inside DlgProc, you can save that pointer during
WM_INITDIALOG to, let's say, the GWL_USER slot, and use it anytime you
need to handle any message. Here's an example (without much
error-checking) :

BOOL CALLBACK myclass:lgProc(HWND hWnd, ....)
{
// on any msg after WM_INITDIALOG this will contain
// a valid object pointer
myclass* obj = (myclass*)GetWindowLong(hWnd, GWL_USER);

switch (uMsg) {
case WM_INITDIALOG: {
// first save the obj ptr to the GWL_USER slot
SetWindowLong(hWnd, GWL_USER, lParam)
// set it to the local var
obj = (myclass*)wParam;
// save the handle in the object
obj->hWnd = hWnd;
// now, have fun with it
return obj->OnInitDialog();
}
case WM_DESTROY: {
obj->OnDestroy();
return TRUE;
}
case WM_COMMAND: {
obj->OnCommand(wParam, lParam);
return TRUE;
}
//...etc...
}

return FALSE;
}


Posted by Stefano \HappyMan\ on December 23rd, 2003


On Tue, 23 Dec 2003 04:27:22 +0100, "Nick"
<nick_1979NOSPAM@hotmailNOSPAM.com> wrote:

[cut]

You can download a little framework I wrote to encapsulate the Win32
API in a object oriented way. The framework is in 2 files and it is
quite simple to read and modify.

http://www.sgr.info/windev

Bye

Stefano "HappyMan" (Lago Maggiore - NO)
--
Personal Web http://www.sgr.info
Email happyman69 (at) despammed.com

Posted by Jugoslav Dujic on December 23rd, 2003


Elias Fotinis wrote:
| Nick wrote:
|
| All this, of course, beats the purpose of using an object to hold your
| data, since you can't use its functions directly with DialogBox. You'll
| have to use DialogBoxParam and pass a pointer to the object
| (&dialogclass). Then, inside DlgProc, you can save that pointer during
| WM_INITDIALOG to, let's say, the GWL_USER slot, and use it anytime you
| need to handle any message.

Also, take a look at SetProp and GetProp APIs. I think they're a tad
more bulletprof than GWL_USERDATA. One possible schema is (pardon my
sloppy C++, I'm just trying to express an idea):

class myclass
{
private: // whatever

public:

static BOOL CALLBACK GeneralDlgProc(HWND hDlg, UINT msg, WPARAM wParam,
LPARAM lParam);
BOOL CALLBACK MyRealDlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM
lParam);
};
// ----------------------------------------

myclass dialogclass;

case WM_CREATE:

DialogBoxParam (hInstance, TEXT ("Hello"), hwnd, GeneralDlgProc,
(LPARAM)&dialogclass);
// ----------------------------------------
static BOOL CALLBACK myclass::GeneralDlgProc(HWND hDlg, UINT msg, WPARAM wParam,
LPARAM lParam)
....
myclass* dialogclass;
case WM_INITDIALOG:
SetProp(hwnd, "mydialog", (HANDLE)lParam);
dialogclass = (myclass*)lParam;
return dialogclass->MyRealDlgProc(hDlg, ....);
default:
dialogclass = (myclass*)GetProp(hwnd, "mydialog");
return dialogclass->MyRealDlgProc(hDlg, ....);

--
Jugoslav
___________
www.geocities.com/jdujic

Posted by Nick on December 23rd, 2003


Thank you all very much for the help.
You saved me a lot of headaches!



Similar Posts