Updated January 29, 2014, 4:42 pm


#ifndef INC_FRAMEWND_H
#define INC_FRAMEWND_H

#include "WndObject.h"
#include "Input.h"
#include "..\HiresTimer.h"

namespace STWin
{
	//Window types
	namespace WindowStyles
	{
		enum types
		{
			WINDOWED = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW,
			FULLSCREEN = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_SYSMENU,
			VIEWPORT = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_CHILD	,
			BORDER = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_SYSMENU | WS_DLGFRAME,
			WINDOWED_NOTSIZEABLE = WS_CAPTION | WS_CLIPSIBLINGS |WS_CLIPCHILDREN | WS_SYSMENU | WS_MINIMIZEBOX,
			WINDOWED_SIZEABLE_NOMAXIMIZE = WS_CAPTION | WS_CLIPSIBLINGS |WS_CLIPCHILDREN | WS_SYSMENU | WS_MINIMIZEBOX | WS_THICKFRAME
		};
	};
	
	class Toolbar;
	class Statusbar;

    class FrameWnd : public WndObject
    {
    public:
		FrameWnd(){};
		//
		//Used by the MDIFrameWnd to create the window
		//
		FrameWnd(const std::string& classname,
			     const std::string& title,
				 DWORD dwStyle,
				 int x,int y,
				 int w,int h,
				 HWND hParent,WORD wMenu,bool fullscreen);
		
	    ~FrameWnd();
		
		//
		//	Every window inheriting FrameWnd must implement update
		//
        virtual void update()=0;

		//
		// Check or uncheck a menu item                                                                     
		//
	    void checkMenuItem(HMENU hMenu,UINT uIDCheckItem,BOOL check);
	    void toggleMenuItem(UINT uIDCheckItem);
		bool isVisible()const;
	    float getFPS()const{return m_FPS;}
		bool isFPSLocked()const{return m_LockFPS;}
		void lockFPS(bool flag){m_LockFPS = flag;}
		float getDeltaTime()const{return m_DeltaTime;}
		unsigned int getTotalTime()const{return m_TotalTime;}
		Input& getInput(){return m_Input;}
		bool isFullScreen()const{return m_FullScreen;}
		bool isCursorInsideWindow();
		bool isCursorInsideClient();
		//
		// returns the cursor position in client coordinates of this window
		//
		POINT getCursorPosition()const;
	    
		boost::shared_ptr<Toolbar> m_Toolbar;
		boost::shared_ptr<Statusbar> m_Statusbar;

		static LRESULT CALLBACK WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);

    protected:
		HINSTANCE m_hInstance;		
	    HMENU m_hMenu;			
	    bool m_FullScreen;
		//
	    //	Title of the window
	    //
		std::string	m_Title;
		//
	    //	Input class for this window
	    //
		Input m_Input;				
	    //
	    //	Hires timer for this window
	    //
		STE::HiresTimer	m_Timer;				
	    //
	    //	Elapsed time between two update calls
	    //
		float m_DeltaTime;
		//
		// total time
		//
		unsigned int m_TotalTime;
		//
		// Frames per second
		//
		float m_FPS;
		bool m_LockFPS;
    
    
	    virtual LRESULT	onCreate(LPCREATESTRUCT lpCreate);
	    virtual void	onClose();
	    virtual void	onSize(int width,int height,int flags);
		virtual void	onSizing(WPARAM wParam,RECT* rect);
	    virtual void	onMove(int clientX,int clientY);
	    virtual void	onWindowPosChanging(LPWINDOWPOS lpPos);
	    virtual void	onPaint();
		virtual unsigned int onEraseBackground();
	    virtual BOOL	onNotify(WPARAM wParam,LPARAM lParam,LRESULT *pResult);
	    virtual void	onCommand(WORD wNotifyCode,WORD wID,HWND hWndCtrl);
	    virtual void	onContextMenu(HWND hWnd,int posX,int posY);
	    virtual LRESULT	onActivate(WPARAM wParam,LPARAM lParam);
	    virtual LRESULT	onNCActivate(HWND hParent,HWND hWnd,WPARAM wParam,LPARAM lParam);
	    virtual LRESULT onEnable(HWND hParent,HWND hWnd,WPARAM wParam,LPARAM lParam);
	    virtual LRESULT	onMouseActivate(HWND hWndTop,int hitTest,UINT uMsg);
	    virtual void	onActivateApp(int activate,DWORD dwThread);
	    virtual void	onHScroll(HWND hScrollBar,int request,int position);
	    virtual void	onVScroll(HWND hScrollBar,int request,int position);
		virtual void	onChar(char charValue){}
		virtual void	onKeyDown(unsigned int virtKeyCode){}
		virtual void	onKeyUp(unsigned int virtKeyCode){}
		virtual void    onMouseMove(WPARAM wParam,const POINT& cursor);	   
		virtual void	onLeftButtonDown(const POINT& cursor){}
		virtual void	onMiddleButtonDown(const POINT& cursor){}
		virtual void	onRightButtonDown(const POINT& cursor){}
		virtual void	onLeftButtonUp(const POINT& cursor){}
		virtual void	onMiddleButtonUp(const POINT& cursor){}
		virtual void	onRightButtonUp(const POINT& cursor){}
		virtual void	onLeftButtonDoubleClick(const POINT& cursor){}
		virtual void	onMiddleButtonDoubleClick(const POINT& cursor){}
		virtual void	onRightButtonDoubleClick(const POINT& cursor){}
	    virtual void	onMouseWheel(int delta);
    		
