Dialog Boxes Help

Okay, I am a beginner -- obviously -- to the WIN32 API, and I am having trouble with dialog boxes. I can give you the error reports, and both my resource script and my main.cpp code. If you ask, I may even put the resource header in, just so you can see if any problems exist there.

Main.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#include <windows.h>
#include <winsock2.h>
#include "resource.h"

/*Winsock declaration*/
BOOL Winsock2_32()
{
	WSADATA wsaData;
	if (WSAStartup(MAKEWORD(2,0), &wsaData) != 0) {
 	MessageBox(NULL, TEXT("WARNING: FATAL ERROR"), TEXT("WSAStartup failed."),
	MB_OK | MB_ICONINFORMATION);
	return 0;
	}
	else {
		return 1;
	}
}

/*Dialog Box class*/
class Dialog_Boxes {
	public:
		int Dialog_Return_Value;
		BOOL CALLBACK Dialog_Proc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {
			switch(Message) {
		case WM_INITDIALOG:{
			return TRUE;
			break;
		}
		case WM_COMMAND: {
			switch(LOWORD(wParam)) {
				case IDOK: {
					EndDialog(hwnd, IDOK);
					break;
				}
			}
		}
		default: {
			return FALSE;
		}
	}
}
}About_Dialog;

/* This is where all the input to the window goes to */
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {
	switch(Message) {
		
		/* Upon destruction, tell the main thread to stop */
		case WM_DESTROY: {
			PostQuitMessage(0);
			break;
		}
		/*Upon creation, tells windows to create objects inside of the window.*/
		case WM_CREATE: {
			break;
		}

		/*Upon an action upon an window object, this tells how to react to the action.*/
		case WM_COMMAND: {
			switch (LOWORD(wParam)) {
				case IDM_EXIT: {
					PostMessage(hwnd, WM_CLOSE, 0, 0);
					break;
				case IDM_ABOUT: {
					About_Dialog.Dialog_Return_Value = DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDM_ABOUT),
					hwnd, About_Dialog.Dialog_Proc);
						switch (About_Dialog.Dialog_Return_Value){
							case -1: {
								MessageBox(NULL, TEXT("FATAL ERROR"), TEXT("Dialog Box creation error!"), MB_OK | MB_ICONERROR);
								break;
							}
							default: {
								break;
							}
						}
					break;
				}
			}
		}
	}
		
		
		/* All other messages (a lot of them) are processed using default procedures */
		default:
			return DefWindowProc(hwnd, Message, wParam, lParam);
	}
	return 0;
}

/* The 'main' function of Win32 GUI programs: this is where execution starts */
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
	WNDCLASSEX wc; /* A properties struct of our window */
	HWND hwnd; /* A 'HANDLE', hence the H, or a pointer to our window */
	MSG Msg; /* A temporary location for all messages */

	/* zero out the struct and set the stuff we want to modify */
	memset(&wc,0,sizeof(wc));
	wc.cbSize		 = sizeof(WNDCLASSEX);
	wc.lpfnWndProc	 = WndProc; /* This is where we will send messages to */
	wc.hInstance	 = hInstance;
	wc.hCursor		 = LoadCursor(NULL, IDC_ARROW);
	wc.lpszMenuName = MAKEINTRESOURCE(IDM_MENU); //Load menu defined in Resource.rc
	
	/* White, COLOR_WINDOW is just a #define for a system color, try Ctrl+Clicking it */
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wc.lpszClassName = "WindowClass";
	wc.hIcon		 = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON));  //Load 32, 32 size icon.
	wc.hIconSm		 = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON), 
	IMAGE_ICON,	16, 16, 0);  //Load smaller 16, 16 size icon.
	

	if(!RegisterClassEx(&wc)) {
		MessageBox(NULL, "Window Registration Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
		return 0;
	}

	hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,"WindowClass","Caption",WS_VISIBLE|WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, /* x */
		CW_USEDEFAULT, /* y */
		640, /* width */
		480, /* height */
		NULL,NULL,hInstance,NULL);

	if(hwnd == NULL) {
		MessageBox(NULL, "Window Creation Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
		return 0;
	}
	
	/*Winsock error check function call*/
	if((Winsock2_32) == 0) {
		DestroyWindow(hwnd);
	}

	/*
		This is the heart of our program where all input is processed and 
		sent to WndProc. Note that GetMessage blocks code flow until it receives something, so
		this loop will not produce unreasonably high CPU usage
	*/
	while(GetMessage(&Msg, NULL, 0, 0) > 0) { /* If no error is received... */
		TranslateMessage(&Msg); /* Translate key codes to chars if present */
		DispatchMessage(&Msg); /* Send it to WndProc */
	}
	return Msg.wParam;
}


