Home

Object-Oriented Win32

 

Window Objects

 

Introduction

Every object you see on your screen that can be located, can be clicked, or moved, is called a window. As you may imagine, these window objects can be as different as the human eye can distinguished them. Some of these objects are icons, buttons, pictures, menu items, etc. As different as they are, there are also various ways of creating them.

There are three main ways you create a window, as we will learn throughout this site. One of the techniques you can use consists of creating a script in a resource file, as we have introduced scripts in lessons 1 and 2. Another technique you can use consists of calling one of the Win32 functions such as CreateWindow() or CreateWindowEx() to create a window; we have introduced it when creating the main window in all previous applications. The last option you have is to use your own class and customize the creation of a window.

OOP Win32 Fundamentals

In C++, you probably learned that it is a good idea to make sure that the main() function be not crowded, which can make your program easier to read and troubleshoot when problems happen. You can also apply this to Win32 programming by separating tasks in their own units. Based on this, you can define functions that perform specific tasks such as creating or registering the window

To apply object oriented programming (OOP) to a Win32 application, you can create a class for each window you use in your application. Since each object is primarily a window, you can start with a general window that lays a foundation for other windows. Such a class can be created as follows (this is a primary window class; we will add methods to it as needed:

#ifndef WINCTRLS_H
#define WINCTRLS_H

#include <windows.h>

//---------------------------------------------------------------------------
class WControl
{
public:
	WControl();
	virtual ~WControl();

	HWND Create(HINSTANCE hinst, LPCTSTR clsname,
		   LPCTSTR wndname, HWND parent = NULL,
	            DWORD dStyle = WS_OVERLAPPEDWINDOW,
		   int x = CW_USEDEFAULT, int y = CW_USEDEFAULT,
		   int width = 450, int height = 380);
	BOOL Show(int dCmdShow = SW_SHOWNORMAL);
	operator HWND();
protected:
	HWND hwnd;
	HINSTANCE mhInst;

public:
	HINSTANCE GetInstance();

private:
};
//---------------------------------------------------------------------------

#endif	// WINCTRLS_H

This class can be implemented as follows:

#include "winctrl.h"

//---------------------------------------------------------------------------
WControl::WControl()
	: hwnd(0)
{
}
//---------------------------------------------------------------------------
WControl::~WControl()
{
}
//---------------------------------------------------------------------------
WControl::operator HWND()
{
	return hwnd;
}
//---------------------------------------------------------------------------
HWND WControl::Create(HINSTANCE hinst, LPCTSTR clsname,
		   LPCTSTR wndname, HWND parent,
		   DWORD dStyle,
		   int x, int y,
		   int width, int height)
{
	hwnd = CreateWindow(clsname, wndname, dStyle,
		x, y, width, height, parent, NULL, hinst, NULL);

	return hwnd;
}
//---------------------------------------------------------------------------
BOOL WControl::Show(int dCmdShow)
{
	BOOL CanShow = ::ShowWindow(hwnd, dCmdShow);

	if( CanShow )
		return TRUE;
	return FALSE;
}
//---------------------------------------------------------------------------
HINSTANCE WControl::GetInstance()
{
	return mhInst;
}
//---------------------------------------------------------------------------

To use this class, simply declare it in your application and call the necessary methods. Here is an example:

 
#include <windows.h>
#include "winctrl.h"
//---------------------------------------------------------------------------
HINSTANCE hInst;
LPCTSTR ClsName = L"BasicApp";
LPCTSTR WndName = L"A Simple Window";
//---------------------------------------------------------------------------
ATOM RegWnd(HINSTANCE hInst);
LRESULT CALLBACK WndProcedure(HWND hWnd, UINT uMsg,
			   WPARAM wParam, LPARAM lParam);
//---------------------------------------------------------------------------
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
               LPSTR lpCmdLine, int nCmdShow)
{
	// The message class of the application
	MSG        Msg;

	// Initialize the instance of this application
	hInst = hInstance;
	// create and register the application
	RegWnd(hInstance);
	// Create the window object
	WControl Ctrl;

	Ctrl.Create(hInst, ClsName, WndName);
	Ctrl.Show();

	// Process the messages
	while( GetMessage(&Msg, NULL, 0, 0) )
	{
             TranslateMessage(&Msg);
             DispatchMessage(&Msg);
	}

	return Msg.wParam;
}
//---------------------------------------------------------------------------
ATOM RegWnd(HINSTANCE hInst)
{
	WNDCLASSEX WndClsEx;

	// Create the application window
	WndClsEx.cbSize        = sizeof(WNDCLASSEX);
	WndClsEx.style         = CS_HREDRAW | CS_VREDRAW;
	WndClsEx.lpfnWndProc   = WndProcedure;
	WndClsEx.cbClsExtra    = 0;
	WndClsEx.cbWndExtra    = 0;
	WndClsEx.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
	WndClsEx.hCursor       = LoadCursor(NULL, IDC_ARROW);
	WndClsEx.hbrBackground = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
	WndClsEx.lpszMenuName  = NULL;
	WndClsEx.lpszClassName = ClsName;
	WndClsEx.hInstance     = hInst;
	WndClsEx.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

	// Register the application
	return RegisterClassEx(&WndClsEx);
}
//---------------------------------------------------------------------------
LRESULT CALLBACK WndProcedure(HWND hWnd, UINT Msg,
			      WPARAM wParam, LPARAM lParam)
{
    switch(Msg)
    {
	case WM_CREATE:
		break;
    case WM_DESTROY:
        PostQuitMessage(WM_QUIT);
        break;

    default:
        return DefWindowProc(hWnd, Msg, wParam, lParam);
    }
    
    return 0;
}
//---------------------------------------------------------------------------
 