	    virtual LRESULT	otherMessages(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam);
    };


}
#endif // INC_FRAMEWND_H
</pre>
<pre class="code-snippet">


#include "STWin\FrameWnd.h"
#include "STWin\WndApp.h"
#include "STException.h"
#include "WindowsX.h"
#include "STWin/Statusbar.h"
#include "STWin/Toolbar.h"

#include <locale>

namespace STWin
{
    FrameWnd::FrameWnd(const std::string& className,
					   const std::string& title,
					   DWORD dwStyle,
					   int x,int y,
					   int w,int h,
					   HWND hParent,WORD wMenu,bool fullscreen):
	WndObject(x,y,w,h),
	m_hMenu(NULL),
	m_FullScreen(fullscreen),
	m_Title(title),
	m_DeltaTime(0.0f),
	m_TotalTime(0),
	m_FPS(0.0f),
	m_LockFPS(true)
    {
		
		m_hInstance = (HINSTANCE)GetModuleHandle(NULL);

	    RECT windowRect;
	    windowRect.left	= m_ClientX;
	    windowRect.right	= m_ClientX + m_ClientWidth;
	    windowRect.top	    = m_ClientY;
	    windowRect.bottom	= m_ClientY + m_ClientHeight;

	    
		if(wMenu != NULL)
		{
			m_hMenu = LoadMenu(m_hInstance,MAKEINTRESOURCE(wMenu));
			AdjustWindowRect( &windowRect, dwStyle, true);
		}
		else 
			AdjustWindowRect( &windowRect, dwStyle, false);
    	
        //create window
		m_hWnd = CreateWindowEx(NULL,
            className.c_str(),
            title.c_str(),
            dwStyle,
            windowRect.left,
            windowRect.top,
            windowRect.right - windowRect.left,
            windowRect.bottom - windowRect.top,
            hParent,
            m_hMenu,
            m_hInstance,
            (void*)this);
	 
		if(!m_hWnd)
		{
			throw STE::RunTimeException("Window Creation Failed",FUNCTIONINFO);
	    }
	    m_hDC = GetDC(m_hWnd);
    	
    }


    FrameWnd::~FrameWnd()
    {
		//destroy the window
		DestroyWindow(m_hWnd);
    }

