• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.

Archived

This topic is now archived and is closed to further replies.

Brian Jones

TOTWGPG

10 posts in this topic

Hello, I am at the latter part of the second chapter in this book. I've made a program that opens two different windows, based on two different classes.
  
// Two Windows.cpp : Defines the entry point for the application.

// DEMO2_5.CPP - Creates two windows based on the same 

// window class


// INCLUDES ///////////////////////////////////////////////

#define WIN32_LEAN_AND_MEAN  // just say no to MFC


#include <windows.h>   // include all the windows headers
#include <windowsx.h>  // include useful macros
#include <stdio.h>     
#include <math.h>
#include <stdafx.h>


// DEFINES ////////////////////////////////////////////////


// defines for windows 

#define WINDOW_CLASS_NAME "WINCLASS1"
#define WINDOW_CLASS_NAME2 "WINCLASS2"

// GLOBALS ////////////////////////////////////////////////

HWND hWindow1 = NULL;
HWND hWindow2 = NULL;

// FUNCTIONS //////////////////////////////////////////////

LRESULT CALLBACK WindowProc(HWND hwnd, 
						    UINT msg, 
                            WPARAM wparam, 
                            LPARAM lparam)
{
// this is the main message handler of the system

PAINTSTRUCT		ps;		// used in WM_PAINT

HDC				hdc;	// handle to a device context


// what is the message 

switch(msg)
	{	
	case WM_CREATE: 
        {
		// do initialization stuff here


        // return success

		return(0);
		} break;

	case WM_PAINT: 
		{
		// simply validate the window

		hdc = BeginPaint(hwnd,&ps);	 
		// you would do all your painting here

        EndPaint(hwnd,&ps);

        // return success

		return(0);
   		} break;

	case WM_DESTROY: 
		{
		// kill the application, this sends a WM_QUIT message 

		if( hwnd == hWindow1 )
		hWindow1 = NULL;
		if( hwnd == hWindow2 )
		hWindow2 = NULL;
		if((!hWindow1)  && (!hWindow2) )
		PostQuitMessage(0);
        // return success

		return(0);
		} break;

	default:break;

    } // end switch


// process any messages that we didn't take care of 

return (DefWindowProc(hwnd, msg, wparam, lparam));

} // end WinProc


// WINMAIN ////////////////////////////////////////////////

int WINAPI WinMain(	HINSTANCE hinstance,
					HINSTANCE hprevinstance,
					LPSTR lpcmdline,
					int ncmdshow)
{

WNDCLASSEX winclass; // this will hold the class we create

WNDCLASSEX winclass2;
MSG		   msg;		 // generic message


// first fill in the window class stucture

winclass.cbSize         = sizeof(WNDCLASSEX);
winclass.style			= CS_DBLCLKS | CS_OWNDC | 
                          CS_HREDRAW | CS_VREDRAW;
winclass.lpfnWndProc	= WindowProc;
winclass.cbClsExtra		= 0;
winclass.cbWndExtra		= 0;
winclass.hInstance		= hinstance;
winclass.hIcon			= LoadIcon(NULL, IDI_APPLICATION);
winclass.hCursor		= LoadCursor(NULL, IDC_ARROW);
winclass.hbrBackground	= (HBRUSH)GetStockObject(BLACK_BRUSH);
winclass.lpszMenuName	= NULL;
winclass.lpszClassName	= WINDOW_CLASS_NAME;
winclass.hIconSm        = LoadIcon(NULL, IDI_APPLICATION);

// winclass2 struct

winclass2.cbSize		= sizeof(WNDCLASSEX);
winclass2.style			= CS_DBLCLKS | CS_OWNDC |
						  CS_HREDRAW | CS_VREDRAW;
winclass2.lpfnWndProc	= WindowProc;
winclass2.cbClsExtra	= 0;
winclass2.cbWndExtra	= 0;
winclass2.hInstance		= hinstance;
winclass2.hIcon			= LoadIcon(NULL, IDI_APPLICATION);
winclass2.hCursor		= LoadCursor(NULL, IDC_ARROW);
winclass2.hbrBackground	= (HBRUSH)GetStockObject(BLACK_BRUSH);
winclass2.lpszMenuName	= NULL;
winclass2.lpszClassName	= WINDOW_CLASS_NAME2;
winclass2.hIconSm		= LoadIcon(NULL, IDI_APPLICATION);



// register the window class

if (!RegisterClassEx(&winclass))
	return(0);
// register the window2 class

if (!RegisterClassEx(&winclass2))
	return(0);


// create the first window

if (!(hWindow1 = CreateWindowEx(NULL,                  // extended style

                            WINDOW_CLASS_NAME,     // class

						    "Window 1 Based on WINCLASS1", // title

						    WS_OVERLAPPEDWINDOW | WS_VISIBLE,
					 	    0,0,	    // initial x,y

						    400,400,  // initial width, height

						    NULL,	    // handle to parent 

						    NULL,	    // handle to menu

						    hinstance,// instance of this application

						    NULL)))	// extra creation parms

return(0);

// create the second window

if (!(hWindow2 = CreateWindowEx(NULL,                  // extended style

                            WINDOW_CLASS_NAME2,     // class

						    "Window 2 Based on WINCLASS2", // title

						    WS_OVERLAPPEDWINDOW | WS_VISIBLE,
					 	    100,100,  // initial x,y

						    400,400,  // initial width, height

						    NULL,	  // handle to parent 

						    NULL,	  // handle to menu

						    hinstance,// instance of this application

						    NULL)))	// extra creation parms

return(0);

// enter main event loop, but this time we use PeekMessage()

// instead of GetMessage() to retrieve messages

while(TRUE)
	{
    // test if there is a message in queue, if so get it

	if (PeekMessage(&msg,NULL,0,0,PM_REMOVE))
	   { 
	   // test if this is a quit

       if (msg.message == WM_QUIT)
           break;
	
	   // translate any accelerator keys

	   TranslateMessage(&msg);

	   // send the message to the window proc

	   DispatchMessage(&msg);
	   } // end if

    
    // main game processing goes here

	
	} // end while


// return to Windows like this

return(msg.wParam);

} // end WinMain