Resource script

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <windows.h> 									//Header declarations
#include "resource.h"									//Header declarations

IDI_ICON ICON App_Icon.ico								//System Icon

IDM_MENU MENU DISCARDABLE  								//System Menu
{
	POPUP "&File"
	{
		 MENUITEM "&EXIT",			IDM_EXIT
	}
	POPUP "&Help"
	{
		MENUITEM "&About",			IDM_ABOUT
	}
}

IDD_ABOUT_POPUP DIALOG DISCARDABLE 0, 0, 239, 66,		//About menuitem dialog popup declaration
Style DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
Caption "Winsock"
Font 8, "MS SANS SERIF"
{
	DEFPUSHBUTTON 	"&OK" IDOK, 174, 18, 50, 14
	GROUPBOX		"About this program...", IDC_STATIC, 7, 7, 225, 52
	CTEXT			"This program was made by Harley Lorenzo with Dev-C++", IDC_STATIC, 16, 18, 144, 33
}


Error:
Line 73, col 41: [Error] cannot convert 'Dialog_Boxes::Dialog_Proc' from type 'BOOL (Dialog_Boxes::)(HWND, UINT, WPARAM, LPARAM) {aka int (Dialog_Boxes::)(HWND__*, unsigned int, unsigned int, long int)}' to type 'DLGPROC {aka int (__attribute__((__stdcall__)) *)(HWND__*, unsigned int, unsigned int, long int)}'


Note that line 73 is now 65 on the main.cpp for some reason
Last edited on
Hello, anyone?

I need serious help.

SERIOUS help.

I can not find or define any work around.
the prototype of Dialog_Boxes::Dialog_Proc is not equal to the prototype of the forth parameter in Dialog_Boxes .
You must declare the prototype of the forth parameter like:
CALLBACK INT_PTR proc(HWND, UINT, WPARAM, LPARAM);

so on line 23
1
2
3
BOOL CALLBACK Dialog_Proc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)
=> 
INT_PTR CALLBACK Dialog_Proc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam)


Have any other questions?
Yes, I am still getting an error. I will the lines that are the problem, and the error.

1
2
3
4
class Dialog_Boxes {
	public:
		int Dialog_Return_Value;
		INT_PTR CALLBACK Dialog_Proc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) 


1
2
About_Dialog.Dialog_Return_Value = DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDM_ABOUT),
					hwnd, About_Dialog.Dialog_Proc(HWND, UINT, WPARAM, LPARAM));


The second coding box is getting these errors:

Expected Primary expression before ',' token
x3
Expected Primary expression before ')' token


Obviously, this means I am missing something in the parameters in the function, but, I've tried every single combination of everything.
Last edited on
I lowered down the errors by changing to exactly like you said. (I never do things exactly people tell me to do them, I try to find my own original way. Hence, the confusing Dialog box class I made for myself.)

Here is the entire code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#include <windows.h>
#include <winsock2.h>
#include "resource.h"

/*Winsock declaration*/
BOOL Winsock2_32()
{
	WSADATA wsaData;
	if (WSAStartup(MAKEWORD(2,0), &wsaData) != 0) {
 	MessageBox(NULL, TEXT("WARNING: FATAL ERROR"), TEXT("WSAStartup failed."),
	MB_OK | MB_ICONERROR);
	return 0;
	}
	else {
		return 1;
	}
}

/*Dialog Box class*/
class Dialog_Boxes {
	public:
		int Dialog_Return_Value;
		INT_PTR CALLBACK Dialog_Proc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {
			switch(Message) {
		case WM_INITDIALOG:{
			return TRUE;
		}
		case WM_COMMAND: {
			switch(LOWORD(wParam)) {
				case IDOK: {
					EndDialog(hwnd, IDOK);
				}
			break;
			}
		}
		default: {
			return FALSE;
		}
	}
}
}About_Dialog;

