Title Name not showing and background color not changing


Keywords:c++ 


Question: 

I have code for a C++ Win32 Wrapper Class which i am fiddling with. Since I'm just trying to use handler's, i removed the WindowProcedure and just used a message router. And somehow things are getting buggy. Now with just the message router the title of the WindowClass which i have tired to make doesn't display the title name of the window. And somehow i can't seem to get the background color to change.

Main.cpp

#include "BaseWindow.h"
#include "GameWindow.h"

    int APIENTRY WinMain ( HINSTANCE h_instance, HINSTANCE h_prev_instance, LPSTR lp_cmd_line, int n_cmd_show ) {
        // Create the Game Window
        GameWindow game_window ( h_instance, TEXT ( "GameWindow" ) );
        game_window.Register ();

        // Create the Base Window
        BaseWindow base_window ( TEXT ( "BaseWindow" ), game_window.ClassName () );
        base_window.Create ();
        base_window.Show ();

        // Pump Messages
        MSG messages;
        int status;
        while ( ( status = GetMessage ( &messages, 0, 0, 0 ) ) != 0 ) {
            if ( status == -1 ) {
                // Break;
                break;
            }
            TranslateMessage ( &messages );
            DispatchMessage ( &messages );
        }
        return messages.wParam;

    }

AbstractWindow.h

#pragma once
#ifndef __ABSTRACT_WINDOW_H__
#define __ABSTRACT_WINDOW_H__

#include <Windows.h>

class AbstractWindow {
    public:
        AbstractWindow ();
        ~AbstractWindow ();

        virtual bool Create ();

        static LRESULT CALLBACK MessageRouter ( HWND, UINT, WPARAM, LPARAM );

    protected:
        HWND hwnd_;

        DWORD style_ex_;
        LPCTSTR class_name_;
        LPCTSTR window_name_;
        DWORD style_;
        int x_;
        int y_;
        int width_;
        int height_;
        HWND parent_;
        HMENU menu_;
        HINSTANCE h_instance_;
        LPVOID param_;

        // Default Handlers
        virtual bool OnCreate ( HWND ) = 0;
        virtual bool OnCommand ( int, int ) = 0;
        virtual bool OnDestroy () = 0;

        virtual bool EraseBackground ( HWND, WPARAM ) = 0;
        virtual bool LeftButtonUp () = 0;

};
#endif // !__ABSTRACT_WINDOW_H__

AbstractWindow.cpp

#include "AbstractWindow.h"

AbstractWindow::AbstractWindow () {}

AbstractWindow::~AbstractWindow () {}

bool AbstractWindow::Create () {
    hwnd_ = CreateWindowEx (
        style_ex_,
        class_name_,
        window_name_,
        style_,
        x_,
        y_,
        width_,
        height_,
        parent_,
        menu_,
        h_instance_,
        this                    // Pointer to this class instance
        );

    return ( !hwnd_ ? false : true );
}

LRESULT CALLBACK AbstractWindow::MessageRouter ( HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param ) {
    AbstractWindow* abstract_window = 0;

    if ( message == WM_NCCREATE ) {
        abstract_window = ( AbstractWindow* ) ( ( LPCREATESTRUCT ( l_param ) )->lpCreateParams );
        SetWindowLong ( hwnd, GWL_USERDATA, long ( abstract_window ) );
        abstract_window->OnCreate ( hwnd );
    }
    else {
        abstract_window = ( AbstractWindow* ) ( GetWindowLong ( hwnd, GWL_USERDATA ) );

        if ( abstract_window ) {
            switch ( message ) {
                case WM_COMMAND:
                    return abstract_window->OnCommand ( LOWORD ( w_param ), HIWORD ( w_param ) );
                case WM_DESTROY:
                    return abstract_window->OnDestroy ();

                case WM_ERASEBKGND:
                    return abstract_window->EraseBackground ( hwnd, w_param );
                case WM_LBUTTONUP:
                    return abstract_window->LeftButtonUp ();

                default:
                    return DefWindowProc ( hwnd, message, w_param, l_param );
            }
        }
        else {
            return DefWindowProc ( hwnd, message, w_param, l_param );
        }

    }
}

BaseWindow.h

#pragma once
#ifndef __BASE_WINDOW_H__
#define __BASE_WINDOW_H__

#include <Windows.h>
#include "AbstractWindow.h"

class BaseWindow : public AbstractWindow {
    public:
        BaseWindow ();
        ~BaseWindow ();

        BaseWindow ( const TCHAR*, const TCHAR* );

        // Display the window onto the screen while updating the client area
        void Show ();


    private:
        virtual bool OnCreate ( HWND );
        virtual bool OnCommand ( int, int );
        virtual bool OnDestroy ();

        virtual bool EraseBackground ( HWND, WPARAM );
        virtual bool LeftButtonUp ();


};
#endif // !__BASE_WINDOW_H__

BaseWindow.cpp

#include "BaseWindow.h"

BaseWindow::BaseWindow () {}

BaseWindow::~BaseWindow () {}

BaseWindow::BaseWindow ( const TCHAR* window_name, const TCHAR* class_name ) : AbstractWindow () {
    // Member variables are declaried in AbstractWindow as Protected
    window_name_ = window_name;
    class_name_ = class_name;

    // Get the module handle for the window currently running
    h_instance_ = GetModuleHandle ( NULL );
    style_ = WS_OVERLAPPEDWINDOW | WS_VISIBLE;
    x_ = CW_USEDEFAULT;
    y_ = CW_USEDEFAULT;
    width_ = CW_USEDEFAULT;
    height_ = CW_USEDEFAULT;
    parent_ = NULL;
    menu_ = NULL;

}