    void FrameWnd::checkMenuItem(HMENU hMenu,UINT uIDCheckItem,BOOL check)
    {
	    if(hMenu)
		    CheckMenuItem(hMenu,uIDCheckItem,check?MF_CHECKED:MF_UNCHECKED);
    }
    void FrameWnd::toggleMenuItem(UINT uIDCheckItem)
    {
	    if(m_hMenu)
		{
		    if(GetMenuState(m_hMenu,uIDCheckItem,MF_BYCOMMAND)==MF_CHECKED)
			    CheckMenuItem(m_hMenu,uIDCheckItem,MF_UNCHECKED);
		    else CheckMenuItem(m_hMenu,uIDCheckItem,MF_CHECKED);
	    }
    }
	bool FrameWnd::isVisible()const
	{
		return (IsWindowVisible(m_hWnd)!=0);
	}
    
    bool FrameWnd::isCursorInsideClient()
    {
	    POINT cursorInClient = m_Input.getCursorPosInClient(m_hWnd);		
		if((cursorInClient.x > 0) && (cursorInClient.x < m_ClientWidth) && 
		   (cursorInClient.y > 0) && (cursorInClient.y < m_ClientHeight))
		    return true;
	    return false;
    }

	bool FrameWnd::isCursorInsideWindow()
	{
		RECT rc;
		GetWindowRect(m_hWnd,&rc);
		POINT cursorInScreen = m_Input.getCursorPosInScreen();		
    	
	    if(cursorInScreen.x>rc.left && cursorInScreen.x < rc.right && cursorInScreen.y > rc.top && cursorInScreen.y < rc.bottom)
		    return true;
	    
		return false;
	}

	POINT FrameWnd::getCursorPosition()const
	{
		return m_Input.getCursorPosInClient(m_hWnd);
	}
   
    LRESULT FrameWnd::onCreate(LPCREATESTRUCT lpCreate)
    {
	    DefWindowProc(m_hWnd,WM_CREATE,0,0);
		return 0;
    }
    void FrameWnd::onContextMenu(HWND hWnd,int posX,int posY)
    {
	    LPARAM lParam = MAKELPARAM(posX,posY);
	    DefWindowProc(m_hWnd,WM_CONTEXTMENU,(WPARAM)hWnd,lParam);
    }
    void FrameWnd::onCommand(WORD wNotifyCode,WORD wID,HWND hWndCtrl)
    {
	    WPARAM wParam = MAKEWPARAM(wID,wNotifyCode);
	    DefWindowProc(m_hWnd, WM_COMMAND, wParam, (LPARAM)hWndCtrl);
    }
    BOOL FrameWnd::onNotify(WPARAM wParam,LPARAM lParam,LRESULT *pResult)
    {
	    DefWindowProc(m_hWnd,WM_NOTIFY,wParam,lParam);
	    return 0;
    }
    void FrameWnd::onActivateApp(int activate,DWORD dwThread)
    {
		if(activate)
		    WndApp::activateApp(true);
	    else
		    WndApp::activateApp(false);

    	
	    DefWindowProc(m_hWnd,WM_ACTIVATEAPP,(WPARAM)activate,(LPARAM)dwThread);
    }
    void FrameWnd::onPaint()
    {
	    DefWindowProc(m_hWnd,WM_PAINT,0,0);
    }
	
	unsigned int FrameWnd::onEraseBackground()
	{
		DefWindowProc(m_hWnd,WM_ERASEBKGND,0,0);
		return 0;
	}

    void FrameWnd::onSize(int width,int height,int flags)
    {
	    LPARAM lParam = MAKELPARAM(width,height);
	    m_ClientWidth = width;
	    m_ClientHeight = height;
	    DefWindowProc(m_hWnd,WM_SIZE,flags,(LPARAM)lParam);
    }
	void FrameWnd::onSizing(WPARAM wParam,RECT* rect)
	{

		DefWindowProc(m_hWnd,WM_SIZING,wParam,(LPARAM)rect);
	}
    void FrameWnd::onMove(int clientX,int clientY)
    {
	    LPARAM lParam = MAKELPARAM(clientX,clientY);
	    
		m_ClientX = clientX;
	    m_ClientY = clientY;
    	
	    DefWindowProc(m_hWnd,WM_MOVE,0,lParam);
    }
    void FrameWnd::onWindowPosChanging(LPWINDOWPOS lpPos)
    {
	    DefWindowProc(m_hWnd,WM_WINDOWPOSCHANGING,0,(LPARAM)lpPos);
    }
    void FrameWnd::onHScroll(HWND hScrollBar,int request,int position)
    {
	    WPARAM wParam = MAKEWPARAM(request,position);
	    DefWindowProc(m_hWnd,WM_HSCROLL,wParam,(LPARAM)hScrollBar);
    }
    void FrameWnd::onVScroll(HWND hScrollBar,int request,int position)
    {
	    WPARAM wParam = MAKEWPARAM(request,position);
	    DefWindowProc(m_hWnd,WM_VSCROLL,wParam,(LPARAM)hScrollBar);
    }
   