/* This is where all the input to the window goes to */
LRESULT CALLBACK WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {
	switch(Message) {
		
		/* Upon destruction, tell the main thread to stop */
		case WM_DESTROY: {
			PostQuitMessage(0);
			break;
		}
		/*Upon creation, tells windows to create objects inside of the window.*/
		case WM_CREATE: {
			break;
		}

		/*Upon an action upon an window object, this tells how to react to the action.*/
		case WM_COMMAND: {
			switch (LOWORD(wParam)) {
				case IDM_EXIT: {
					PostMessage(hwnd, WM_CLOSE, 0, 0);
					break;
				case IDM_ABOUT: {
					About_Dialog.Dialog_Return_Value = DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDM_ABOUT),
					hwnd, INT_PTR CALLBACK About_Dialog.Dialog_Proc(HWND, UINT, WPARAM, LPARAM));
						switch (About_Dialog.Dialog_Return_Value){
							case -1: {
								MessageBox(NULL, TEXT("FATAL ERROR"), TEXT("Dialog Box creation error!"), 
								MB_OK | MB_ICONERROR);
								break;
							}
							default: {
								break;
							}
						}
					break;
					}
				}
			}
		}
		/* All other messages (a lot of them) are processed using default procedures */
		default:
			return DefWindowProc(hwnd, Message, wParam, lParam);
	}
	return 0;
}

/* The 'main' function of Win32 GUI programs: this is where execution starts */
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
	WNDCLASSEX wc; /* A properties struct of our window */
	HWND hwnd; /* A 'HANDLE', hence the H, or a pointer to our window */
	MSG Msg; /* A temporary location for all messages */

	/* zero out the struct and set the stuff we want to modify */
	memset(&wc,0,sizeof(wc));
	wc.cbSize		 = sizeof(WNDCLASSEX);
	wc.lpfnWndProc	 = WndProc; /* This is where we will send messages to */
	wc.hInstance	 = hInstance;
	wc.hCursor		 = LoadCursor(NULL, IDC_ARROW);
	wc.lpszMenuName = MAKEINTRESOURCE(IDM_MENU); //Load menu defined in Resource.rc
	
	/* White, COLOR_WINDOW is just a #define for a system color, try Ctrl+Clicking it */
	wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
	wc.lpszClassName = "WindowClass";
	wc.hIcon		 = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON));  //Load 32, 32 size icon.
	wc.hIconSm		 = (HICON)LoadImage(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON), 
	IMAGE_ICON,	16, 16, 0);  //Load smaller 16, 16 size icon.
	

	if(!RegisterClassEx(&wc)) {
		MessageBox(NULL, "Window Registration Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
		return 0;
	}

	hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,"WindowClass","Caption",WS_VISIBLE|WS_OVERLAPPEDWINDOW,
		CW_USEDEFAULT, /* x */
		CW_USEDEFAULT, /* y */
		640, /* width */
		480, /* height */
		NULL,NULL,hInstance,NULL);

	if(hwnd == NULL) {
		MessageBox(NULL, "Window Creation Failed!","Error!",MB_ICONEXCLAMATION|MB_OK);
		return 0;
	}
	
	/*Winsock error check function call*/
	if((Winsock2_32) == 0) {
		DestroyWindow(hwnd);
	}

	/*
		This is the heart of our program where all input is processed and 
		sent to WndProc. Note that GetMessage blocks code flow until it receives something, so
		this loop will not produce unreasonably high CPU usage
	*/
	while(GetMessage(&Msg, NULL, 0, 0) > 0) { /* If no error is received... */
		TranslateMessage(&Msg); /* Translate key codes to chars if present */
		DispatchMessage(&Msg); /* Send it to WndProc */
	}
	return Msg.wParam;
}


Error:

Line 64: Expected Primary-Expression before '_attribute_'
hi man,well done.i'm very sorry that i did not say it clearly.
I think you are a beginner so that you don't distinguish between function calls and function declaration.

