[MSVC++] Reacting on events (strange bug now)

Started by
10 comments, last by GameDev.net 18 years ago
Hello everybody, I just recently got into windows programming using the Microsoft Visual C++ 6.0 compiler. First of all, I'll need to tell you how I have everything set up and then I'll demonstrate you my current problem. So, I have added an ".rc"-resource to my project. In this resourcce file, I added two dialogs (one called "IDDFORMLOGIN" and the other is named "IDDFORMMAIN"). I added all kinds of controls (labels, groups, buttons etc.) on those dialogs with the editor in MSVC++ 6. That all works fine. This is the way my source code looks right now:

// BarcodeDemo.cpp

#include "stdafx.h"
#include "windows.h"
#include "Resource.h"


HWND hWnd;
HINSTANCE hInstance;

LRESULT CALLBACK FormLoginProc ( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam );
LRESULT CALLBACK FormMainProc ( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam );

INT WINAPI WinMain ( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
	DialogBox ( hInstance, MAKEINTRESOURCE ( IDD_FORMLOGIN ), hWnd, reinterpret_cast<DLGPROC> ( FormLoginProc ) );
	return FALSE;
}


LRESULT CALLBACK FormLoginProc ( HWND hWndDlg, UINT Msg, WPARAM wParam, LPARAM lParam )
{
	switch ( Msg )
	{
		case WM_INITDIALOG:
			return TRUE;
		break;

		case WM_CLOSE:
			EndDialog ( hWndDlg, 0 );
			DialogBox ( hInstance, MAKEINTRESOURCE ( IDD_FORMMAIN ), hWnd, reinterpret_cast<DLGPROC> ( FormMainProc ) );
		break;
	}

	return FALSE;
}

LRESULT CALLBACK FormMainProc ( HWND hWndDlg, UINT Msg, WPARAM wParam, LPARAM lParam )
{
	switch ( Msg )
	{
		case WM_INITDIALOG:
			return TRUE;
		break;

		case WM_CLOSE:
			EndDialog ( hWndDlg, 0 );
		break;
	}

	return FALSE;
}




This shows the first dialog (IDDFORMLOGIN), and then - after the user closes this dialog, it displays the second one (IDDFORMMAIN). I want to change this behaviour. I need to close the first dialog when the user presses a button on the first one. The problem is, I don't have any idea how to react to a button press. I searched through the MSDN and everything, but really didn't manage to find anything nearly useful. Also, I wonder if this is really the best way to achieve what I want. I basically need to display a first window with several controls on it, that allow you to log in using a username and a password. Then when the user clicks on the "log in" button, I want it to change to a second window with other controls, labels etc. on it. Do I need a new dialog for every of those "screens"? Thanks ahead of time, and make sure to ask if something is unclear to you. I am really new to this windows programming. [Edited by - d h k on March 26, 2006 6:28:43 AM]
Advertisement
normally what you do for modal dialogs is (below is from the dialog proc):

case(WM_COMMAND) :    {     switch(LOWORD(wparam)) {       case(IDOK) :            EndDialog(window, IDOK);            return TRUE;       case(IDCANCEL) :            EndDialog(window, IDCANCEL);            return TRUE;       case(IDOFSOMEOTHERBUTTON) :            EndDialog(window, IDCANCEL (or IDOK or IDOFSOMEOTHERBUTTON));            return TRUE;      }     return FALSE;    }


also, instead of starting the second dialog from the first's dialog procedure, you should start it from WinMain. You also don't need reinterpret_cast if you declare your dialog procedure properly, using INT_PTR CALLBACK instead of LRESULT CALLBACK.

