Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations biv343 on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

CreateDialog Dies. 2

Status
Not open for further replies.

LyMc

Programmer
Jun 3, 2003
84
US
The code:

Code:
#include "stdafx.h"
#include "GroundZero.h"
#include <stdio.h>
#include <commctrl.h>
#include <htmlhelp.h>
#define MAX_LOADSTRING 100

// Global Variables:
static HWND	hDlg		= NULL;
HINSTANCE	hInst;	
TCHAR		szTitle	[MAX_LOADSTRING];	
TCHAR		szWindowClass	[MAX_LOADSTRING];
TCHAR		szVersion	[MAX_LOADSTRING];
Options		opts;

// Forward declarations of functions included in this code module:
BOOL	CALLBACK	Wnd1Proc(HWND, UINT, WPARAM, LPARAM);
BOOL	CALLBACK	Wnd2Proc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain (
			HINSTANCE	hInstance,
			HINSTANCE	PrevInstance,
			LPTSTR		lpCmdLine,
			int		nCmdShow
			)
{
	MSG		msg;
	HACCEL		hAccelTable;
	WNDCLASSEX	wcex;

	// Initialize global strings
	LoadString (hInstance, IDS_APP_TITLE,		szTitle, MAX_LOADSTRING);
	LoadString (hInstance, IDC_GROUNDZERO,		szWindowClass, MAX_LOADSTRING);
	LoadString (hInstance, IDS_VERSION,			szVersion, MAX_LOADSTRING);
	sprintf (szTitle, &quot;%s v%s&quot;, szTitle, szVersion);

	// Set up the class:
	wcex.cbSize		= sizeof (WNDCLASSEX);
	wcex.style		= CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc	= (WNDPROC) Wnd1Proc;
	wcex.cbClsExtra		= 0;
	wcex.cbWndExtra		= 0;
	wcex.hInstance		= hInstance;
	wcex.hIcon		= LoadIcon (hInstance, (LPCTSTR) IDI_GROUNDZERO);
	wcex.hCursor		= LoadCursor (NULL, IDC_ARROW);
	wcex.hbrBackground	= (HBRUSH) (COLOR_WINDOW+1);
	wcex.lpszMenuName	= (LPCTSTR) IDC_GROUNDZERO;
	wcex.lpszClassName	= szWindowClass;
	wcex.hIconSm		= LoadIcon (wcex.hInstance, (LPCTSTR) IDI_SMALL);
	RegisterClassEx (&wcex);

	// Perform application initialization:
	hInst = hInstance;
	hAccelTable = LoadAccelerators (hInstance, (LPCTSTR) IDC_GROUNDZERO);
	InitOpts (&opts);
	for (bool phase = true; true; phase = !phase) {
		opts.back = false;
		if ((hDlg = [red]CreateDialog[/red] (hInst, MAKEINTRESOURCE (phase ? IDD_DLG1 : IDD_DLG2), 
					NULL, (DLGPROC) (phase ? Wnd1Proc : Wnd2Proc))) == NULL) {
			ErrBox (MB_OK, &quot;Error creating dialog %d.&quot;, phase);
			exit (0);
		}
		ShowWindow (hDlg, SW_SHOW);
		ErrBox (MB_OK, &quot;Dialog should have shown by now.&quot;);
		while (GetMessage (&msg, NULL, 0, 0)) {
			if (!IsWindow (hDlg) || !IsDialogMessage (hDlg, &msg)) {
				if (!TranslateAccelerator (msg.hwnd, hAccelTable, &msg)) {
					TranslateMessage (&msg);
					DispatchMessage (&msg);
				}
			}
		}
		if ((phase && opts.immediate) ||
		   (!phase && (opts.immediate || !opts.back))) break;
	}
	ExitOut (&opts);
	return (int) msg.wParam;
}

Note that either of two dialogs can be called: first one, and then when it exits, another. The problem is the first dialog: the program processes until it enters the CreateDialog statement, and the program quietly dies inside it. Several calls are made on the dialog handler, but the window never appears. Note that it is the only window being used; there is no normal &quot;main&quot; window. This does not happen on my development machine; it works fine. It only happens on a clean install. I'm using Windows XP Pro, and MSVS.net as a compiler. Any ideas?
 
put this function in your code, and after you you see something wrong, use this function to see what happens:
int _show_last_error_a()
{
char* x = 0;
FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
0,
(char*)&x,
0,
NULL
);
MessageBoxA(0, x, &quot;error:&quot;, MB_ICONEXCLAMATION);
//delete[] x;
return 0;
}

If you use no windows, only dialogs you can change the program to:

#include &quot;stdafx.h&quot;
#include &quot;GroundZero.h&quot;
#include <stdio.h>
#include <commctrl.h>
#include <htmlhelp.h>
#define MAX_LOADSTRING 100