/*ok,put function poiter,parameters are not needed*/
1
2
case IDM_ABOUT: {
	About_Dialog.Dialog_Return_Value = DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDM_ABOUT),hwnd,About_Dialog.Dialog_Proc);


my email: nie950@gmail.com
Unbelievable. I am still getting the same error.

It appears that no matter how I do this, this FREAKING API IS GOING TO GIVE ME SUPER S***!!!!!!!!

1
2
About_Dialog.Dialog_Return_Value = DialogBox(GetModuleHandle(NULL), MAKEINTRESOURCE(IDD_ABOUT_POPUP),
					hwnd, About_Dialog.Dialog_Proc);


Error: Expected primary-expression before '_attribute_'

WHAT THE HECK AM I DOING WRONG!

I have already done this exact thing before you showed up, and I got this error before. There is something else that I need to do to fix this.
You're right, there is some thing else you need to do :)

When you pass Dialog_Proc to DialogBox(...), it must be a static function. Member functions have a hidden this pointer passed with them so you can't pass them to functions that take function pointers as parameters. Their signatures will just never match.

Remember though, since static functions have no this pointer, you can't access instance member variables of your class unless they are also static. You need a pointer to the object's instance i.e. this to access an instance variable. The way round this is to use DialogBoxParam(...) instead of DialogBox(...) which takes an extra parameter which you can use to pass a pointer to your object's instance. When your DlgProc gets called, the pointer you passed to DialogBoxParam you can get from the lparam parameter of the WM_INITDIALOG message which you'll see in the updated code below.

See here: http://msdn.microsoft.com/en-us/library/windows/desktop/ms645465(v=vs.85).aspx
and here: http://msdn.microsoft.com/en-us/library/windows/desktop/ms645428(v=vs.85).aspx

Your code should look something like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/*Dialog Box class*/
class Dialog_Boxes {
    private:
        // Somewhere to store our dialog window handle as we'll need it later
        HWND hDlg; 
    public:
        // A constructor and destructor
        Dialog_Boxes() : hDlg(NULL) {};
        ~Dialog_Boxes() {};
        
        // You don't really need to store this here.
        int Dialog_Return_Value;
        static INT_PTR CALLBACK Dialog_Proc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) {
        // The dwInitParam of DialogBoxParam will be stored in GWLP_USERDATA so lets try and cast it 
        Dialog_Boxes* pDlg = reinterpret_cast<Dialog_Boxes*>(GetWindowLongPtr(hwnd,GWLP_USERDATA));
            if (!pDlg)
            {
                if (Message == WM_INITDIALOG) {
                    // Since our pointer only get's passed with the WM_INITDIALOG message
                    // what we've casted might not be ours so only record it if we receive the message
                    pDlg = reinterpret_cast<Dialog_Boxes*>(lParam);
                    pDlg->hDlg = hwnd;
                    // Pop the lParam back in the USERDATA area (I can't remember why, it's been a while!)
                    SetWindowLongPtr(hwnd,GWLP_USERDATA, lParam);
                    return TRUE;
                }
            }
            else {
                return 0; // Ignore the message and let windows deal with it
            }
            // Handle the message with our member function
            return pDlg->ClassDialogProc(Message, wParam, lParam);
        }
        // An normal member function
        INT_PTR ClassDialogProc(UINT message, WPARAM wParam, LPARAM lParam)
        {
            switch (message) {
                case WM_COMMAND: {
                    switch(LOWORD(wParam)) {
                        case IDOK: {
                            return EndDialog(hDlg, IDOK);		// Remember the hWnd we stored earlier?
                        }
                    break;
                    }
                }
                default: {
                    return 0;
                }
            }
        }	
    }
}; // No need for this -  About_Dialog; 


And in your IDM_ABOUT handler:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
case IDM_ABOUT: {
    Dialog_Boxes dialog;
    INT_PTR ret = DialogBoxParam(GetModuleHandle(NULL), MAKEINTRESOURCE(IDM_ABOUT),
    hwnd, Dialog_Boxes::Dialog_Proc, reinterpret_cast<LPARAM>(&dialog));
    switch (ret){
        case -1: {
            MessageBox(NULL, TEXT("FATAL ERROR"), TEXT("Dialog Box creation error!"), 
                MB_OK | MB_ICONERROR);
            break;
        }
        default: {
            break;
        }
    }
    break;
}
                }