void BaseWindow::Show () {
    // hwnd_ is from AbstractWindow Class
    ShowWindow ( hwnd_, SW_SHOW );
    UpdateWindow ( hwnd_ );
}


// Handlers

bool BaseWindow::OnCreate (HWND hwnd) {
    MessageBox ( hwnd, TEXT ( "[BaseWindow] Window has been successfully created!" ), TEXT ( "SUCCESS" ), MB_OK );

    return true;
}

bool BaseWindow::OnCommand ( int ctrl_id, int notify_code ) {

    // Lower 16 bits specifies the element the mouse was used on
    // Upper 16 bits specifies the mouse properties
    // ctrl_id = Lower
    // notify_code = Upper
    return true;
}

bool BaseWindow::OnDestroy () {
    PostQuitMessage ( 0 );
    return true;
}

bool BaseWindow::EraseBackground ( HWND hwnd, WPARAM w_param) {
    RECT rect;
    GetClientRect ( hwnd, &rect );

    FillRect ( ( HDC ) w_param, &rect, GetSysColorBrush ( COLOR_BTNFACE ) );

    return true;
}

bool BaseWindow::LeftButtonUp () {

    return true;
}

GameWindow.h

#pragma once
#ifndef __GAME_WINDOW_H__
#define __GAME_WINDOW_H__

#include <Windows.h>
#include "AbstractWindow.h"

class GameWindow : protected WNDCLASSEX {
    public:
        GameWindow ();
        ~GameWindow ();

        GameWindow ( HINSTANCE, const TCHAR* );

        virtual bool Register ();

        virtual const TCHAR* ClassName () const;

    protected:
        UINT cb_size_;
        UINT style_;
        WNDPROC lpfn_wnd_proc_;
        int cb_cls_extra_;
        int cb_wnd_extra_;
        HINSTANCE h_instance_;
        HICON h_icon_;
        HCURSOR h_cursor_;
        HBRUSH hbr_background_;
        LPCTSTR lpsz_menu_name_;
        LPCTSTR lpsz_class_name_;
        HICON h_icon_sm_;


};
#endif // !__GAME_WINDOW_H__

GameWindow.cpp

#include "GameWindow.h"

GameWindow::GameWindow () {}

GameWindow::~GameWindow () {}

GameWindow::GameWindow ( HINSTANCE h_instance, const TCHAR* class_name ) {

    // All messages belonging to this Window Class will get sent to MsgRouter

    hInstance =                 h_instance;
    lpszClassName =             class_name;

    lpfnWndProc =               AbstractWindow::MessageRouter;
    lpszMenuName =              NULL;
    cbSize =                    sizeof ( WNDCLASSEX );
    cbClsExtra =                NULL;
    cbWndExtra =                NULL;
    style =                     CS_HREDRAW | CS_VREDRAW;
    hIcon =                     LoadIcon ( NULL, IDI_APPLICATION );
    hIconSm =                   LoadIcon ( NULL, IDI_APPLICATION );
    hCursor =                   LoadCursor ( NULL, IDC_HAND );
    hbrBackground =             ( HBRUSH ) GetStockObject ( COLOR_BTNFACE );

}

const TCHAR* GameWindow::ClassName () const {
    return lpszClassName;
}

bool GameWindow::Register () {
    return ( ( RegisterClassEx ( this ) ) ? true : false );
}

1 Answer: 

Your MessageRouter is missing default processing. Add DefWindowProc as shown

LRESULT CALLBACK AbstractWindow::MessageRouter ( HWND hwnd, UINT message, WPARAM w_param, LPARAM l_param ) {
    AbstractWindow* abstract_window = 0;

    if ( message == WM_NCCREATE ) {
        abstract_window = ( AbstractWindow* ) ( ( LPCREATESTRUCT ( l_param ) )->lpCreateParams );
        SetWindowLong ( hwnd, GWL_USERDATA, long ( abstract_window ) );
        abstract_window->OnCreate ( hwnd );
        return DefWindowProc(hwnd, message, w_param, l_param);//ADD THIS LINE
    }
    ...

For background, you can either handle WM_ERASEBKGND or you can set hbrBackground

Method 1: handle WM_ERASEBKGND

virtual LRESULT EraseBackground(HWND hwnd, WPARAM w_param)
{
    RECT rect;
    GetClientRect(hwnd, &rect);
    FillRect((HDC)w_param, &rect, GetSysColorBrush(COLOR_BTNFACE));
    return 1;
}

Method 2: set hbrBackground and let window do the rest

hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);

virtual LRESULT EraseBackground(HWND hwnd, WPARAM w_param)
{
    //let window do this
    return DefWindowProc(hwnd, WM_ERASEBKGND, w_param, 0);
}

......... Edit #2

class AbstractWindow
{
    virtual void OnPaint()=0;
    ...
};

AbstractWindow::MessageRouter()
{
case WM_PAINT:
    abstract_window->OnPaint();
    return 0;
...
}

void GameWindow::OnPaint()
{
    PAINTSTRUCT ps; 
    HDC hdc = BeginPaint(hwnd, &ps); 
    TextOut(hdc, 0, 0, "Hello, Windows!", 15); 
    EndPaint(hwnd, &ps); 
}