// Global Variables:
static HWND hDlg = NULL;
HINSTANCE hInst;
TCHAR szTitle [MAX_LOADSTRING];
TCHAR szWindowClass [MAX_LOADSTRING];
TCHAR szVersion [MAX_LOADSTRING];
Options opts;

// Forward declarations of functions included in this code module:
BOOL CALLBACK Wnd1Proc(HWND, UINT, WPARAM, LPARAM);
BOOL CALLBACK Wnd2Proc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY _tWinMain (
HINSTANCE hInstance,
HINSTANCE PrevInstance,
LPTSTR lpCmdLine,
int nCmdShow
)
{
HACCEL hAccelTable;

// Initialize global strings
LoadString (hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString (hInstance, IDC_GROUNDZERO, szWindowClass, MAX_LOADSTRING);
LoadString (hInstance, IDS_VERSION, szVersion, MAX_LOADSTRING);
sprintf (szTitle, &quot;%s v%s&quot;, szTitle, szVersion);


hInst = hInstance;
hAccelTable = LoadAccelerators (hInstance, (LPCTSTR) IDC_GROUNDZERO);
InitOpts (&opts);
for (bool phase = true; true; phase = !phase)
{
opts.back = false;
if ((hDlg = CreateDialog(hInst, MAKEINTRESOURCE (phase ? IDD_DLG1 : IDD_DLG2),
NULL, (DLGPROC) (phase ? Wnd1Proc : Wnd2Proc))) == NULL)
{
ErrBox (MB_OK, &quot;Error creating dialog %d.&quot;, phase);
exit (0);
}
ShowWindow (hDlg, SW_SHOW);

if ((phase && opts.immediate) ||
(!phase && (opts.immediate || !opts.back))) break;
}
ExitOut (&opts);
return (int) msg.wParam;
}



Ion Filipski
1c.bmp

ICQ: 95034075
AIM: IonFilipski
filipski@excite.com
 
Ion,

I applied the changes you recommended. Unfortunately, if I delete the message loop, the program throws the dialog onto the screen (on my development machine), and then immediately exits. So I left the message loop code in, deleting only the class registration.

So, I have this:
Code:
	...
	InitOpts (&opts);
	for (bool phase = true; true; phase = !phase) {
		opts.back = false;
_show_last_error_a();
		if ((hDlg = CreateDialog (hInst, MAKEINTRESOURCE (phase ? IDD_DLG1 : IDD_DLG2), 
					NULL, (DLGPROC) (phase ? Wnd1Proc : Wnd2Proc))) == NULL) {
			ErrBox (MB_OK, &quot;Error creating dialog %d.&quot;, phase);
			exit (0);
		}
_show_last_error_a();
		ShowWindow (hDlg, SW_SHOW);
		while (GetMessage (&msg, NULL, 0, 0)) {
			if (!IsWindow (hDlg) || !IsDialogMessage (hDlg, &msg)) {
				if (!TranslateAccelerator (msg.hwnd, hAccelTable, &msg)) {
					TranslateMessage (&msg);
					DispatchMessage (&msg);
				}
			}
		}
		if ((phase && opts.immediate) ||
		   (!phase && (opts.immediate || !opts.back))) break;
	}
	...

On the user machine, there is no error immediately before the CreateDialog, and it never returns from it. On the development machine, when it returns, the dialog is on the screen and I get a &quot;Access denied&quot; message from your dialog (it appears that I can get rid of the ShowWindow call anyway). It sounds like I may be onto something there, but what exactly is being accessed in the CreateDialog that causes denial? I do some file reading in the InitOpts call, but that is well passed when I see no error before CreateDialog.

 
does CreateDialog return NULL? If yes, no dialog is created. In this case you could have some errors in dialog procs.

Ion Filipski
1c.bmp

ICQ: 95034075
AIM: IonFilipski
filipski@excite.com
 
No - I never see the ErrBox reporting a problem come up either on the development or the user machines.
 
put a MessageBox inside DlgProc at the first line and see if it enters the dialog proc.

Ion Filipski
1c.bmp

ICQ: 95034075
AIM: IonFilipski
filipski@excite.com
 
If it is useful, here is the Wnd1Proc routine:


Code:
BOOL CALLBACK Wnd1Proc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)			// Page 1.
{
	HDC				hdc;
	PAINTSTRUCT		ps;
	char			buffer			[20];

	if (message == opts.abortID) {
shutdown:
		opts.immediate = true;
quit:	DestroyWindow (hWnd);
	} else
		switch (message) {

		case WM_INITDIALOG:
			DisplayOpts (hWnd, &opts);
			break;

		case WM_COMMAND:
			switch (LOWORD (wParam)) {
			case IDC_INSERT:
				opts.a.insert = !opts.a.insert;
				DisplayOpts (hWnd, &opts);
				break;
			case IDC_ENGLISH:
				opts.a.metric = false;
				DisplayOpts (hWnd, &opts);
				break;
<other similar command handlers for controls>
			case IDCANCEL:
				goto shutdown; 
			case IDOK:	
				goto quit;
			case IDHELP:
				HtmlHelp (GetDesktopWindow(), HELPNAME, HH_DISPLAY_TOPIC, NULL);	
				break;
			}
			break;

		case WM_PAINT:
			hdc = BeginPaint (hWnd, &ps);
			DrawOpts (hdc, 1, &opts);
			EndPaint (hWnd, &ps);
			break;

		case WM_DESTROY:
			PostQuitMessage (0);
			break;
		}
	return 0;
}
 