	void FrameWnd::onMouseMove(WPARAM wParam,const POINT& cursor)
	{
		LPARAM lParam = MAKELPARAM(cursor.x,cursor.y);
		DefWindowProc(m_hWnd,WM_MOUSEMOVE,wParam,lParam);
	}

	
    void FrameWnd::onMouseWheel(int delta)
    {
	   m_Input.setMouseWheel(delta);
    }
    LRESULT FrameWnd::onActivate(WPARAM wParam,LPARAM lParam)
    {
	    return DefWindowProc(m_hWnd,WM_ACTIVATE,wParam,lParam);
    }
    LRESULT FrameWnd::onNCActivate(HWND hParent,HWND hWnd,WPARAM wParam,LPARAM lParam)
    {
	    return DefWindowProc(m_hWnd,WM_NCACTIVATE,wParam,lParam);
    }
    LRESULT FrameWnd::onEnable(HWND hParent,HWND hWnd,WPARAM wParam,LPARAM lParam)
    {
	    return DefWindowProc(m_hWnd,WM_ENABLE,wParam,lParam);
    }

    LRESULT FrameWnd::onMouseActivate(HWND hwndTop,int hitTest,UINT uMsg)
    {
	    LPARAM lParam = MAKELPARAM(hitTest,uMsg);
	    return DefWindowProc(m_hWnd,WM_MOUSEACTIVATE,(WPARAM)hwndTop,lParam);
    }

    void FrameWnd::onClose()
    {
	    PostQuitMessage(0);
    }

