Win32 Modeless Dialog is being a jerk.

Started by
11 comments, last by BrickInTheWall 14 years ago
Hi guys, I'm going apeshit over a modeless dialog I'm trying to create. I don't know what I'm doing wrong but it's completely breaking my application. It's just supposed to be an about-box with an ok button, but nooo, the "Ok" button doesn't even show, and the whole program acts weird. I created a template in memory rather than use a resource since I don't have an editor and I'd like to learn how they are built. I tested the template in modal mode using DialogBoxIndirect and everything worked fine. Now I use CreateDialogIndirect and add a few changes and everything screws up, and I don't know why. here is my WndProc function in main.cpp:

...

// Global handles.
HWND hDlgHelpAbout = NULL;

...

// Window Procedure function definition.
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
		case WM_CREATE:
			// Create the menu.
			initMenu(hWnd);
		break;

		case WM_COMMAND:
		{
			switch (LOWORD(wParam))
			{
				case ID_HELP_ABOUT:
					if (!IsWindow(hDlgHelpAbout))
					{
						// Create "About" dialog.
						LPDLGTEMPLATE lpDlgTemp = createHelpAbout(hWnd);
						hDlgHelpAbout = CreateDialogIndirect(GetModuleHandle(NULL), lpDlgTemp, hWnd, (DLGPROC)helpAboutProc);
						GlobalFree(lpDlgTemp);

						// Show it too.
						ShowWindow(hDlgHelpAbout, SW_SHOW);
					}
					break;
				case ID_FILE_EXIT:
					PostMessage(hWnd, WM_CLOSE, 0, 0);
					break;
			}
		}
		break;

		case WM_CLOSE:
			DestroyWindow(hWnd);
			break;

		case WM_DESTROY:
			DestroyWindow(hDlgHelpAbout);
			PostQuitMessage(0);
			break;

		default:
			return DefWindowProc(hWnd, msg, wParam, lParam);
	}

	return 0;
}
and here are the function I use to create the template and the dialogs procedure function (in another .cpp file):

#include <windows.h>
#include "ids.h"
#include "dialogTemplate.h"
#include "dialogFunctions.h"

BOOL CALLBACK helpAboutProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch (msg)
	{
		case WM_COMMAND:
			switch (LOWORD(wParam))
			{
				case IDOK:
					DestroyWindow(hWnd);
					return TRUE;
			}

		case WM_DESTROY:
			PostQuitMessage(0);
			return TRUE;

		case WM_CLOSE:
			DestroyWindow(hWnd);
			return TRUE;
	}

	return FALSE;
}

LPDLGTEMPLATE createHelpAbout(HWND hWnd)
{
	// Handle to the memory.
	HANDLE hGlobal = GlobalAlloc(GMEM_ZEROINIT, 1024);

	LPWORD lpw = createDlgHeader(hGlobal, "About", DS_SETFONT | DS_CENTER | DS_3DLOOK | WS_POPUP | WS_SYSMENU | DS_MODALFRAME | WS_CAPTION, 1, 8, "MS Sans Serif", 0, 0, 319, 47);
	lpw = createDlgCtrl(lpw, BUTTON_CLASS, IDOK, "Ok", WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_DEFPUSHBUTTON, 264, 7, 48, 15);

	return (LPDLGTEMPLATE)hGlobal;
}
I know I should be setting hDlgHelpAbout to NULL in the WM_CLOSE of the dialogs procedure, but I'll take care of that later, that can't be the problem. That should only hinder it from being created again. Also, the close buttons (the "X") doesn't work either. Anyone know why this might be? Cheers
Fate fell short this time your smile fades in the summer.
Advertisement
Need to see where you call CreateDialog() and your message loop. Also you should put a "return FALSE;" after the switch statement in the WM_COMMAND handler in helpAboutProc().
To do a modeless dialog right you almost need to launch it from a separate thread.
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes." - the Laughing Man
My message loop:

	while (GetMessage(&msg, hWnd, 0, 0) > 0)	{		if (!IsDialogMessage(hDlgHelpAbout, &msg))		{			TranslateMessage(&msg);			DispatchMessage(&msg);		}	}



I call CreateDialogIndirect in the case ID_HELP_ABOUT of my main windows procedure function. Thanks for the heads up about the return FALSE.
Fate fell short this time your smile fades in the summer.
I don't know what's wrong with it from what you've shown -- I've never done the thing you do in which you create a template in memory. I've actually never even heard of doing that.

I guess if I were you I'd try commenting out the !IsDialogMessage() and just a do a regular Translate and Dispatch message loop and I'd comment out everything in the dialog procedure and just return FALSE and then see if I got different behavior. I guess if that doesn't change the behavior then the problem has to be in createDlgHeader or createDlgCtrl, even though they worked with the modal DialogBox() case.

If you're doing things the way you are for learning purposes fine, but if you just want to make a modeless "about box" without using a resource editor, there are easier ways to do it than building your own DLGITEMTEMPLATE. Either (a) don't use an official dialog box -- just make a custom window class with whatever controls you need on it with a few calls to CreateWindow or (b) define a dialog in a .rc file without using a resource editor (VC++ Express still compiles .rc files even though it doesn't have a visual resource editor)

[Edited by - jwezorek on April 16, 2010 7:41:35 PM]
Quote:Original post by jwezorek
I don't know what's wrong with it from what you've shown -- I've never done the thing you do in which you create a template in memory. I've actually never even heard of doing that.



I did it once, and it's insane. Of course I did it a long time ago, maybe the process by which to do it has gotten easier.

What the OP needs to do to debug this is to design an equivalent dialog in the resource editor, load the resource into memory, and then do a memcmp to make sure that it's actually the same.
Quote:Original post by cache_hit
Quote:Original post by jwezorek
I don't know what's wrong with it from what you've shown -- I've never done the thing you do in which you create a template in memory. I've actually never even heard of doing that.



I did it once, and it's insane. Of course I did it a long time ago, maybe the process by which to do it has gotten easier.

What the OP needs to do to debug this is to design an equivalent dialog in the resource editor, load the resource into memory, and then do a memcmp to make sure that it's actually the same.

And since that requires a resource editor... just use the resource instead of doing it by hand.

In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.

Quote:Original post by cache_hit
I did it once, and it's insane.


Out of curiosity, what was the context? Did you have to do it for a reason or was it just Win32 spelunking?
A few tiny mistakes:

1)
The main problem: Remove the HWND in your message loop. Pass NULL instead. Otherwise you only process messages of the main window.

2)
Move the return DefWindowProc OUT OF THE DEFAULT CASE AFTER THE SWITCH.

3)
You're calling PostQuitMessage twice, one in the main window close, one in the modeless dialog proc.

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

Quote:Original post by Endurion
A few tiny mistakes:

1)
The main problem: Remove the HWND in your message loop. Pass NULL instead. Otherwise you only process messages of the main window.

2)
Move the return DefWindowProc OUT OF THE DEFAULT CASE AFTER THE SWITCH.

3)
You're calling PostQuitMessage twice, one in the main window close, one in the modeless dialog proc.


Where his DefWindowProc call is shouldn't be a problem. If he handles a message he calls break which falls to return 0. Otherwise, it calls DefWindowProc (for message he doesn't handle.) Unless I missing something.

This topic is closed to new replies.

Advertisement