first of all never use goto. C++ has other programming style than VB. I never analyze code which contains the goto instruction. You have a lot of ways to not use goto. If one of my students use goto then he does not pass the exam, even his code could be genially structured.

Change your code. If after changes it does not work, put it there in the forum.

Ion Filipski
1c.bmp

ICQ: 95034075
AIM: IonFilipski
filipski@excite.com
 
As you wish:

Code:
BOOL CALLBACK Wnd1Proc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)            // Page 1.
{
    HDC                hdc;
    PAINTSTRUCT        ps;
    char            buffer            [20];

    if (message == opts.abortID) {
        opts.immediate = true;
        DestroyWindow (hWnd);
    } else
        switch (message) {

        case WM_INITDIALOG:
            DisplayOpts (hWnd, &opts);
            break;

        case WM_COMMAND:
            switch (LOWORD (wParam)) {
            case IDC_INSERT:
                opts.a.insert = !opts.a.insert;
                DisplayOpts (hWnd, &opts);
                break;

            case IDC_ENGLISH:
                opts.a.metric = false;
                DisplayOpts (hWnd, &opts);
                break;

<other similar command handlers for controls>

            case IDCANCEL:
                opts.immediate = true;
                DestroyWindow (hWnd);
                break;

            case IDOK:    
                DestroyWindow (hWnd);
                break;

            case IDHELP:
                HtmlHelp (GetDesktopWindow(), HELPNAME, HH_DISPLAY_TOPIC, NULL);    
                break;
            }
            break;

        case WM_PAINT:
            hdc = BeginPaint (hWnd, &ps);
            DrawOpts (hdc, 1, &opts);
            EndPaint (hWnd, &ps);
            break;

        case WM_DESTROY:
            PostQuitMessage (0);
            break;
        }
    return 0;
}

The code still acts as described above. And, yes, I did place a message box call in Wnd1Proc, and it is getting calls before the Create Dialog dies. I see messages 28 and 85, with error codes 1400 and 1421 (and 0). I reckon the 1400's are complaining about the NULL for the parent window to the CreateDialog call (should I use something else?), but I don't know what the 1421 &quot;Control ID&quot; is.
 
put a MessageBox at the first line in each message handler and see shich one is executed.
When you localize the handler, go on with messageboxes for each line to see which one fails.

Ion Filipski
1c.bmp

ICQ: 95034075
AIM: IonFilipski
filipski@excite.com
 
OK, I message-boxed the heck out of it. I found that I got a flurry (6-8) messages of type decimal 28 (WM_ACTIVATEAPP) and 48 (WM_SETFONT), neither of which are caught; the last error code is 0. Then a final WM_DESTROY with an error code set to 1407, &quot;Cannot find window class&quot;. So, no code of mine is getting executed in the dialog proc handler (except the message boxes); presumably the error is coming out of CreateDialog in response to its arguments and/or environment. We deleted the window class setting the first message - is that what's is being complained about?
 
Essencially is what DialogBox is created, and now something inside DialogProc.
By the way, if you have processed the message you should return TRUE instead of break....->..return 0

In my opinion it seems a little like you use a control in the dialog, which is absent on the target operation system.

Ion Filipski
1c.bmp

ICQ: 95034075
AIM: IonFilipski
filipski@excite.com
 
are you using common controls?

remember to call InitCommonControls() before you try to create your dialog
 
>Skute
have you read attentive LyMc's posts?
In the first post you can find this:
> This does not happen on my development machine

Ion Filipski
1c.bmp

ICQ: 95034075
AIM: IonFilipski
filipski@excite.com
 
And that, my friends, did it. Adding the call to InitCommonCtrlsEx fixed the problem. Why wasn't it needed on the development machine? While adding the call I had to add the common controls library to the linker list. Ah, well, you (I) learn somthing new every day.

Thank you, Skute, for the final hint, and thank you, Ion, for sticking with me on this. I learned from both.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top