Win32 Object Programming

 

The Application

In order to create an application, you must first create an application (sorry for the repetition). As we have seen so far, an application is created using the WNDCLASS or the WNDCLASSEX structures. Therefore, you can start with a class that would hold a member variable of this type. As some members of these structures are usually the same for most basic applications, you can create a class that uses default values and can then be easily initialized when it is time to create an application. 

Practical Learning Practical Learning: Initializing an Application

  1. Start your programming environment
  2. Create a Win32 project (If you are using Visual C++, create the project as empty) named Win32OOP1
    If you are using C++ Builder, save the unit as Exercise
    If you are using Visual C++, create a source file and name it Exercise
  3. Create a header file. Save it as WinApp and type the following in it:
     
    #pragma once
    #include <windows.h>
    
    //---------------------------------------------------------------------------
    class WApplication
    {
    public:
    	// This constructor will initialize the application
    	WApplication(HINSTANCE hInst, char *ClasName,
    		     WNDPROC WndPrc, LPCTSTR MenuName = NULL);
    
    	// Class Registration
    	void Register();
    
    protected:
    	// Global variable that holds the application
    	WNDCLASSEX _WndClsEx;
    };
    //---------------------------------------------------------------------------
  4. Create a source file. Save it as WinApp and type the following in it:
     
    #include "WinApp.h"
    
    //---------------------------------------------------------------------------
    WApplication::WApplication(HINSTANCE hInst, char *ClsName,
    			   WNDPROC WndPrc, LPCTSTR MenuName)
    {
    	// Initializing the application using the application member variable
    	_WndClsEx.cbSize        = sizeof(WNDCLASSEX);
    	_WndClsEx.style         = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
    	_WndClsEx.lpfnWndProc   = WndPrc;
    	_WndClsEx.cbClsExtra    = 0;
    	_WndClsEx.cbWndExtra    = 0;
    	_WndClsEx.hInstance     = hInst;
    	_WndClsEx.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    	_WndClsEx.hCursor       = LoadCursor(NULL, IDC_ARROW);
    	_WndClsEx.hbrBackground = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
    	_WndClsEx.lpszMenuName  = MenuName;
    	_WndClsEx.lpszClassName = ClsName;
    	_WndClsEx.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);
    }
    //---------------------------------------------------------------------------
    void WApplication::Register()
    {
    	RegisterClassEx(&_WndClsEx);
    }
    //---------------------------------------------------------------------------
  5. Save all

The Window

As we have done in previous lessons, after initializing the application, you can create a window, or the main window. This is done by calling either the CreateWindow() or the CreateWindowEx() functions. After creating the main window, you can display it, then process its messages.