INT WINAPI WinMain ( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){ // retval is equal to whatever EndDialog returns, or is -1 if it fails. INT_PTR retval = DialogBox(hInstance, MAKEINTRESOURCE(IDD_FORMLOGIN), GetDesktopWindow(), FormLoginProc); if(retval == IDOK) // if user chose OK, start next dialog    DialogBox(hInstance, MAKEINTRESOURCE(IDD_FORMMAIN), GetDesktopWindow(), FormMainProc); return FALSE;}


As for the rest of the stuff, you have the right idea. Basically you start dialog #1, fill it out, click on IDOK button, and on your WM_COMMAND's IDOK handler you fill out a global buffer storing all the info before you call EndDialog. Then you start the second dialog, using the global buffer info to do whatever.

Another nitpicky thing is that if you don't define your resource names as integers in your resource header... a la #define IDD_FORMMAIN 1000... you can say:

DialogBox(hInstance, "IDD_FORMMAIN", GetDesktopWindow(), FormMainProc);
instead of
DialogBox(hInstance, MAKEINTRESOURCE(IDD_FORMMAIN), GetDesktopWindow(), FormMainProc);

as I never use integer resource handlers for dialogs.

[Edited by - yadango on March 25, 2006 11:08:22 AM]
Thank you very much for your response.. That helped me tons.

It works on my computer perfectly now, but whenever I run this on either one of my two laptops, it just closes after clicking on the "log in" button! They both run the very same Windows XP, too.

How could that happen?

Here is the code again (notice, I didn't include your "nitpicky" stuff just yet):

// BarcodeDemo.cpp#include "stdafx.h"#include "windows.h"#include "Resource.h"HWND hWnd = NULL;LRESULT CALLBACK FormLoginProc ( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam );LRESULT CALLBACK FormMainProc ( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam );INT WINAPI WinMain ( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ){	INT_PTR return_value = DialogBox ( hInstance, MAKEINTRESOURCE ( IDD_FORMLOGIN ), GetDesktopWindow ( ), reinterpret_cast<DLGPROC> ( FormLoginProc ) );	if ( return_value == IDC_LOGINBUTTON )	{		DialogBox ( hInstance, MAKEINTRESOURCE ( IDD_FORMMAIN ), GetDesktopWindow ( ), reinterpret_cast<DLGPROC> ( FormMainProc ) );	} return FALSE;}LRESULT CALLBACK FormLoginProc ( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam ){	switch ( Msg )	{		case WM_COMMAND:		{			switch ( LOWORD ( wParam ) )			{				case IDC_LOGINBUTTON:					EndDialog ( hWnd, IDC_LOGINBUTTON );					return TRUE;				break;			}			return FALSE;		}		case WM_CLOSE:			EndDialog ( hWnd, 0 );			return TRUE;		break;	}	return FALSE;}LRESULT CALLBACK FormMainProc ( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam ){	switch ( Msg )	{		case WM_CLOSE:			EndDialog ( hWnd, 0 );			return TRUE;		break;	}	return FALSE;}


I have no idea what could cause the program to work on my computer while not working (and terminating after clicking the "log in" button instead) on any other system I run this on!
One thing I still see wrong is that you don't have to call EndDialog from within WM_CLOSE. For modal dialogs, you don't have to respond to WM_CLOSE. Try removing WM_CLOSE entirely and instead respond to WM_COMMAND's IDCANCEL. Then let me know if you still get that crash. What might be happening is your EndDialog(IDC_LOGINBUTTON) closes the window first, then on WM_CLOSE your EndDialog(hWndDlg, 0) is trying to close it again. WM_CLOSE is a big no-no for modal dialogs.

case(WM_COMMAND) :    {     switch(LOWORD(wparam)) {       // make IDOK behave like IDC_LOGINBUTTON so that when you       // press the ENTER key it works just like IDC_LOGINBUTTON.       case(IDOK) :       case(IDC_LOGINBUTTON) :            // save login data            EndDialog(window, IDC_LOGINBUTTON);            return TRUE;       case(IDCANCEL) :            EndDialog(window, IDCANCEL);            return TRUE;      }     return FALSE;    }
I just tried out your new code but the problem's still there... It won't work on different systems.

This is the most current source code:

// BarcodeDemo.cpp#include "stdafx.h"#include "windows.h"#include "resource.h"HWND hWnd = NULL;LRESULT CALLBACK FormLoginProc ( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam );LRESULT CALLBACK FormMainProc ( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam );INT WINAPI WinMain ( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow ){	INT_PTR return_value = DialogBox ( hInstance, MAKEINTRESOURCE ( IDD_FORMLOGIN ), GetDesktopWindow ( ), reinterpret_cast<DLGPROC> ( FormLoginProc ) );	if ( return_value == IDC_LOGINBUTTON )	{		DialogBox ( hInstance, MAKEINTRESOURCE ( IDD_FORMMAIN ), GetDesktopWindow ( ), reinterpret_cast<DLGPROC> ( FormMainProc ) );	} return FALSE;}LRESULT CALLBACK FormLoginProc ( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam ){	switch ( Msg )	{		case WM_COMMAND:		{			switch ( LOWORD ( wParam ) )			{				case IDOK:				case IDC_LOGINBUTTON:					EndDialog ( hWnd, IDC_LOGINBUTTON );					return TRUE;				break;				case IDCANCEL:					EndDialog ( hWnd, IDCANCEL );					return TRUE;				break;			}			return FALSE;		}	}	return FALSE;}LRESULT CALLBACK FormMainProc ( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam ){	switch ( Msg )	{		case WM_COMMAND:		{			switch ( LOWORD ( wParam ) )			{				case IDCANCEL:					EndDialog ( hWnd, IDCANCEL );					return TRUE;				break;			}			return FALSE;		}	}	return FALSE;}


Thanks again fro your help so far.
hmmm... it could be lots of things... can you compile and debug the program on the laptop to see if it's the first dialog crashing or the second one as it is loading? Is that your whole dialog code that you posted? Did you strip out the GetDlgItem stuff in WM_INITDIALOG?
Quote:
can you compile and debug the program on the laptop to see if it's the first dialog crashing or the second one as it is loading?


I could do that, but it would take quite some time and I'd really rather not go through the hazzle of this.

Quote:
Is that your whole dialog code that you posted? Did you strip out the GetDlgItem stuff in WM_INITDIALOG?


The code I posted is absolutely everything I have. How should I use the GetDlgItem function in WM_INITDIALOG exactly?

Thanks for your time!
Ok, then if that's all your code and you aren't using GetDlgItem, it still could be a common control crash but I doubt it. Uhm, does this code and EXE crash for you? Very similar to yours but one or two different things. It should still compile on VC6 SP5 if I recall right.

code.
Your application crashes on the computer where my own application works just fine. I didn't know that windows programming could be THIS tricky... ;)
lol! yep. very tricky sometimes. i ran your last code sample exactly as you typed it (but with my own resource files) and it ran fine as well. on your sample program, what does each DialogBox return? Do any return -1? Does GetLastError() return any code? What value are you using for IDC_LOGINBUTTON? these are all things that can effect whether or not the next dialog appears.

This topic is closed to new replies.

Advertisement