Top

C++/Win32: Inheritance and Beginning GUI

March 2, 2008

Inheritance

Now we’ll see exactly how easy inheritance is. We are going to create a new class called PortScannerWindow, which publicly inherits from Win32WrapperClass. But first, we’ll need to change our private members of Win32WrapperClass to protected, so that the new class gets them too. This only requires changing private to protected in the class declaration in Win32WrapperClass.h

Now, we’ll want to create two new files, PortScannerWindow.h and PortScannerWindow.cpp. These will hold the class declaration and definition, respectively, of our new class. PortScannerWindow.h will be pretty simple at first, since we aren’t adding much right now. PortScannerWindow.cpp will need to include our redefined constructor and destructor functions and our redefined message handler.

A few things have to be done to make this work. First, of all, when you inherit from a class, you do NOT inherit the constructors and destructors.

What this means to you is a little bit complicated. When you derive a class from another class, the compiler invisibly invokes the default constructors of all classes going down the inheritance chain. If you don’t explicitly define a default constructor, the compiler will invisibly create one for you that does nothing, and all will be well as long as you don’t try to inherit from the class. That’s not us. The compiler does a lot of invisible stuff that will screw you up if you don’t expect it. The default constructor is a constructor that takes no arguments. So to make sure the compiler is happy, we need to go back to the Win32WrapperClass declaration and declare a default (no parameter) constructor. Then we need to go into the class definition and put a do-nothing constructor definition there. Now no one can complain. The same is true for the destructors.

Here’s an example (cout prints to the screen):

		class Pet {
			public:
				Pet() {
					cout << "Pet Constructor\n";
				}
				~Pet() {
					cout << "Pet Destructor\n";
				}
		}

		class Dog: public Pet {
			public:
				Dog() {
					cout << "Dog Constructor\n";
				}
				~Dog() {
					cout << "Dog Destructor\n";
				}
		}

Notice that Dog extends Pet, and each have a default constructor and destructor. Now let’s do the following in WinMain:

		Dog MyDog;

This will create a Dog object called MyDog. The following will be output to the screen:

		Pet Constructor
		Dog Constructor

Pretty straightforward. Now, when the program exits, the destructors will be called. Destructors work the same, only in reverse, so

the following will appear onscreen:


		Dog Destructor
		Pet Destructor

Simple. At this point you should be thinking of classes as composed of parts: the new part (the subclass part) and the base class part. Each part needs to be dealt with at construction and destruction time. For this reason, you should usually define some sort of default constructor and destructor in your base classes, because you can’t assume that someone extending your class will responsibly allocate memory and deallocate memory in their subclass. Your constructors should always deal with the stuff you’ve put in your class, and let

the subclasser deal with his own part.

So, the first thing we’ve done in order to be able to extend Win32WrapperClass is add a default constructor (which, lamely, does nothing).

A cool question to ask here (and one that would indicate all this makes sense so far) is: if classes don’t inherit destructors, why do we have to declare the Win32WrapperClass destructor virtual? Good question. After all, virtual functions are functions that can be overridden in child classes, but as we just saw, destructors HAVE to be overridden. So here’s an introduction to polymorphism:

It happens sometimes that you will have a pointer to an object without knowing exactly what the object is. All you know is the base class of the object. Let’s say you have three classes that form an inheritance line: Human->Man->Businessman. Now, let’s say we’ve defined a public function in Human called IncrementAge() that adds 1 to the public variable Age, and that the function is not virtual — meaning it will be the same function in Man and Businessman. Now let’s say elsewhere in the program we have a function called AgeUp that will take a Human, Man, or Businessman and call its IncrementAge function. Well, we could either write three separate functions to handle this, one for each type of object, or we can take advantage of the fact that every one of these objects has the same IncrementAge() function. This is polymorphism: Businessman objects are also Man objects are also Human objects. So we can have the following:

	int AgeUp(Human *human) {
		human->IncrementAge();
	}

	Businessman josh;
	AgeUp (&josh);

