no-messages to WindowProc()

Started by
10 comments, last by Ninja_Mouse 19 years, 3 months ago
Hi there - I am a noob to C++ and was hoping someone could help me out. I have been reading "Programming Role Playing Games with DirectX 9" by Jim Adams and can't seem to replicate some of his code (I'm using Visual Studio .NET 2002). The problem - If I use the CreateWindow() function (for the main window) everything is fine, but if I use the CreateDialog() function to make a window from a dialog resource I get my problem. The window from CreateDialog() appears fine but the WindowProc function is never called and thus I can't catch any messages. I don't know if it is because I haven't set up the dialog resource correctly. If I run the source code from the book's CD (which is the code I just copied word for word and couldn't run) then it runs fine. But if I add a dialog resource and then alter the CreateDialog() function to run my dialog rather than the one they made I get the same no-messages problem. If anyone has any ideas on solving my no-messages with CreateDialog() problem please let me know. Thanks in advance, Farran
Advertisement
Depends... You usually specify dialog's procedure in the CreateDialog function, but if the dialog is meant to be the main window, you usually register a class for the given dialog and you specify your dialog procedure there... You also have to specify the name of the window class in the DIALOG resouce.

Could you post some code, please? [smile]

Oxyd
Soz, I don't know how to put the code in those little boxes, but here it is:

#include <windows.h>
#include <stdio.h>
#include "resource.h"

// Application variables ////////////////////////
HWND g_hWnd; // Window handle
char g_szClass[] = "KeyboardDemo"; // Class name

// Application prototypes ///////////////////////
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow);
LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