///////////////////////////////////////////////////////////


   
It executes perfectly, but I'm not sure how WindowProc works. How does it know which window need to be repainted? I'm my code, it doesn't appear to know the handle of either window. Somebody please help so I can move on to the next chapter. Edited by - Brian Jones on December 12, 2001 5:24:02 PM Edited by - Brian Jones on December 12, 2001 5:28:01 PM
0

Share this post


Link to post
Share on other sites
If you look at the function declaration, you will see hwnd.

LRESULT CALLBACK WindowProc(HWND hwnd,
UINT msg,
WPARAM wparam,
LPARAM lparam) {
....
}

When you window gets a system message such as window close, resize, repaint, etc....it calls WindowProc with hwnd, which is a handle to the current window (ie, itself). So when WindowProc is called, it does it''s work on hwnd, which points to the window that called it. Make sense?

And if you notice throughout your code below, you call all the functions to manipulate the window with hwnd again. So you always do the work on the calling window.

Good to see you asking the questions, g''luck with it all =)

R.
0

Share this post


Link to post
Share on other sites
But, hWindow1, and hWindow2 are the handles to the two windows. How would I pass both of those handles to WindowProc?
0

Share this post


Link to post
Share on other sites
Well, those handles are just pointers. You have more than one pointer to each window.

Say for example you tell your window to minimize. The window you created knows that it''s callback function is WindowProc because you created a Window Class and told it what function to use. So, when you minimize that window, it will call WindowProc for you using using hWindow1 or hWindow2 depending on which window does the calling. If you minimize hWindow2, it''ll call Windowproc with hWindow2 as it''s first paramater. Windowproc just create a new pointer called hwnd to point to hWindow2. At this point, hwnd = hWindow2.

Same thing if it was hWindow1 that sent a message to WindowProc. If it didn''t work this way, you''d have to write a seperate WindowProc for each Window. If you had an application with 10 windows, that''d be 10 WindowProcs?! Waste of time. Instead, you can create a common WindowProc and maybe a special WindowProc when you want the window to act differently or just write a lot of code to compare hwnd to hWindow1, hWindow2, etc. Just like you did in the code from the book. If you look at WM_DESTROY in WindowProc, you can see code where you see if hwnd == hWindow1 or if hwnd == hWindow2.

R.
0

Share this post


Link to post
Share on other sites
Easily, they are both based on the same WndProc. In your WNDCLASS struct you assign the same WndProc to both.

This they both point to the same function, in this case the WndProc.

ECKILLER
0

Share this post


Link to post
Share on other sites
Ahhh I get it. I forgot about that. This Windows programming is hard. One more thing though

  
case WM_DESTROY:
{ // kill the application, this sends WM_QUIT

if( hwnd == hWindow1 )
hWindow1 = NULL;
if( hwnd == hWindow2 )
hWindow2 = NULL;
if((!hWindow1) && (!hWindow2) )
PostQuitMessage(0); // return success

return(0);
} break;


Somebody please explain that. That code is not mine, somebody added it to the program when I was writing it.
0

Share this post


Link to post
Share on other sites
quote:
if( hwnd == hWindow1 )
hWindow1 = NULL;
if( hwnd == hWindow2 )
hWindow2 = NULL;

Assign whichever window received the WM_DESTROY message to point to NULL. Whoever wrote it felt that it was necessary so that the application would be able to quit if both Windows had been closed. It was also necessary to explicitly refer to the variables by name because the window procedure gets a copy of the handle, not the original.

Not exactly a stroke of elegant genious, but it works.

[ GDNet Start Here | GDNet FAQ | MS RTFM | STL | Google ]
Thanks to Kylotan for the idea!
0

Share this post


Link to post
Share on other sites
Ok.... I get it. But what does the last part mean?
  

if((!hWindow1) && (!hWindow2) )



Everybody must be like "God this guy can''t figure out anything
for himself."
0

Share this post


Link to post
Share on other sites
I still don''t get it. Do that handle to a window point to NULL when a WM_DESTROY message is sent to that window?
0

Share this post


Link to post
Share on other sites
quote:
Original post by Brian Jones
I still don''t get it. Do that handle to a window point to NULL when a WM_DESTROY message is sent to that window?

You need to pay attention to what you read.

Can you see where hWindow1
    or
hWindow2 is set to NULL? And then the code checks to see if they are both NULL?

[ GDNet Start Here | GDNet FAQ | MS RTFM | STL | Google ]
Thanks to Kylotan for the idea!
0

Share this post


Link to post
Share on other sites