Notice the function expects a Human object, but we pass it a Businessman object. Same thing. Since Businessman is a Human, the compiler won’t freak when we try to execute it’s IncrementAge function. The thing is, though, that it doesn’t call the IncrementAge function for Businessman, it calls the IncrementAge function for Human. In this case, its no big deal, but it might matter a lot in the case of a destructor. By calling a destructor virtual, we are saying MAKE SURE you use the right one, don’t just assume they are the same. Since destructors are important for cleaning up after an object, you should typically make your destructors virtual.

So with that out of the way, I’ve modified WinMain to declare and create a PortScannerWindow instead of a Win32WrapperClass. If you compile and run this, it will do the same thing its always done: pop up a window and wait for you to close it. But take a look at the class definition and declaration for PortScannerWindow — looks clean, right? Because we’ve put all the tedious window creation stuff in Win32WrapperClass and extended it, we can now modify PortScannerWindow without getting caught up in all the stuff we’ve already sorted through. So our code is much easier to manage.

Beginning the Port Scanner

Before we begin making this thing into a port scanner, we need to make sure we have a plan. Since there’s only an hour left before I leave this place for the night, I’ll spend it laying out the plan.

In Windows programming, an obvious place to start planning is at the GUI level. We’ll first make this port scanner as simple as possible. It will need to read in an IP address, a start port and an end port. It will need a button to tell the program that there is info to be had, and it will need a text display box to output the results. Lets make our app window square, and fit things in like this:

|---------------------------------------------------------------------------------------------|
| LinkSixteen Port Scanner                                                            _ 0 X   |
|---------------------------------------------------------------------------------------------|
|                                                                                             |
|      |-----------------|         |--------|      |--------|   /--------------\              |
|   IP | 216.144.238.234 |   Start |  20    |  End | 30     |   |     SCAN     |              |
|      |-----------------|         |--------|      |--------|   \--------------/              |
|                                                                                             |
|   |------------------------------------------------------------------------------------|    |
|   | Results:                                                                           |    |
|   | 20: open                                                                           |    |
|   | 21: closed                                                                         |    |
|   | 22: open                                                                           |    |
|   |                                                                                    |    |
|   |                                                                                    |    |
|   |                                                                                    |    |
|   |                                                                                    |    |
|   |                                                                                    |    |
|   |                                                                                    |    |
|   |                                                                                    |    |
|   |                                                                                    |    |
|   |                                                                                    |    |
|   |                                                                                    |    |
|   |                                                                                    |    |
|   |                                                                                    |    |
|   |------------------------------------------------------------------------------------|    |
|                                                                                             |
|---------------------------------------------------------------------------------------------|

