C++ 3D DirectX Tutorial [Message Loop / WndProc] 3

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
because it's chilly here welcome back to hardware 3d tutorial 3d in the last video we created our first window and we have shown it to the user and that works fine except the window is highly unresponsive to our advances so this is a problem why are we getting this well remember I told you two things about windows number one windows is about windows number 2 windows is about messages but in order to understand messages you have to understand something called event-driven programming so if you've gone through my C++ series you will understand this is the game loop right this is how games generally work they just they spin this loop many times a second like 60 times or a hundred times a second and they're constantly spitting out frames and hopefully a constant rate and this doesn't depend on whether there's any input or whether there's any change in the game state it's just constantly gonna spit out frames now let's contrast this with something like notepad notepad when you're not doing anything when you're not clicking on it or typing it just sits there it doesn't do anything it's not processing any frames it's not redrawing itself it's just a static window and when you click on it when you bring to the foreground well then it will change its appearance it'll redraw parts of its UI but again it's going to go back to sleep until you do something like type into the window and when you type it is going to get events keyboard events and it is going to process them by putting data into its buffer into its data buffer and because the data buffer has changed it's got to update the view on that data so it is going to redraw this part of its screen and that's how works mostly mostly notepad is sleeping waiting for an event and I mean even this blinking cursor here this is controlled by a timer event so it sleeps until it gets an event and the event might be a it might be a click it might be a keystroke it might be a timer event that will tell it to you know redraw it's this cursor here this is very efficient right because if you're not doing anything you ain't notepad you don't need to redraw the screen you know 60 times a second of course you couldn't do this in general with a game because games even if you're not doing any input usually it's a simulation and things are moving around of their own accord AI and stuff like that now Windows was originally written mainly with applications like notepad and Microsoft Visual Studio and word in mind so it is inherently an event-based system and what the Windows messages are is they're just events all right now with that information under our belt let's take a look at how we process messages in Windows so here is we got two sides we got the windows 32 side in the app side the windows 32 side it's Windows is managing a bunch of data for your window including a queue of messages and what happens is when you do some stuff when you move the mouse and when you do a mouse click Windows is going to process that input and it is going to put those messages in that order on to your queue then what you do is in your application when you're ready those message will just keep stacking up when you're ready you call get message and you will pull one of those messages off of the queue and then you can do some processing on that message those messages whatever you like really there's one function windows api function that you generally call called translate message and we'll get into this a little bit later but basically what it does is if the message is a keydown message it will generate an additional WM car message and put that on the queue we'll talk about that later the most important one that we're gonna be calling here after get message is dispatch message and again this basically passes the message back to the windows 32 side and what windows 32 does is it says okay now we've got to handle this message now in every window you are gonna have a pointer to a Windows procedure this might be a little familiar to you because remember when we defined our windows class we also defined a long pointer function windows procedure and we set that to be the default windows procedure alright but in general you are going to set that to your own procedure that you define so we're saying here is that windows of this class will have this behavior and by extension that means that that also defines their their appearance because the behavior of the draw of handling messages like the draw message will control the appearance of the window so basically you call dispatch message windows API checks the window sees what the pointer is in there and it will pass that message on to your windows procedure generally when those procedure will then process messages that it is interested in and after it has processed anything that it wants to do it will also call default windows procedure to get the default behavior for all those messages default windows procedure very important because there's probably around a thousand windows messages and you don't want to have to implement all of them so for the most part you're just gonna get the default behavior and you're only gonna add some a little extra something something on top of that when you want something other than the default behavior all right now let's get to the code now the first thing we're gonna do is like I showed you in the diagram we have to call get message so what you do with the new windows function you look it up on MSDN get message takes four parameters first one is a pointer to a message next one is the handle to the window that we're gonna be retrieving messages from and the last two are filter values to filter what kind of messages you want to get so first things first let's let's talk about what these are the pointers and message is basically there's a message structure that holds the message data and you pass a pointer to that structure to get message and get message will fill your structure now the handle to the window we set this to null and the reason why is because if you pass in null then it will get message for any window that belongs to the current thread so we'll just wanting we want to get all messages regardless of what window they come from so we pass in null here and let's take a look at what the message structure is it's got a bunch of stuff in here it's got the handle to the window that the message is for it has a you unsigned int which is the message this gives you the message number which tells you what type of message it is this is the most important part of the message then you've got two parameters here w / m and l / m and they're just two 32-bit values and what they actually mean depends on the message so it's definitely it's completely context dependent they mean complete different things for different messages and then you've got a timestamp for the message point and L private so point apparently you can get the position of the cursor for every message every message you receive you can get where the cursor was at that time which might be useful that I know I don't actually use this one and the other thing is a private this one is it basically don't touch it doesn't doesn't have anything to do with us so that is a message structure now this filter min in filter max allows us to specify a range of message numbers that we want to pull off of the queue and we want to ignore all the other ones but we want to process all messages so if we set them both to zero we'll just get all message numbers now the last thing is the return value of get message this is also very important if get message retrieves a message that is not a quick message then the value is going to be nonzero if it retrieves a quick message it returns zero and if there's an error it's gonna return negative one so basically all we need to do is check if the return value is greater than zero and if it is we keep going but if it is 0 or less than 0 that means it is time to GTFO all right with all this win a P I information on our belt here let's write our first message pump so again you're gonna have your message structure where your messages are gonna be filled into and then we want to do a while loop we want to continuously process messages get message as long as we're not quitting so we go what we a pointer to our message null pointer for the window because we want to handle messages for all windows and we don't want to filter messages we want that unfiltered good stuff pane as long as a return value is greater than 0 we are going to translate message not accelerator there we go translate message we pass it a pointer to our msg I love that name s do you remember or not remember but take a look at this it's a constant pointer so this is telling us that translate message will not modify our message but it will generate auxilary messages in certain cases we'll get into that later then we gotta go dispatch message and this one is what's going to pass our message along to the window proc for the window that belongs that is related to this message and there you go there's your message pump couldn't be easier let's run that again we've got our window but now we can move our window we can't resize it because I didn't enable that ability but I can minimize it and I can maximize it and I can close it only if I close it notice that our program isn't actually closing the windows gone but our process is still running we've got to stop it with the debugger or we get that zombie process again so again remember we are setting the windows procedure to the default procedure which has default behavior for all of the important windows messages including windows message closed but the thing about the default procedure is it doesn't know whether you want to quit out of the whole application or whether you just want to close that one window maybe you have multiple windows and I mean that would be pretty annoying if you close one window and it exited out of the whole application so windows procedure doesn't assume your applications status there and so you have to define that behavior if you want it so let's define a custom windows procedure this is the signature that your windows procedures must have it's going to return basically a 32-bit integer value you have to define the calling convention to be state called because that's how Windows likes it and this is gonna be called from windows 32 name is anything you like and it's got to take these parameters it's got to take a handle to the window that it'll be processing the message for because remember a single procedure can be used for multiple windows it's used for all the windows of this class and then it takes the number of the message the message ID and the W parameter M which like I said before they their meaning depends on exactly what message you're processing now the meaning of the result code also depends on the message you're handling but we don't have to worry about this usually because the last thing we generally call before returning and the value that we return is we return def window proc so we invoke def window proc and it's a window proc so it has the same function signature as our window proc msg WP LP there we go so this will basically give us the same behavior as we got down here so if I now replace this with our wind proc and I run it we should see the same behavior and indeed we are our window is responding the messages but it is not exiting the application when we close the window ok so now we've got to add in that extra something something we've got add some extra behavior for the clothes message so how do we do that well we're gonna add a switch in here so we switch on the message ID and we want to check for WM underscore close so windows defines macros for all the different message codes so you don't have to remember numbers you just have to remember these WM underscore names now for the clothes message all we want to do is post a quick message to our message queue and of course we're gonna have the exit code be 69 so post quick message is a nice little helper function that just posts a quick message to your message queue and this 69 here is the return value that you would like to application to exit with or the exit code and won't break here now you might be wondering why a switch you're only looking for one thing why don't you use an if and the reason is is because of course in the future we're probably going to be processing many different kinds of messages now we handle the message but we haven't handled it completely we've just posted quick message we also want the behavior needed to actually destroy the current window and will allow deaf window Prok to destroy the window because we've seen it's already good at destroying the window it just doesn't tell our application to quit so we add this little behavior on top of what def is already doing and if we do this we will see that if we close this BAM our application exits we can look at the output and application has exited with code 0 wait a minute we wanted angular with code 69 why is it exiting with code 0 well of course because down here we return 0 when we should be returning the whatever exit code was passed in to post quit message so what we should actually do here because there are many cases if get message is negative 1 that means there was an error if get message was 0 that means we have a quick message and we should return the the code in there so what we should do here get message returns a Windows booth I'll call it G result forget result and note that this isn't a C++ bool type it's actually just means but whatever and what we want to do is we want to check to see so we're gonna capture G result when we call get message and we'll check to see whether that captured value is greater than 0 if so we process but if not then we want to check to see what exactly that captured value was so G result is equal to negative 1 we'll just return negative 1 signaling we had an air with our the get message function itself encountered an error otherwise what we want to do is we want to return message dot W program we'll get rid of this because W / M is going to be this code here now you might be saying chilly how did you know that well of course you're gonna Google WM quit cuz that's the message that gets posted when you quit out and if you look at the windows documentation here you're gonna see what W parameter per M do for this message we can see that L / M is not used W / M is the exit code given in the post quit message function so you Google these are these symbols here these define symbols and you will get information about every message you will understand what the parameters mean for every individual message and if we run this bad boy close this one application exits and if we look at that return code we've got a big old 69 now everything is working as we expect and there you go we've got our first functioning window everything works as expected of course the the actual client region here looks a little weird that's because we're not drawing it so it just takes on whatever value was in that video memory when we created the window but when we get on to direct3d we will of course be drawing to this part of our window but that's gonna about do it for this lesson in the next video we are gonna explore other windows messages and we are gonna I'm gonna show you guys how to handle keyboard and mouse input which is obviously very important for writing a game engine until then I hope you enjoyed this video if you did please click the like button helps a lot and I will see you soon with some more hardware 3d [Music] [Applause] [Applause] [Music]
Info
Channel: ChiliTomatoNoodle
Views: 38,482
Rating: undefined out of 5
Keywords: 3d game programming, c++ 3d, game programming tutorial, c++, C++ tutorial, c++ game engine, how to, 3d game engine, Directx programming, direct3d programming, how to program 3d games, DirectX, Direct3D, D3D, programming, game, lesson, cpp, guide, code, tutorial, coding, software, development, windows, visual studio, game dev, chili, winapi, windows sdk, win32
Id: Fx5bGZ3B_CI
Channel Id: undefined
Length: 17min 17sec (1037 seconds)
Published: Wed Dec 26 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.