Practical Learning Practical Learning: Creating a Window

  1. Create a header file. Save it as MainWnd and type the following in it:
     
    #pragma once
    #include <windows.h>
    
    //---------------------------------------------------------------------------
    class WWindow
    {
    public:
    	// We will use a default constructor to declare a window
    	WWindow();
    	// The Create() method wil be used to initialize a window
    	HWND Create(HINSTANCE hinst,
    		    LPCTSTR clsname,
         		    LPCTSTR wndname,
    	            HWND parent   = NULL,
    	            DWORD dStyle  = WS_OVERLAPPEDWINDOW,
    	            DWORD dXStyle = 0L,
    		    int x         = CW_USEDEFAULT,
                        int y         = CW_USEDEFAULT,
    		    int width     = CW_USEDEFAULT,
                        int height    = CW_USEDEFAULT);
    
    	// This method will be used to display the window
    	BOOL Show(int dCmdShow = SW_SHOWNORMAL);
    
    	// Because each window is of type HWND, we will need a way
    	// to recognize the window handle when used in our application
    	operator HWND();
    
    protected:
    	// This will be a global handle available to
    	// this and other windows
    	HWND _hwnd;
    };
    //---------------------------------------------------------------------------
  2. Create a source file. Save it as MainWnd and type the following in it:
     
    #include "MainWnd.h"
    
    //---------------------------------------------------------------------------
    WWindow::WWindow()
    {
    	// If we declare a window class with a default constructor,
    	// we need to reset the window to a nothing
    	_hwnd = NULL;
    }
    //---------------------------------------------------------------------------
    HWND WWindow::Create(HINSTANCE hinst,
        				 LPCTSTR clsname,
    	    			 LPCTSTR wndname,
    	  	    		 HWND parent,
    			    	 DWORD dStyle,
    					 DWORD dXStyle,
    				     int x,
         				 int y,
    	     			 int width,
    		    		 int height)
    {
    	// When call the Create() method, we can use it to create a new window
    	_hwnd = CreateWindowEx(dXStyle, clsname, wndname, dStyle, x, y, width,
    		                 height, parent, NULL, hinst, NULL);
    
    	// We hope everything went alright and the window was created
    	if( _hwnd != NULL )
    		return _hwnd;
    	// If something went wrong, for example if the window could not
    	// be created, return a "nothing" window
    	return NULL;
    }
    //---------------------------------------------------------------------------
    BOOL WWindow::Show(int dCmdShow)
    {
    	// We will display the main window as a regular object and update it
    	if(	ShowWindow(_hwnd, dCmdShow) && UpdateWindow(_hwnd) )
    		return TRUE;
    	return FALSE;
    }
    //---------------------------------------------------------------------------
    WWindow::operator HWND()
    {
    	// This overloaded operator allows us to use HWND anyway we want
    	return _hwnd;
    }
    //---------------------------------------------------------------------------
  3. Save all

Main Application Creation

There are some steps that you should/must follow to create an application. You start by initializing an application object, then create a window, display it, and process its messages. We have mentioned that the messages of an application are treated in a function pointer referred to as callback. Since C++ doesn't like or doesn't encourage function pointers to be members of a class (some libraries such as Borland VCL implemented in C++ Builder solve this problem another way; the Microsoft .NET Framework also solves this problem somehow), the function should be created globally and passed to WNDCLASS or WNDCLASSEX.

Practical Learning Practical Learning: Creating an Application

  1. Open the Exercise.cpp source file and type the following in it (if using C++ Builder, make only the changes):
     
    #include <windows.h>
    #include "WinApp.h"
    #include "MainWnd.h"
    
    //---------------------------------------------------------------------------
    LRESULT CALLBACK MainWndProc(HWND hWnd, UINT Msg,
                                 WPARAM wParam, LPARAM lParam);
    //---------------------------------------------------------------------------
    INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst,
    				   LPSTR lpCmdLine, int nCmdShow)
    {
    	MSG   Msg;
    	LPCTSTR ClsName = L"Win32OOP";
    	LPCTSTR WndName = L"Object-Oriented Win32 Programming";
    
    	// Initialize the application class
    	WApplication WinApp(hInstance, ClsName, MainWndProc);
    	WinApp.Register();
    
    	// Create the main window
    	WWindow Wnd;
    	Wnd.Create(hInstance, ClsName, WndName);
    	// Display the main winow
    	Wnd.Show();
    
    	// Process the main window's messages
    	while( GetMessage(&Msg, NULL, 0, 0) )
    	{
    		TranslateMessage(&Msg);
    		DispatchMessage(&Msg);
    	}
    
    	return 0;
    }
    //---------------------------------------------------------------------------
    LRESULT CALLBACK MainWndProc(HWND hWnd, UINT Msg,
                                 WPARAM wParam, LPARAM lParam)
    {
    	switch(Msg)
    	{
    	case WM_DESTROY:
    		PostQuitMessage(WM_QUIT);
    		return 0;
    	}
    
    	return DefWindowProc(hWnd, Msg, wParam, lParam);
    }
    //---------------------------------------------------------------------------
  2. Execute the application
     
    Object-Oriented Win32 Programming
  3. Return to your programming environment
 
 

Previous Copyright © 2004-2010 FunctionX, Inc. Next