// Application //////////////////////////////////
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow)
{
WNDCLASS wc;
MSG Msg;
char KeyStateBuffer[256];

// Register window class
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = DLGWINDOWEXTRA;
wc.hInstance = hInst;
wc.hIcon = LoadIcon(hInst, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClass;
RegisterClass(&wc);

// Create the dialog box window and show it
g_hWnd = CreateDialog(hInst, MAKEINTRESOURCE(IDD_KB), 0, NULL);
ShowWindow(g_hWnd, nCmdShow);
UpdateWindow(g_hWnd);

ZeroMemory(&Msg, sizeof(MSG));
while(Msg.message != WM_QUIT) {

// Handle Windows messages (if any)
if(PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}

// Clean up
UnregisterClass(g_szClass, hInst);

return 0;
}

LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg) {
case WM_DESTROY:
PostQuitMessage(0);
break;

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

return 0;
}
You can put your code inside the box using:

[source]
Your code...
[/source]

The code looks fine to me... Are you sure you have your dialog resource like:

IDD_KB DIALOG DISCARDABLECLASS "KeyboardDemo"


You have to specify the dialog class in the resource file.

Oxyd
Is your dialog box set-up as a Popup window (because VS defaults to Child, which means you'd have to do some more message passing jiggery-pokery).

Jim.
I am a bit lost here. I have checked in the resource properties under "Class Name" and it is greyed out on both my dialog and the book's dialog.

I literally created a dialog and changed the ID, and nothing more. I would see that the class name would need to be associated with the dialog as when you use CreateWindow() you have to specify the class name, but don't when using CreateDialog().

In regards to your question about "IDD_KB DIALOG DISCARDABLE" - I don't know where I would find that info.

In regards to the dialog's class name, how do I go about defining that? Or if I am asking that am I far from beaten path and should hide my head in shame?
Jim, I have tried my dialog as pop-up and overlapped (both didn't work). The book's dialog has it set as overlapped.
Oops, I missed something sort of obvious.

In your CreateDialog call, you never request the dialog to be attached to a wndproc procedure (the fourth parameter). Change:

g_hWnd = CreateDialog(hInst, MAKEINTRESOURCE(IDD_KB), 0, NULL);

to:

g_hWnd = CreateDialog(hInst, MAKEINTRESOURCE(IDD_KB), 0, WindowProc);

and see if that works.

Jim.
Jim, I gave that a try but the fourth parameter in the CreateDialog() function requires a DLGPROC function, rather than a WNDPROC function.

I did try casting the WindowProc function as WNDPROC and I also gave changing the WindowProc function to DlgProc, but both resulted in the same thing. It would show the window and the messages were coming through (finally!), but the window was totally frozen (downer!).

Hmm, any ideas from here?
Yeah, there is a slightly different formulation for a dialogproc - sorry, that slipped my mind.

OK - I'm gonna post some of my own code - I'll try and cut out the extraneous bits (so this code probably won't work as written), and leave in the bits that are relevant - see if they help you. I'll be honest - I've always used a main window created from CreateWindow and then added dialog boxes, so I'm a little on shaky ground, but I'm assuming that you can create self-standing dialogs (cos your book says so).

OK - so heres a WinMain function:

// Includes// Forward declaration of main wndproc procedureLRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow){// Define main window class	static TCHAR szAppName[] = TEXT("CakeOrDeath");	HWND hWnd;	MSG msg;	WNDCLASS wndClass;	wndClass.style = CS_HREDRAW | CS_VREDRAW;	wndClass.lpfnWndProc = WndProc;	wndClass.cbClsExtra = 0;	wndClass.cbWndExtra = 0;	wndClass.hInstance = hInstance;	wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);	wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);	wndClass.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);	wndClass.lpszMenuName = NULL;	wndClass.lpszClassName = szAppName;// Register window and add menu	if(!RegisterClass(&wndClass))	{		return 0;	}	HMENU hMenu = LoadMenu(hInstance, MAKEINTRESOURCE(IDR_MENU1));// Create window	hWnd = CreateWindow(		szAppName,		"CakeOrDeath",		WS_OVERLAPPEDWINDOW,		CW_USEDEFAULT,		CW_USEDEFAULT,		CW_USEDEFAULT,		CW_USEDEFAULT,		NULL,		hMenu,		hInstance,		NULL);// Usual windows loop gumf - note this uses GetMessage and not PeekMessage, which would be more usual for games	ShowWindow(hWnd, iCmdShow);	UpdateWindow(hWnd);	while(GetMessage(&msg, NULL, 0, 0))	{		TranslateMessage(&msg);		DispatchMessage(&msg);	}	return static_cast<int>(msg.wParam);}// Main windows procedureLRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){	static HINSTANCE hInstance;	switch(message)	{	case WM_CREATE:		hInstance = ((LPCREATESTRUCT) lParam)->hInstance;		break;	case WM_DESTROY:		PostQuitMessage(0);		return 0;// All my dialog boxes are created using DialogBox, instead of CreateDialog// All are activated from main window Menu - hence use of WM_COMMAND	case WM_COMMAND:		switch(LOWORD(wParam))		{		case ID_INGREDIENT_ADDNEWINGREDIENT:			DialogBox(hInstance, MAKEINTRESOURCE(IDD_ADDNEWINGREDIENT), hWnd, AddNewIngredientProc);			return 0;		case ID_INGREDIENT_EDITINGREDIENTS:// First create listbox to identify ingredient to be selected// Then allow editing of ingredient			if(DialogBox(hInstance, MAKEINTRESOURCE(IDD_EDITINGREDIENTLISTBOX), hWnd, EditIngredientListBoxProc))				DialogBox(hInstance, MAKEINTRESOURCE(IDD_ADDNEWINGREDIENT), hWnd, EditIngredientProc);			return 0;		case ID_RECIPES_ADDNEWRECIPE:			DialogBox(hInstance, MAKEINTRESOURCE(IDD_ADDNEWRECIPE), hWnd, AddNewRecipeProc);			return 0;		case ID_RECIPES_REVIEWRECIPES:			DialogBox(hInstance, MAKEINTRESOURCE(IDD_REVIEWRECIPES), hWnd, ReviewRecipesProc);			return 0;		case ID_CONVERSIONTABLES_ADDNEWUNIT:			DialogBox(hInstance, MAKEINTRESOURCE(IDD_ADDNEWCONVERSIONUNIT), hWnd, AddNewConversionUnitProc);			return 0;		case ID_CONVERSIONTABLES_EDITCONVERSIONS:			DialogBox(hInstance, MAKEINTRESOURCE(IDD_EDITCONVERSIONTABLE), hWnd, EditConversionTableProc);		}	}	return DefWindowProc(hWnd, message, wParam, lParam);}


Next I've got a specific example of a dialog box callback:

//Note the slightly different signature....BOOL CALLBACK AddNewIngredientProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam){	char itemName[255];	char itemUnit[255];	unsigned int itemCost = 0;	char itemWeight[255];	std::string thisUnit;	HWND hWndList;	int i = 0;	switch(message)	{	case WM_INITDIALOG:		hWndList = GetDlgItem(hDlg, IDC_COMBO1);		ConversionTable::Instance()->SetCurrentUnit(0);// Sets up amount units		while(1)		{			thisUnit = ConversionTable::Instance()->GetCurrentUnit();			SendMessage(hWndList, CB_ADDSTRING, 0, (LPARAM) thisUnit.c_str());			SendMessage(hWndList, CB_SETITEMDATA, i, (LPARAM) i);			++i;// Check to see if we've reached the end of the list			if(!ConversionTable::Instance()->DoesNextUnitExist())				break;		}// Set up default amount		SendDlgItemMessage(hDlg, IDC_COMBO1, CB_SETCURSEL, 0, 0);		SetFocus(GetDlgItem(hDlg, IDC_EDITINGREDIENTNAME));		return true;	case WM_COMMAND:		switch(LOWORD(wParam))		{		case IDCLOSE:			IngredientManager::Instance()->SaveIngredients();			EndDialog(hDlg, 0);			return true;		case IDSAVE:			itemCost = GetDlgItemInt(hDlg, IDC_EDITINGREDIENTCOST, NULL, false);			GetDlgItemText(hDlg, IDC_COMBO1, &itemUnit[0], 255);			if(GetDlgItemText(hDlg, IDC_EDITINGREDIENTNAME, &itemName[0], 255) &&				itemCost &&				GetDlgItemText(hDlg, IDC_EDITINGREDIENTWEIGHT, &itemWeight[0], 255)				)			{				IngredientManager::Instance()->AddNewIngredient(itemName, itemCost, itemWeight, itemUnit);				SetDlgItemText(hDlg, IDC_EDITINGREDIENTNAME, " ");				SetDlgItemText(hDlg, IDC_EDITINGREDIENTCOST, " ");				SetDlgItemText(hDlg, IDC_EDITINGREDIENTWEIGHT, " ");				SetFocus(GetDlgItem(hDlg, IDC_EDITINGREDIENTNAME));			}			return true;		default:			return false;		}	default:		return false;	}}


The key point I think here is to change your callback function signature to BOOL CALLBACK instead of LRESULT CALLBACK.

So - let's see if that works!
Jim.

Edit : or do what the AP says, which will probably circumvent my stumbling!

This topic is closed to new replies.

Advertisement