ASCII art makes me weepy and nostalgic :(

Anyways, obviously this may change, but we can see that we’ll need three text input boxes, a button, and a text area. We will also need three text labels to identify the input boxes. Luckily, Windows provides all these, so we won’t have to do this ourselves — we just have to tell Windows we want them, and make sure we keep track of them. Hopefully by now you realize that these items will be members of the PortScannerWindow class, and will themselves be window objects as far as Windows is concerned.

Now, how are we going to handle the actual scanning? While we should use threads to handle each individual connection, we won’t. Eventually, we’ll cover threading and modify this thing to thread, but for now we’ll do this in order. Our flowchart will look something like this:

		10: Create and Show PortScannerWindow

		20: Wait for input 

		30: On button press, verify input
			- valid? goto 40
			- invalid? goto 20

		40: for each port from Start to End do:
			41: create socket
			42: connect to IP:port
				- if succeed, echo port: open
				- if fail, echo port: close
				- next

		50: goto 20

This is going to be simple, really, except the part about sockets, and even that isn’t that tough.

Building the GUI

Ok, to build the GUI, we need to maintain a handle on all of our elements (3xEdit Box, 3xText Label, 1xButton, 1xText Area). Seems reasonable, then, for our PortScannerWindow class to have 8 protected HWND variables for this purpose. We should also have a separate function called BuildGUI() that handles creating the elements, positioning them in the window, and drawing them. Once we build that function and add the HWND variables to the protected section of the class, we can worry then about where to call BuildGUI().

The good thing about window elements being windows themselves is that you don’t have to learn anything new. All you have to do is call CreateWindow and pass it the name of a predefined class. Remember to create our app window, we had to first register a class with Windows. For standard window elements, the classes are already registered, and have such obvious class names as “BUTTON,” so all you have to do is call CreateWindow with that class name, and assign the returned HWND value to a variable.

A button is created like this:

HWND button;
button= CreateWindow(
    "BUTTON",				        // predefined class
    "OK",					// button text
    WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,	// styles
						// Size and position values are given explicitly, because
						// the CW_USEDEFAULT constant gives zero values for buttons.
    10,						// starting x position
    10,						// starting y position
    100,					// button width
    100,					// button height
    hwnd,					// parent window
    NULL,					// No menu
    hInstance,					// Our app's HINSTANCE
    NULL					// pointer not needed
);

Notice that by ORing the WS_VISIBLE style, the “window” is visible without having to call ShowWindow. WS stands for “Window Style” and BS stands for “Button Style.” So in this example, we’ve created a visible default pushbutton, which is a child window. A child window needs a parent, so we have to pass it the HWND of the parent, and you’ll see in parameter 8 we pass in hwnd, which we assume to be the HWND of the main app window.

So now we have a button, but how to we interact with it? Through Windows messages, of course. We know already that we have to tell Windows where to send messages for our user defined windows, but this window isn’t user defined. So where do the messages go? They go to the parent window’s message handler. That’s convenient, because we can handle all the messages for the window in one place, without having to write separate message handlers for each window element.

The message that Windows sends when a button is pushed is WM_COMMAND, so we’ll have to watch for that in our message handler. Have a look at our overriding WinProc function (the one we wrote for PortScannerWindow) and you’ll see this bit of code:

		switch(uMsg)
	    {
	        case WM_COMMAND:
	            switch(LOWORD(wParam))
		        {
		            case IDC_PRESS:
		                MessageBox(m_hWnd, "Hi!", "This is a message",
		                    MB_OK | MB_ICONEXCLAMATION);
		            break;
		            case IDC_OTHER:
		                MessageBox(m_hWnd, "Bye!", "This is also a message",
		                    MB_OK | MB_ICONEXCLAMATION);
		            break;
		        }
		    break;
		    default:
		        return FALSE;
		}
		return TRUE;

This introduces the switch construct, so I’ll deal with it quickly. The switch statement is an easier way of writing if/else if/else if etc… and it works exactly like it’s named: as a switch. Here’s a simpler example:

int age=getUserAge();				// assume this reads in the user's age

switch(age) {
        case 5:
	        printf "Youngin'!";
		break;
	case 20:
		printf "Alcoholic!";
		break;
	case 80:
		printf "Dead!";
		break;
	default:
		printf "Your age is irrelevant to me";
}

Basically, this checks the value of age against several cases, and executes the code under the case it matches. One odd thing about switches is that they will continue executing code for every case after it finds a match, unless you put a break statement. So if the break statement in case 5 were removed, and age==5, the output would be “Youngin’!Alcoholic!”. There can be a default case for all other values that don’t get their own case, but it’s not necessary. If the switch fails all the way down, and there is no default, nothing will happen.

Now, back to our uMsg switch: we are going to use switches to route our program to the right code for the message we’ve received. So far, we’re only checking for a WM_COMMAND message. If that is the message we’ve received, we’ll execute the code for that case, which, you’ll see, is another switch, this time checking the LOWORD portion of the wParam. In the case where Windows sends us a WM_COMMAND message, the LOWORD of the wParam parameter will hold the resource ID of the element that was hit. More about resource IDs a little later.

Here’s what all this LOWORD stuff is about:

wParam and lParam are 32 bit data values. A word is a 16 bit datavalue, so a DWORD or “double word” is a 32 bit value. Then it makes sense to think of wParam (or lParam) as a double word, made up of a low order word (the first 16 bits) and a high order word (the last 16 bits). As I said before, Windows crams whatever information it can into these two DWORDs (wParam and lParam), and it’s your job to break them apart and analyze them to figure out what Windows is trying to tell you. Getting the low order word out of wParam is easy, you just pass it to the function LOWORD, as you see in the nested switch statement above.

What lParam and wParam contain is different for each message, so when you get ready to handle a particular message, you’ll need to look up the message definition to know what you’ll be getting. In the case of our button here, we just need to know which button we’re receiving a message about. Actually, since we have only one button, we don’t even need that, but you should always make sure you’re receiving what you think you’re receiving.

So how do we know which button we’re getting a message for? How do we compare the low order word of wParam to our button to see if it’s a match? We will need to assign this button a resource ID. Lucky for you I have already spent the 10 hours needed to figure out where in Visual Studio you have to do this.

Basically, you will pass a resource ID to CreateWindow where the menu ID would be if this were a regular window. The 9th parameter to CreateWindow is a HMENU, which is a handle to a menu resource. We could have created a menu using the Visual Studio resource editor, and passed the resource ID VS gave us to the CreateWindow call in PortScannerWindow’s Create() function and had a groovy menu to play with. In the case of a button, adding a menu to it makes no sense, so we use this parameter to pass in the button’s resource ID, only first we’ll have to cast it to the HMENU type, since that’s what CreateWindow is expecting. Casting is easy, just stick a (HMENU) right in front of your resource ID and its all done.

This is bizarre and stupid and confusing, so just accept it and move on.

The last thing we have to worry about is making sure our resource ID is unique. We could just keep track of it ourselves, pass in something like 101 for the button’s ID, and it would work, but then what if we extended this program and really did add a menu to our main app window? Then we’d be in fear that Visual Studio would assign our menu the same resource ID, and we’d be in huge trouble. So what we need to do is tell Visual Studio we need a resource ID, and let it give us one. That way, it will know we’ve taken that ID for our button, and it won’t attempt to use it later. This is what took me forever to figure out, but it was really simple:

At the top right of Visual Studio, you’ll see a box that shows either the Class View or the Solution Explorer of your app. There are four tabs at the bottom allowing you to switch between Class View, Solution Explorer, Resource View and the MSDN Library. Click the Solution Explorer tab, and then open the Resource Files folder. There should be a .rc file in there. Double click it, and you will jump to the Resource View. Now you’ll see a .rc folder. Right click it, and go to Resource Symbols. It is in here that you’ll ask for a resource ID, assign it a name, and shake hands with Visual Studio. Click New. VS will automatically come up with the next available resource ID, starting with 101, and ask you for a name. Try to name your resources according to convention. In the case of a button, name it IDB_GOSCAN. IDB, of course, stands for ID Button. Close the window after you’ve added your resource. You might want to do a File->Save All at this point for no good reason other than Visual Studio seems to not update itself immediately if you don’t.

Now, go into the Solution Explorer. Double click the resource.h file under Header Files. You should see your resource ID in there. The line will look like this:

#define IDB_GOSCAN                      101

This just defines a constant called IDB_GOSCAN to the value 101. So we’ve reserved it and defined it in our resource file. Now we can safely pass it to CreateWindow when we create our button. Go back to PortScannerWindow.cpp and modify the call to CreateWindow in BuildGUI(), changing the 9th parameter from NULL to (HMENU)IDB_GOSCAN and that’s all we have to do to let Windows know how to ID our button. Now add the following to the top of PortScannerWindow.h to include our resource definitions, and we’re done:

#include "resource.h"

So then, the next step is to modify our switch statement to see if the LOWORD of wParam matches our button, and if so, handle that button press.

The new code looks like this:

switch(uMsg) {
	case WM_COMMAND:
		switch(LOWORD(wParam)) {
			case IDB_GOSCAN:
			    MessageBox(m_hWnd, "Hi!", "This is a message",
			    MB_OK | MB_ICONEXCLAMATION);
			    break;
		}
		break;
 }

Here we’re checking the received message. If it is a WM_COMMAND, we check the low order word of wParam to see if it’s our IDB_GOSCAN button. If so, we pop up a MessageBox saying “Hi.”. That’s it. Of course, in the finished Port Scanner app, pushing this button will trigger a call to the function that handles the actual scanning.

To complete the GUI, we need to add HWND variables for all of our 8 elements, position and define them properly using CreateWindow, assign resource IDs to each, and handle messages as necessary in WinProc. Look over the code to see this in detail.

Our HWND declarations go in PortScannerWindow.h, and look like this:

HWND m_hGoButton;
HWND m_hIPAddressEdit;
HWND m_hStartPortEdit;
HWND m_hEndPortEdit;
HWND m_hIPAddressLabel;
HWND m_hStartPortLabel;
HWND m_hEndPortLabel;
HWND m_hDisplayArea;

Our CreateWindow calls for each of these go in PortScannerWindow.cpp, in the BuildGUI() function, and look like this:

// Create and show our button
m_hGoButton = CreateWindow("BUTTON", "Scan", WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
        400,10, 80, 20, m_hWnd, (HMENU)IDB_GOSCAN, m_hInstance, NULL);	

// Create and show our edit boxes
m_hIPAddressEdit = CreateWindow("EDIT", "127.0.0.1", WS_VISIBLE | WS_CHILD | ES_LEFT | WS_BORDER,
         10, 10, 120, 20, m_hWnd, (HMENU)IDE_IPADDRESS, m_hInstance, NULL);
m_hStartPortEdit = CreateWindow("EDIT", "1", WS_VISIBLE | WS_CHILD | ES_LEFT | WS_BORDER, 140, 10,
         100, 20, m_hWnd, (HMENU)IDE_STARTPORT, m_hInstance, NULL);
m_hEndPortEdit = CreateWindow("EDIT", "100", WS_VISIBLE | WS_CHILD | ES_LEFT | WS_BORDER, 250, 10,
         100, 20, m_hWnd, (HMENU)IDE_ENDPORT, m_hInstance, NULL);	

// Create and show our labels
m_hIPAddressLabel = CreateWindow("STATIC", "IP Address", WS_VISIBLE | WS_CHILD, 10, 40, 120, 20,
        m_hWnd, (HMENU)IDS_IPADDRESS, m_hInstance, NULL);
m_hStartPortLabel = CreateWindow("STATIC", "Start Port", WS_VISIBLE | WS_CHILD, 140, 40, 100, 20,
        m_hWnd, (HMENU)IDS_STARTPORT, m_hInstance, NULL);
m_hEndPortLabel = CreateWindow("STATIC", "End Port", WS_VISIBLE | WS_CHILD, 250, 40, 100, 20,
        m_hWnd, (HMENU)IDS_ENDPORT, m_hInstance, NULL);	

// Create and show our text output area
m_hEndPortLabel = CreateWindow("STATIC", "LinkSixteen Port Scanner v1.0",
        WS_VISIBLE | WS_CHILD | WS_BORDER, 10, 80, 470, 380, m_hWnd, (HMENU)IDT_OUTPUT,
        m_hInstance, NULL);

That’s it. When BuildGUI() is called, all of these elements will be drawn into the parent window.

Now, up until now we’ve only seen Windows send messages to your window’s message handler when it has something to tell you. But you can also send messages to the window yourself. You would need to do this if you need to update it for any reason — for example, to change the text in a text box. Let’s say we have an edit control and a button. If, when the button is pressed, we check the data in the edit box and determine it is invalid, we might want to clear out the data in the box, or possibly replace it with a message or a default data value. To do this, we will need to send a message to the control telling it we want it to redraw its text, and we’ll also have to send it the new text.

There is a more complicated way to do this, but Windows provides you with a function that does it for you: SetDlgItemText. Let’s change the data in our m_hIPAddressEdit edit box (listed above) from “127.0.0.1″ to “216.144.238.247″:

SetDlgItemText(m_hWnd, IDE_IPADDRESS, "216.144.238.247");

That’s it. We pass in the HWND of the parent window, the resource ID of the control, and our new text. This function handles the tasks of sending the appropriate message, and packing the information into wParam and lParam. If you’re wondering why this is important at the moment, we are going to use this function to update the text in our text output box when we have the result of a port scan.

In Win32/C++, whenever you see a function called SetSomething(), you can generally expect there will be a GetSomething() to go along with it. SetDlgItemText is no exception. We can get the text from the edit control, but we have to do more work to get it. Of course it would be nice if the function just returned a pointer to a string, but it doesn’t. When we want to store a string, but we don’t know how long it will be, we need to allocate memory to hold it. Remember, memory allocation is a lot easier than it seems. We just need to declare a char pointer, ask the system for x chars of memory, and then we can safely write to memory what we receive from GetDlgItemText.

Here’s the code for that:


int len = GetWindowTextLength(GetDlgItem(m_hWnd, IDE_IPADDRESS));
if (len>0) {
	char* buf;
	buf = (char *)GlobalAlloc(GPTR, len+1);
	GetDlgItemText(m_hWnd, IDE_IPADDRESS, buf, len + 1);

	// .... work witht the text

	GlobalFree((HANDLE)buf);
}

First, we declare an int called len to store the length of the text, which we retrieve by calling GetWindowTextLength. We need to pass to that function the DlgItem, so we get that from GetDlgItem. Next, we allocate len + 1 bytes (byte = the length of a char) and give it to buf, a char pointer. Why len + 1? Because all strings end with a null terminator, represented in C++ by \0. This tells the system when the string is done. GetWindowTextLength only returns the length of the string NOT including the null terminator, so we have to make room for that thing. The only way to know whether you need to make room for the null terminator or not when dealing with a particular function is to read the docs. Or, you can just be safe and always + 1 your buffers, because why the hell not? It’s only 4 bits of memory you may (or may not) be wasting.

Anyways, now that we have a buffer big enough to hold our text, we call GetDlgItemText, pass it the parent window’s HWND, the resource ID of the control, the buffer we want our text to go into, and how much of the text we want (which is all of it, in this case). Then, of course, we have to call GlobalFree to tell the system we are done with the memory, and it can go back into the usable pool again.

If that seems like a ridiculously complicated way of figuring out the text in an edit control, you are correct sir. And you’ll do it a whole lot, because 80% of Windows programming is reading input from edit controls. So you might as well wrap all that nonsense in your own class member function that takes a resource ID and returns the text. We’ll do that when we need to add that functionality.

What about reading numbers from edit controls? Win32 has a function to handle that, and it does it much more nicely than with text. The function is GetDlgItemInt, and typical usage would look like this:

BOOL bSuccess;
int StartPort = GetDlgItemInt(m_hWnd, IDE_STARTPORT, &bSuccess, FALSE);

That’s it. No buffers or any of that junk, because we aren’t dealing with chars. We pass in the HWND of the parent window, the resource ID of the edit control, a pointer to a BOOL (which I’ll explain in a second), and a flag, either TRUE or FALSE, representing whether we expect signed (+/-) or unsigned data to be read. We pass a pointer to a BOOL in to catch failure. If the function fails, for whatever reason, it will return 0 as the value, so if the return value is 0, we should probably check to make sure that bSuccess is TRUE, because otherwise the function failed and 0 wasn’t actually read.

We can also define our edit box using the ES_NUMBER style flag to tell Windows to only allow digits in this edit control, like this:

m_hIPAddressEdit = CreateWindow("EDIT",
                                "127.0.0.1",
                                WS_VISIBLE | WS_CHILD | ES_NUMBER | WS_BORDER,
                                10, 10, 120, 20,
                                m_hWnd,
                                (HMENU)IDE_IPADDRESS,
                                m_hInstance,
                                NULL);

If we do this, however, ONLY digits will be allowed, so we can’t receive decimal points, minus signs, or anything like that. This should only be used if we expect unsigned (0 and up) integer values — for example, our start port and end port values.

Recap

At this point, we have wrapped our window in a class (Win32WrapperClass), extended the class to a more specific subclass (PortScannerWindow), and build up a primitive GUI using a new function called BuildGUI(). We have also seen how to assign resource IDs and how to communicate with window components using their IDs. This is, without a doubt, the hardest material there is. The rest is nothing compared to this, so make sure you understand this stuff completely and soon we’ll be writing sick code and taking over the world.

Next: Port Scanning and Sockets.


Source Code:

win32tut_part4.zip [601kb zipped]

Additional Information:

· theForger’s Win32 API Tutorial - Standard Controls

Further Reading:

· Nitty Gritty Windows Programming with C++ by Henning Hansen.

· Thinking in C++ by Bruce Eckel.

Comments

Got something to say?





Bottom