I haven't compiled or tested this as I don't have a compiler handy at the moment but it should give you an idea of what to do. I also haven't worked on windows in a loooong time so if I've got anything wrong I apologise :)

*Edit* I realise that some of this may not make sense initially, just stick at it and remember - there's no such thing as a stupid question :)
Last edited on
Thank you, thank you so much!

I put it in, and I only have one more question. I have one resource error in the dialog box resource. Can you have a look? (By the way, I think all of this confusion is do to a old tutorial, don't you say? If you can point me to a more modern WIN32 API tutorial, I would be infinitely thankful.)

Dialog Box section of the Resource Script:

1
2
3
4
5
6
7
8
9
IDD_ABOUT_POPUP DIALOG DISCARDABLE 0, 0, 239, 66		//About menuitem dialog popup declaration
Style DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
Caption "Winsock"
Font 8, "MS SANS SERIF"
{
	DEFPUSHBUTTON 	"&OK" IDOK, 174, 18, 50, 14
	GROUPBOX		"About this program...", IDC_STATIC, 7, 7, 225, 52
	CTEXT			"This program was made by Harley Lorenzo with Dev-C++", IDC_STATIC, 16, 18, 144, 33
}


The second line is the one with the syntax error.
I took your resource script from your first post and dumped it into Resedit (http://www.resedit.net/) and it moaned about the following things:

 
IDI_ICON ICON "App_Icon.ico"     // Need quotes around App_Icon.ico 


and

 
IDD_ABOUT_POPUP DIALOG DISCARDABLE 0, 0, 239, 66   // Get rid of the trailing comma - which you've already done in your last post 


I also added a comma here although it did accept it without:
 
DEFPUSHBUTTON 	"&OK", IDOK, 174, 18, 50, 14    // See the comma after "&OK" 


Once I'd fixed those it parsed perfectly fine.

One other thing I noticed in your code was this:
1
2
3
	if((Winsock2_32) == 0) {
		DestroyWindow(hwnd);
	}


which should be this:

1
2
3
	if(Winsock2_32() == 0) {
		DestroyWindow(hwnd);
	}


I would recommend using something like Resedit to create/edit your resource files instead of writing them manually. There's nothing to stop you editing them by hand but at least Resedit will parse it for you and show you where any errors are.

As for tutorials, the Win32 API hasn't changed much over the years so most of the tutorials out there will still be relevant. MSDN is always a good place to start:
http://msdn.microsoft.com/en-us/library/vstudio/bb384843.aspx
http://msdn.microsoft.com/en-us/library/ff381409(v=vs.85).aspx

I would highly recommend getting a good book. Petzold's "Programming Windows" is probably the most widely accepted one for learning raw Win32. It's old but much of it is still relevant today.

I notice you're using Dev-C++ as your IDE. If you have the Bloodshed version, I would highly recommend ditching it as it comes with an out of date compiler and it hasn't been updated in years. Orwell's Dev C++ is a decent alternative, as is Code::Blocks or even Visual Studio express edition. There are numerous threads on this subject so have a mooch around here and I'm sure you'll find something.
Last edited on
I've already tried Resedit, and it just didn't work for me. And, I mean, AT ALL! It proved to be more than a headache, and since I keep all my C++ projects, I can always go back to the projects and correct my errors on my newer projects by referencing them.

I was using the Orwell update already, so yeah.

I am getting that Petzold book as a PDF right now. I was using The Forger's WIN32 API tutorial, and that was what messed me all up. I have a feeling that maybe it isn't accurate.

(On a side note, I hate Microsoft, so in no way in hell will I be learning any coding from them. The only reason I am using a windows computer is because I have no alternative. I had no computer for 6 years, and no internet for 8, so this is my savior. (Using other people's internet)).

Thanks for correcting the one slight error I made in the Winsock2_32 function call. I can't believe I made that, and the IDE let me get away with that!

But, as for the resource script, you only corrected me on lines I DID NOT ask you to help me with. I was getting an error on the second line, everything else was fine. (Still not compiling.)
Not second line, my mistake. The style line of the dialog box. Which should be line 19, I think.
Topic archived. No new replies allowed.