Sign in to follow this  

no-messages to WindowProc()

This topic is 4716 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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;
}

Share this post


Link to post
Share on other sites
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 DISCARDABLE
CLASS "KeyboardDemo"


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

Oxyd

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
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 procedure
LRESULT 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 procedure
LRESULT 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!

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Dialogs are different from Windows. A Dialog, which you're creating with "CreateDialog", processes unwanted messages internally. This means that you do not call DefWindowProc in the message loop, as that function is only used for Windows.

Share this post


Link to post
Share on other sites

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

// Application variables ////////////////////////
HWND g_hWnd; // Window handle

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

// Application //////////////////////////////////
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow)
{
MSG Msg;

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

ShowWindow(g_hWnd, nCmdShow);
UpdateWindow(g_hWnd);

// Loop until ESCAPE pressed
ZeroMemory(&Msg, sizeof(MSG));
while(Msg.message != WM_QUIT)
{
// Handle dialog messages (if any)
if(PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
{
if (IsDialogMessage(g_hWnd, &Msg))
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
}
}

return 0;
}

// Dialog message handler
BOOL CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CLOSE:
DestroyWindow (g_hWnd);
return TRUE;
}

return 0;
}



Well, after much jiggling about I have fixed the problem with the source code shown above. I think basically the problem came down to removing the window class (as that isn't needed), and changing the message handling bits to DialogProc. I also found that you can use IsDialogMessage() to find only dialog messages.

Lots of thanks for the help you guys gave. I am still not sure how the project from the book has a main window created from CreateDialog() but uses the WindowProc() messages handler...? One day I will know, one day.

Keep it real,
Ninja Mouse

Share this post


Link to post
Share on other sites

This topic is 4716 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this