    LRESULT FrameWnd::otherMessages(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
    {
	    return DefWindowProc(hWnd,uMsg,wParam,lParam);
    }

    LRESULT CALLBACK FrameWnd::WndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)
    {
        FrameWnd* window = reinterpret_cast<FrameWnd*>(GetWindowLongPtr(hWnd,GWLP_USERDATA));
        
	    if (!window)
		{	
		    if(uMsg == WM_CREATE)
			{	
			    //set userdata
				window = (FrameWnd*)(((LPCREATESTRUCT)lParam)->lpCreateParams);
			    SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)window);
			    window->m_hWnd= hWnd;
			    return window->onCreate((LPCREATESTRUCT)lParam);
		    }
		    else 
			    return DefWindowProc(hWnd, uMsg, wParam, lParam);
	    }
	    switch (uMsg)											
        {													
		    case WM_CREATE:									
			    return window->onCreate((LPCREATESTRUCT)lParam);
		    
			case WM_CONTEXTMENU:
			    window->onContextMenu((HWND)wParam,LOWORD(lParam),HIWORD(lParam));	
			    return 0;
		    case WM_COMMAND:
			    window->onCommand(HIWORD(wParam),LOWORD(wParam),(HWND)lParam);
			    return 0;
		    case WM_NOTIFY:
			    LRESULT lp;
			    window->onNotify(wParam,lParam,&lp);				
			    return lp;
		    
			case WM_SIZE:
			    window->onSize(LOWORD(lParam),HIWORD(lParam),(int)wParam);
			    return 0;
			
			case WM_SIZING:
				window->onSizing(wParam,(RECT*)lParam);
				return TRUE;
		   
			case WM_MOVE:
			    window->onMove((int)(short)LOWORD(lParam),(int)(short) HIWORD(lParam));
			    return 0;
		    
			case WM_WINDOWPOSCHANGING:
			    window->onWindowPosChanging((LPWINDOWPOS)lParam);
			    return 0;
		    
			case WM_PAINT:
			    window->onPaint();
			    return 0;

			case WM_ERASEBKGND:
				return window->onEraseBackground();
		   
			case WM_HSCROLL:
			    window->onHScroll((HWND)lParam,LOWORD(wParam),HIWORD(wParam));
			    return 0;
		    
			case WM_VSCROLL:
			    window->onVScroll((HWND)lParam,LOWORD(wParam),HIWORD(wParam));
			    return 0;
		    
			case WM_CHAR:
				window->onChar(wParam);
				return 0;
			
			case WM_KEYDOWN:
				window->m_Input.m_Keys[wParam] = true;
				window->onKeyDown(wParam);
			    return 0;

			case WM_KEYUP:
				window->m_Input.m_Keys[wParam] = false;
				return 0;

			case WM_MOUSEMOVE:
				{
					POINT cursor = {LOWORD(lParam),HIWORD(lParam)};
					window->onMouseMove(wParam,cursor);
				}
				return 0;
			
			case WM_LBUTTONDOWN:
				{
					POINT cursor = {GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam)};
					window->m_Input.leftMBDown();
					window->onLeftButtonDown(cursor);
				}
				return 0;

			case WM_LBUTTONDBLCLK:
				{
					POINT cursor = {GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam)};
					window->onLeftButtonDoubleClick(cursor);
				}
			    return 0;
		    
			case WM_LBUTTONUP:
				{
					POINT cursor = {GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam)};
					window->m_Input.leftMBUp();
					window->onLeftButtonUp(cursor);
				}
			    return 0;
		   
			case WM_MBUTTONDOWN:
				{
					POINT cursor = {GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam)};
					window->m_Input.middleMBDown();
					window->onMiddleButtonDown(cursor);
				}
				return 0;
			
			case WM_MBUTTONDBLCLK:
				{
					POINT cursor = {GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam)};
					window->onMiddleButtonDoubleClick(cursor);
				}
				return 0;
			
			case WM_MBUTTONUP:
				{
					POINT cursor = {GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam)};
					window->m_Input.middleMBUp();
					window->onMiddleButtonUp(cursor);
				}
				return 0;
		    
			case WM_RBUTTONDOWN:
				{
					POINT cursor = {GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam)};
					window->m_Input.rightMBDown();
					window->onRightButtonDown(cursor);
				}
			    break;//leave the contextmenu to DefProc
		    
			case WM_RBUTTONDBLCLK:
				{
					POINT cursor = {GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam)};
					window->onRightButtonDoubleClick(cursor);
				}
			    return 0;
		    
			case WM_RBUTTONUP:
				{
					POINT cursor = {GET_X_LPARAM(lParam),GET_Y_LPARAM(lParam)};
					window->m_Input.rightMBUp();
					window->onRightButtonUp(cursor);
				}
			    break;//leave the contextmenu to DefProc
		    
			case WM_MOUSEWHEEL:
			    window->onMouseWheel(HIWORD(wParam));
			    return 0;
            
		    case WM_MOUSEACTIVATE:
			    return window->onMouseActivate((HWND)wParam,(int) LOWORD(lParam),(UINT) HIWORD(lParam));
		   
			case WM_ACTIVATEAPP:
			    window->onActivateApp((BOOL) wParam,(DWORD) lParam);
 			    return 0;
		    
			case WM_ACTIVATE:
			    window->onActivate(wParam,lParam);
			    return 0;
		    
			case WM_NCACTIVATE:
			    return window->onNCActivate(window->m_hWnd,window->m_hWnd,wParam,lParam);
		    
			case WM_ENABLE:
			    return window->onEnable(window->m_hWnd,window->m_hWnd,wParam,lParam);
		    
			case WM_DESTROY:
			    DefWindowProc(hWnd,uMsg,wParam,lParam);
			    return 0;
		   
			case WM_CLOSE:
			    window->onClose();
			    return 0;
		    
			default:
				break;
				
	    }
	    //do default message processing
	    return window->otherMessages(hWnd,uMsg,wParam,lParam);
		
    }
}