Click here to Skip to main content
15,893,663 members
Articles / Containers / Virtual Machine

TOOL

Rate me:
Please Sign up or sign in to vote.
4.98/5 (52 votes)
23 Oct 200676 min read 231K   5.4K   147  
TOOL (Tiny Object Oriented Language) is an easily-embedded, object-oriented, C++-like-language interpreter. The purpose of this article is to introduce the TOOL interpreter and language from the perspective of a person who has a desire to include a scripting solution as part of his project.
/*****************************************************************************/
/*                              SOURCE FILE                                  */
/*****************************************************************************/
/*
          $Archive:   $

         $Revision:   $

      Last Checkin:
             $Date:   $
                By:
           $Author:   $

 Last Modification:
          $ModTime:   $

       Description:   The main window for the XML forms window

                      TOOL And XML FORMS License
                      ==========================

                      Except where otherwise noted, all of the documentation 
                      and software included in the TOOL package is 
                      copyrighted by Michael Swartzendruber.

                      Copyright (C) 2005 Michael John Swartzendruber. 
                      All rights reserved.

                      Access to this code, whether intentional or accidental,
                      does NOT IMPLY any transfer of rights.

                      This software is provided "as-is," without any express 
                      or implied warranty. In no event shall the author be held
                      liable for any damages arising from the use of this software.

                      Permission is granted to anyone to use this software for 
                      any purpose, including commercial applications, and to 
                      alter and redistribute it, provided that the following 
                      conditions are met:

                      1. All redistributions of source code files must retain 
                         all copyright notices that are currently in place, 
                         and this list of conditions without modification.

                      2. The origin of this software must not be misrepresented;
                         you must not claim that you wrote the original software.

                      3. If you use this software in another product, an acknowledgment
                         in the product documentation would be appreciated but is
                         not required.

                      4. Modified versions in source or binary form must be plainly 
                         marked as such, and must not be misrepresented as being 
                         the original software.
*/
static char OBJECT_ID[] = "$Revision:   $ : $JustDate:   $";
/*****************************************************************************/


#include <map>
#include <math.h>
#include <fstream>	// 2b|!2b==?

#include "stdafx.h"
#include "XMLFormTools.h"
#include "XMLFormErrorPopup.h"
#include "XMLFormFacade.h"
#include "XMLFormWindow.h"
#include "XMLFormControlFactory.h"

#include "../../Utilities/InterpreterCore/APIClasses/VMReportPage.h"
#include "../../Utilities/VMFacade.h"


#pragma warning( disable : 4786 )


HHOOK CXMLFormWindow::m_hOldHook = NULL;  // global hook procedure.

typedef std::map< HWND, CXMLFormWindow*> INSTANCES_MAP;
typedef INSTANCES_MAP::iterator          INSTANCES_ITER;

INSTANCES_MAP  oInstances;
WNDPROC        pfnXMLFormWndProc = 0;


// HitTest Constants
//
#define DHT_CLOSE       0x01
#define DHT_CAPTION     0x02
#define DHT_MINIMIZE    0x08


IMPLEMENT_DYNCREATE( CXMLFormWindow, CFrameWnd )


BEGIN_MESSAGE_MAP( CXMLFormWindow, CFrameWnd )
  //{{AFX_MSG_MAP( CXMLFormWindow )
  ON_WM_NCPAINT()
  ON_WM_ACTIVATE()
  ON_WM_NCACTIVATE()
  ON_WM_NCLBUTTONDOWN() 
  ON_WM_LBUTTONUP()
  ON_WM_CTLCOLOR()
  ON_WM_ERASEBKGND()
  ON_WM_CREATE()
  ON_WM_PAINT()
  ON_WM_SIZE()
  ON_WM_NCHITTEST()
  ON_WM_LBUTTONDOWN()
  ON_WM_RBUTTONDOWN()
  ON_WM_DESTROY()
  //}}AFX_MSG_MAP
END_MESSAGE_MAP()


const COLORREF cDefaultBackground = ::GetSysColor( COLOR_BTNFACE );
const COLORREF cDefaultText       = ::GetSysColor( COLOR_BTNTEXT );


/*****************************************************************************/
/*

     FUNCTION NAME:  CXMLFormWindow::CXMLFormWindow

       DESCRIPTION:  ctor. inits this

             INPUT:  none
            OUTPUT:  none

           RETURNS:  none
*/
CXMLFormWindow::CXMLFormWindow( bool bSizeable, bool bModal )
{
  m_bModal               = bModal;
  m_bDrawGripper         = bSizeable;
  m_oValidationErrorText = _T( "" );
  m_poPopup              = NULL;
  m_poPopupOwner         = NULL;
  m_poObserver           = NULL;
  m_xBackgroundColor     = cDefaultBackground;
  m_xTextColor           = cDefaultText;
  m_poFactory            = NULL;
  m_poOwner              = NULL;
  m_bDestroyed           = false;
  m_poHasFocus           = NULL;
  m_poHadFocusLast       = NULL;
  m_poRenderEngine       = NULL;
  m_bTreatAsControl      = false;

  m_oBrush.CreateSolidBrush( m_xBackgroundColor ); 
}
/* End of function "CXMLFormWindow::CXMLFormWindow"
/*****************************************************************************/


/*****************************************************************************/
/*

     FUNCTION NAME:  CXMLFormWindow::~CXMLFormWindow

       DESCRIPTION:  dtor. removes all allocations from the heap

             INPUT:  none
            OUTPUT:  none

           RETURNS:  none
*/
CXMLFormWindow::~CXMLFormWindow( void )
{
  delete m_poFactory;
  delete m_poRenderEngine;
//  DestroyAcceleratorTable( m_hAccelerator );
}
/* End of function "CXMLFormWindow::~CXMLFormWindow"
/*****************************************************************************/


/*****************************************************************************/
/*

     FUNCTION NAME:  CXMLFormWindow::SetBackgroundColor

       DESCRIPTION:  change our background color

             INPUT:  xNewBackgroundColor - the new background color
            OUTPUT:  none

           RETURNS:  void
*/
void CXMLFormWindow::SetBackgroundColor( COLORREF xNewBackgroundColor )
{
  m_xBackgroundColor = xNewBackgroundColor;
  m_oBrush.DeleteObject();
  m_oBrush.CreateSolidBrush( m_xBackgroundColor );
  InvalidateSpecialKids();
  Invalidate();
}
/* End of function "CXMLFormWindow::SetBackgroundColor"
/*****************************************************************************/


/*****************************************************************************/
/*

     FUNCTION NAME:  CXMLFormWindow::SetTextColor

       DESCRIPTION:  change our text color

             INPUT:  COLORREF xNewTextColor 
            OUTPUT:  none

           RETURNS:  void  
*/
void CXMLFormWindow::SetTextColor( COLORREF xNewTextColor )
{
  m_xTextColor = xNewTextColor;
  InvalidateSpecialKids();
  Invalidate();
}
/* End of function "CXMLFormWindow::SetTextColor"
/*****************************************************************************/


/*****************************************************************************/
/*

     FUNCTION NAME:  CXMLFormWindow::CreateErrorWindow

       DESCRIPTION:  creates a simple edit window for use in the error popup
                     text box

             INPUT:  none
            OUTPUT:  none

           RETURNS:  void 
*/
void CXMLFormWindow::CreateErrorWindow( void )
{
  CRect oRect;
  oRect.top    = 0;
  oRect.bottom = 75;
  oRect.right  = 340;
  oRect.left   = 0;

  m_oPopupText.CreateEx( WS_EX_OVERLAPPEDWINDOW, 
                         _T( "EDIT" ), 
                         _T( "" ), 
                         WS_CHILD | WS_VSCROLL | WS_HSCROLL | ES_READONLY | ES_MULTILINE, 
                         oRect, 
                         this, 
                         NULL );
}
/* End of function "CXMLFormWindow::CreateErrorWindow"
/*****************************************************************************/


/*****************************************************************************/
/*

     FUNCTION NAME:  CXMLFormWindow::OnCreate

       DESCRIPTION:  post construction....completes the initialization of this

             INPUT:  lpCreateStruct - see MFC docs
            OUTPUT:  none

           RETURNS:  0 if good, -1 if not
*/
int CXMLFormWindow::OnCreate( LPCREATESTRUCT lpCreateStruct ) 
{
  if ( CWnd::OnCreate( lpCreateStruct ) == -1 )
    return -1;

  if ( m_bCustomRender == true )
  {
    m_poRenderEngine = new VMFacade();
    m_poRenderEngine->SetDebuggerHook( NULL );
    m_poRenderEngine->CompileText( m_oRenderCode );
  }

  if ( m_bModal )
  {
    if ( m_hOldHook == NULL ) 
    {
#ifdef VC_60_BUILD
       CWinThread*  MyThread = AfxGetThread();        
       m_hOldHook = SetWindowsHookEx( WH_MOUSE, 
                                    (HOOKPROC)CXMLFormWindow::LocalMouseFunc, 
                                      AfxGetInstanceHandle(), 
                                     (DWORD)MyThread->m_nThreadID );
#else
       m_hOldHook = SetWindowsHookEx( WH_MOUSE, 
                                    (HOOKPROC)CXMLFormWindow::LocalMouseFunc, 
                                      AfxGetInstanceHandle(), 
                                     (DWORD)::GetCurrentThreadId() );
#endif
    }
  }

  // have to install our own local wnd proc to get messages from the
  // child windows created here....
  //
  //
  WNDPROC pfn = reinterpret_cast<WNDPROC>( ::SetWindowLong( this->m_hWnd, 
                                                            GWL_WNDPROC, 
                                                            reinterpret_cast<long>( LocalWndProc ) ) );
  if ( !pfnXMLFormWndProc ) 
    pfnXMLFormWndProc = pfn;

  // add this to the instance map so that wnd proc can select this object from 
  // the HWND parameter passed to it.
  //
  m_hMyWindowHandle = this->m_hWnd;
  oInstances.insert( INSTANCES_MAP::value_type( this->m_hWnd, this ) );

  CreateErrorWindow();

  // Remember the original size so later the resizer 
  // can calculate how to place the controls when the
  // dialog resizes
  //
  GetWindowRect( m_oOriginalSize );

  m_poFactory = new CXMLFormControlFactory( this );  

  m_poFactory->SetFormDefinition( &(m_poOwner->m_oParser.m_oPropPages) );

  m_poFactory->SetCurrentPropertyPage( 0 );


  PAGE_DEFINITION_SET_ITER oPagesIter = m_poOwner->m_poFormSetData->find( m_poOwner->m_oCurrentSheetName );
  if ( oPagesIter != m_poOwner->m_poFormSetData->end() )
  {
    P_FORM_DEFINITION     pxForm = (*oPagesIter).second;

    SetTextColor( pxForm->m_xTextColor );
    this->SetBackgroundColor( pxForm->m_xBackColor );
  }

  // since this is resizeable, need to do specialized initialiazation
  // of the resize controller...
  //
  if ( m_bDrawGripper )
  {
    // attach the 'main resizer' to the dialog before
    // any property page (and their controls) are added
    //
    m_oResizeHelper.Attach( m_hWnd, m_oOriginalSize );

    // add each child control to the resize controller
    //
    PAGE_DEFINITION_SET_ITER oPagesIter = m_poOwner->m_poFormSetData->find( m_poOwner->m_oCurrentSheetName );
    if ( oPagesIter != m_poOwner->m_poFormSetData->end() )
    {
      P_FORM_DEFINITION     pxForm = (*oPagesIter).second;
      FORM_CONTROL_MAP_ITER oCtrlIter;

      for ( oCtrlIter = pxForm->m_oControlsMap.begin();
            oCtrlIter != pxForm->m_oControlsMap.end();
            oCtrlIter++ )
      {
        P_FORM_CONTROL pxCtrl = (*oCtrlIter).second;
        m_oResizeHelper.Add( pxCtrl->m_iCtrlID, 
                             (eHorizontalFix)pxCtrl->m_eXAnchor, 
                             (eVerticalFix)  pxCtrl->m_eYAnchor );

        if ( pxCtrl->m_eCtrlType != eSubForm && pxCtrl->m_bForcedHidden == false )
        {
          pxCtrl->m_poControl->ShowWindow( SW_SHOW );
        }

        if ( pxCtrl->m_chAltNavKey != 0 )
        {
//          m_axAccelerators[ m_iAcceleratorCount ].cChar    = pxCtrl->m_chAltNavKey;
//          m_axAccelerators[ m_iAcceleratorCount ].cVirtKey = VK_ALT;
//          m_axAccelerators[ m_iAcceleratorCount ].wID      = pxCtrl->m_iCtrlID;
        }
      }
    }
  }

//  m_hAccelerator = CreateAcceleratorTable( m_axAccelerators, m_iAcceleratorCount );

  return 0;
}
/* End of function "CXMLFormWindow::OnCreate"
/*****************************************************************************/


/*****************************************************************************/
/*
     FUNCTION NAME:	MouseFunc

       DESCRIPTION:	Mouse Hook Function -- Refer to the SDK 
                                           topic MouseProc for details.

                    If the action is WM_LBUTTONDOWN and WM_NCLBUTTONDOWN, 
                    do the following:
                       If the active window is a Pinup dialog, then 
                        If the mouse click is within the dialog, then do nothing.
                       If the click is outside, call a virtual function to 
                        handle the processing.

             INPUT: void	
           RETURNS:	If the virtual function returns TRUE, 
                    Pass the message onto the next hook.
                    Else, discard the message by returning 1.
*/
LRESULT CALLBACK CXMLFormWindow::LocalMouseFunc( int nCode, WPARAM wParam, LPARAM lParam )
{
  MOUSEHOOKSTRUCT *lpStruct;
  BOOL bRet = TRUE;

  if ( nCode >= 0 ) 
  {
    if( ( wParam == WM_NCLBUTTONDOWN ) ||( wParam == WM_LBUTTONDOWN ) ) 
    {
      CWnd *pWnd = GetActiveWindow();
      if ( pWnd ) 
      {
        if ( pWnd->IsKindOf( RUNTIME_CLASS( CXMLFormWindow ) ) ) 
        {
          CXMLFormWindow *pThis = (CXMLFormWindow *)pWnd;
          ASSERT( pThis );
          lpStruct = (LPMOUSEHOOKSTRUCT) lParam;
          if ( !pThis->IsPtInDialog( lpStruct->pt ) )
            bRet = pThis->DoClickProcessing();
        }
      }
    }
  }

  // If bRet == 1, then pass the message on, else discard by returning 1.
  //
  if ( bRet )
    return CallNextHookEx( m_hOldHook, nCode, wParam, lParam );
  else
    return 1;  // Discard message.
}
/*	end of functions "MouseFunc" */
/*****************************************************************************/


/*****************************************************************************/
/*
     FUNCTION NAME:	IsPtInDialog

       DESCRIPTION:	Determines if the mouse's click location is in this dialog
                    hot spot

             INPUT: pt - screen coordinates of point
           RETURNS:	TRUE if point is inside dialog, FALSE otherwise
*/
BOOL CXMLFormWindow::IsPtInDialog( POINT pt )
{
  BOOL bRtn = FALSE;                // assume point not in dialog
  RECT rect;

  GetWindowRect( &rect );
    
  if ( PtInRect( &rect, pt ) )
  {  
     bRtn = TRUE;
  }
 return bRtn;
}
/*	end of functions "IsPtInDialog" */
/*****************************************************************************/


/*****************************************************************************/
/*
     FUNCTION NAME:	DoClickProcessing

       DESCRIPTION:	virtual function to handle mouse clicks outside dialog. 
                    Called from MouseFunc (mouse hook function)
 
                    If the dialog is pinned up, returning TRUE will cause the 
                    mouse function to pass the message to the next hook function. 
                    If not, the function just beeps and discards the message.
                    
                    Note: Made virtual so that you can change the functionality.

             INPUT: void	
           RETURNS:	Returns TRUE if the dialog is pinned up, FALSE otherwise.
*/
BOOL CXMLFormWindow::DoClickProcessing( void ) 
{
  if ( m_bModal ) 
  {
    MessageBeep( 1 );
    return FALSE;   // Causes MouseFunc to discard the message.
  }
  else
    return TRUE;
}
/*	end of functions "DoClickProcessing" */
/*****************************************************************************/


/*****************************************************************************/
/*

     FUNCTION NAME:  CXMLFormWindow::OnDestroy

       DESCRIPTION:  does some clean up related to the destruction of this

             INPUT:  void 
            OUTPUT:  none

           RETURNS:  void  
*/
void CXMLFormWindow::OnDestroy( void )
{
  INSTANCES_ITER  oIter = oInstances.find( m_hMyWindowHandle );
  if ( oIter != oInstances.end() )
  {
    oInstances.erase( oIter );
  }
  if ( 0 == oInstances.size() )
  {
    WNDPROC pfn = reinterpret_cast<WNDPROC>( ::SetWindowLong( this->m_hWnd, 
                                                              GWL_WNDPROC, 
                                                              reinterpret_cast<long>( pfnXMLFormWndProc ) ) );
    if ( m_hOldHook )
    {
      UnhookWindowsHookEx( m_hOldHook );
    }
  }
  m_bDestroyed = true;
  m_oPopupText.DestroyWindow();
  CWnd::OnDestroy();
}
/* End of function "CXMLFormWindow::OnDestroy"
/*****************************************************************************/


/*****************************************************************************/
/*

     FUNCTION NAME:  CXMLFormWindow::RefreshControlsInRect

       DESCRIPTION:  invalidates and forces a paint of all controls in the
                     given rect

             INPUT:  none
            OUTPUT:  none

           RETURNS:  void
*/
void CXMLFormWindow::RefreshControlsInRect( CRect& roRect )
{
  CWnd* poKid = GetWindow( GW_CHILD );

  while( NULL != poKid )
  {
    CRect oRect;
    poKid->GetWindowRect( oRect );
    ScreenToClient( oRect );

    if ( ( roRect.PtInRect( CPoint( oRect.left,  oRect.top    ) ) )
      || ( roRect.PtInRect( CPoint( oRect.left,  oRect.bottom ) ) )
      || ( roRect.PtInRect( CPoint( oRect.right, oRect.top    ) ) )
      || ( roRect.PtInRect( CPoint( oRect.right, oRect.bottom ) ) ) )
    {
      poKid->Invalidate( TRUE );
      InvalidateRect( oRect );
    }
    poKid = poKid->GetWindow( GW_HWNDNEXT );
  }
  InvalidateRect( roRect );
}
/* End of function "CXMLFormWindow::RefreshControlsInRect"
/*****************************************************************************/


/*****************************************************************************/
/*

     FUNCTION NAME:  CXMLFormWindow::OnPaint

       DESCRIPTION:  paint the back ground 'dialog grey'

             INPUT:  none
            OUTPUT:  none

           RETURNS:  void
*/
void CXMLFormWindow::OnPaint() 
{
  CPaintDC oDC( this );

  CRect oRect;
  GetClientRect( oRect );
   
  oDC.FillSolidRect( oRect, m_xBackgroundColor );

  if ( m_bCustomRender )
  {
    // the following setup is *REQUIRED* since this is how the 
    // script engine gets the 'paint context' If this work is
    // *NOT* done the script engine will throw an exception
    //
    VMPageInitInfo oPageInfo;
    oPageInfo.m_dblZoomFactor = 1.0;
    oPageInfo.m_poPageCDC     = &oDC;
    oPageInfo.m_xPageRect     = oRect;
    oPageInfo.m_xPageRect.top = 5;
    oPageInfo.m_iMappingMode  = MM_ISOTROPIC; //MM_TEXT;

    m_poRenderEngine->SetVMPageInitInfo( &oPageInfo );
//    m_poRenderEngine->CompileText( (const char*)m_oRenderCode );
    m_poRenderEngine->Execute( (const char*)m_oRenderEntry );

  }

  // Draw a resizing gripper at the lower left corner
  //
  // Note: Make sure you leave enough space in your dialog template
  // for the gripper to be drawn.
  // Don't put any controls on the lower left corner.
  //
  if ( m_bDrawGripper )
  {
    CRect oRect;

    CPen oBlack;
    CPen oGray;
    CPen oWhite;

    oBlack.CreatePen( PS_SOLID, 1, GetSysColor( COLOR_3DDKSHADOW ) );
    oGray.CreatePen(  PS_SOLID, 1, GetSysColor( COLOR_BTNFACE ) );
    oWhite.CreatePen( PS_SOLID, 1, GetSysColor( COLOR_BTNHIGHLIGHT ) );

    GetClientRect( oRect );

    m_oGripperRect = oRect;

    oRect.left = oRect.right  - GetSystemMetrics( SM_CXHSCROLL );
    oRect.top  = oRect.bottom - GetSystemMetrics( SM_CYVSCROLL );

    CPen* poOldPen = oDC.SelectObject( &oWhite );
    oDC.MoveTo( oRect.left,  oRect.bottom );
    oDC.LineTo( oRect.right, oRect.top    );
    oRect.DeflateRect( 1, 1, 0, 0 );
    oDC.SelectObject( &oGray );
    oDC.MoveTo( oRect.left,  oRect.bottom );
    oDC.LineTo( oRect.right, oRect.top    );
    oRect.DeflateRect( 1, 1, 0, 0 );
    oDC.SelectObject( &oBlack );
    oDC.MoveTo( oRect.left,  oRect.bottom );
    oDC.LineTo( oRect.right, oRect.top    );
    oRect.DeflateRect( 3, 3, 0, 0 );

    oDC.SelectObject( &oWhite );
    oDC.MoveTo( oRect.left,  oRect.bottom );
    oDC.LineTo( oRect.right, oRect.top    );
    oRect.DeflateRect( 1, 1, 0, 0 );
    oDC.SelectObject( &oGray );
    oDC.MoveTo( oRect.left,  oRect.bottom );
    oDC.LineTo( oRect.right, oRect.top    );
    oRect.DeflateRect( 1, 1, 0, 0 );
    oDC.SelectObject( &oBlack );
    oDC.MoveTo( oRect.left,  oRect.bottom );
    oDC.LineTo( oRect.right, oRect.top    );
    oRect.DeflateRect( 3, 3, 0, 0 );

    oDC.SelectObject( &oWhite );
    oDC.MoveTo( oRect.left,  oRect.bottom );
    oDC.LineTo( oRect.right, oRect.top    );
    oRect.DeflateRect( 1, 1, 0, 0 );
    oDC.SelectObject( &oGray );
    oDC.MoveTo( oRect.left,  oRect.bottom );
    oDC.LineTo( oRect.right, oRect.top    );
    oRect.DeflateRect( 1, 1, 0, 0 );
    oDC.SelectObject( &oBlack );
    oDC.MoveTo( oRect.left,  oRect.bottom );
    oDC.LineTo( oRect.right, oRect.top    );

/*
    oDC.SelectObject( &oBlack );
    oDC.MoveTo( oRect.left,  oRect.bottom );
    oDC.LineTo( oRect.right, oRect.top    );
    oRect.DeflateRect( 2, 2, 0, 0 );
    oDC.SelectObject( &oWhite );
    oDC.MoveTo( oRect.left,  oRect.bottom );
    oDC.LineTo( oRect.right, oRect.top    );
    oRect.DeflateRect( 3, 3, 0, 0 );

    oDC.SelectObject( &oBlack );
    oDC.MoveTo( oRect.left,  oRect.bottom );
    oDC.LineTo( oRect.right, oRect.top    );
    oRect.DeflateRect( 2, 2, 0, 0 );
    oDC.SelectObject( &oWhite );
    oDC.MoveTo( oRect.left,  oRect.bottom );
    oDC.LineTo( oRect.right, oRect.top    );
    oRect.DeflateRect( 3, 3, 0, 0 );

    oDC.SelectObject( &oBlack );
    oDC.MoveTo( oRect.left,  oRect.bottom );
    oDC.LineTo( oRect.right, oRect.top    );
    oRect.DeflateRect( 2, 2, 0, 0 );
    oDC.SelectObject( &oWhite );
    oDC.MoveTo( oRect.left,  oRect.bottom );
    oDC.LineTo( oRect.right, oRect.top    );
*/
    oDC.SelectObject( poOldPen );
  }
}
/* End of function "CXMLFormWindow::OnPaint"
/*****************************************************************************/


/*****************************************************************************/
/*

     FUNCTION NAME:  CXMLFormWindow::OnSize

       DESCRIPTION:  when resized, call on the resizer helpers to resize/locate 
                     all the controls on the dialog

             INPUT:  iType   - see MFC docs
                     iDeltaX - see MFC docs
                     iDeltaY - see MFC docs
            OUTPUT:  

           RETURNS:  void  - 
*/
void CXMLFormWindow::OnSize( UINT iType, int iDeltaX, int iDeltaY ) 
{
  // controls with pop-focus get strange sizes on resizing, so set
  // focus to the okay button before resize
  //
  CWnd* poOkay = GetDlgItem( IDOK );
  if ( poOkay != NULL )
  {  
    poOkay->SetFocus();
  }

  CWnd::OnSize( iType, iDeltaX, iDeltaY );

  if ( m_bDrawGripper )
  {
    m_oResizeHelper.OnSize();
  }

  // When enlarging a dialog box we need to erase the old gripper 
  //
  if ( m_bDrawGripper )
  {
    InvalidateRect( m_oGripperRect );
  }

  CRect oRect;
  GetClientRect( oRect );
  InvalidateRect( oRect );
}
/* End of function "CXMLFormWindow::OnSize"
/*****************************************************************************/


/*****************************************************************************/
/*

     FUNCTION NAME:  CXMLFormWindow::ShowErrors

       DESCRIPTION:  does the small amount of work required to put up the 
                     error text ( from validation ) into a popup window

             INPUT:  iButtonID - the button that was clicked when the error
                                 occurred
            OUTPUT:  none

           RETURNS:  void
*/
void CXMLFormWindow::ShowErrors( UINT iButtonID )
{
  m_poPopupOwner = GetDlgItem( iButtonID );
  CXMLFormWindowRect rcCaller( m_poPopupOwner );

  m_oPopupText.SetWindowText( m_oValidationErrorText );
  CXMLFormErrorPopup* pPopup = (CXMLFormErrorPopup*)RUNTIME_CLASS(CXMLFormErrorPopup)->CreateObject();
  m_poPopup = pPopup;
  pPopup->Display( &m_oPopupText, m_poPopupOwner, rcCaller );
}
/* End of function "CXMLFormWindow::ShowErrors"
/*****************************************************************************/


/*****************************************************************************/
/*

     FUNCTION NAME:  CXMLFormWindow::LocalWndProc

       DESCRIPTION:  For some reason, the AFX message maps do not work in this
                     window now....so, have implemented local wnd proc for 
                     processing messages from the kids

             INPUT:  hWnd - used as a look up key to the instance map
                     message - see MFC docs
                     wParam -  see MFC docs
                     lParam -  see MFC docs
            OUTPUT:  

           RETURNS:  FALSE if the message was processed here, otherwise result
                     of call to regular wnd proc
*/
LRESULT CALLBACK CXMLFormWindow::LocalWndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
  // using the hwnd as a key, look up the object instance 
  // that this specific message should be routed to
  //
  INSTANCES_ITER  oIter = oInstances.find( hWnd );
  if ( oIter != oInstances.end() )
  {
    CXMLFormWindow* poWindow = (*oIter).second;


    // the contrls will all 'forward special keys' here for handling by the special-key-handler
    //
    if ( WM_CHAR == message )
    {
      return( poWindow->m_poOwner->SpecialKeyHandler()->SpecialKeyboardHandling( (int)wParam ) );
    }
    else
    // process the message for the user changing the trade type
    // this is how the property pages get flipped
    //
    if ( WM_COMMAND == message && HIWORD( wParam ) == LBN_SELCHANGE )
    {
      int iItemID = LOWORD( wParam );
      return FALSE;
    }
    //
    // process all button clicks and route them accordingly
    //
    else
    if ( WM_COMMAND == message && HIWORD( wParam ) == BN_CLICKED )
    {
      int iItemID = LOWORD( wParam );
      switch( iItemID )
      {
        case 0:
        return FALSE;
        break;

        default:
          if ( poWindow->m_poObserver )
          {
            // execute on click handler 
            //
            P_FORM_DEFINITION     pxForm = NULL;
  
            PAGE_DEFINITION_SET_ITER oPagesIter = poWindow->m_poOwner->m_poFormSetData->find( poWindow->m_poOwner->m_oCurrentSheetName );
            if ( oPagesIter != poWindow->m_poOwner->m_poFormSetData->end() )
            {
              P_FORM_DEFINITION     pxForm = (*oPagesIter).second;

              if ( poWindow->m_poHasFocus != NULL )
              {
                FORM_ACTIONS_ITER oFormActions = pxForm->m_oFormActions.find( poWindow->m_poHasFocus->GetDlgCtrlID() );
                if ( oFormActions != pxForm->m_oFormActions.end() ) 
                {
                  CTRL_ACTIONS* poActions = (*oFormActions).second;
                  CTRL_ACTIONS_ITER oCtrlActions = poActions->find( eOnButtonClick );
                  if ( oCtrlActions != poActions->end() )
                  {
                    std::string oScriptEntry = (*oCtrlActions).second;

                    // the following setup is *REQUIRED* since this is how the 
                    // script engine gets the 'form context' If this work is
                    // *NOT* done the script engine will throw an exception
                    //
                    pxForm->m_poFacade->SetVmXmlFormInfo( poWindow->m_poOwner );
                    pxForm->m_poFacade->SetVar( poWindow->m_poOwner->m_poArguments, 
                                                poWindow->m_poOwner->m_bChildOwnsPointers );
                    pxForm->m_poFacade->SetDebuggerHook( NULL );
                    pxForm->m_poFacade->Execute( oScriptEntry.c_str() );
                  }
                }
              }
            }
            poWindow->m_poObserver->ButtonClick( iItemID );
            return( FALSE );
          }
          else
          {
            return FALSE;
          }
        break;
      }
    }
    else
    //
    // have to process all of these messages from the combo boxes
    // primarily to let the parent know we have a child in focus
    // since the combo box has a lot more ways to indicate that it
    // has gained/lost focus....
    //
    if ( ( WM_COMMAND == message )
      && ( ( HIWORD( wParam ) == CBN_SETFOCUS  ) 
        || ( HIWORD( wParam ) == CBN_SELCHANGE )  
        || ( HIWORD( wParam ) == CBN_SELENDOK  )  
        || ( HIWORD( wParam ) == CBN_DROPDOWN  ) 
        || ( HIWORD( wParam ) == CBN_DBLCLK    ) ) )
    {
      if ( HIWORD( wParam ) == CBN_SELENDOK )
      {
        if ( poWindow->m_poObserver )
        {
          // execute on click handler 
          //
          P_FORM_DEFINITION     pxForm = NULL;
  
          PAGE_DEFINITION_SET_ITER oPagesIter = poWindow->m_poOwner->m_poFormSetData->find( poWindow->m_poOwner->m_oCurrentSheetName );
          if ( oPagesIter != poWindow->m_poOwner->m_poFormSetData->end() )
          {
            P_FORM_DEFINITION     pxForm = (*oPagesIter).second;

            if ( poWindow->m_poHasFocus != NULL )
            {
              FORM_ACTIONS_ITER oFormActions = pxForm->m_oFormActions.find( poWindow->m_poHasFocus->GetDlgCtrlID() );
              if ( oFormActions != pxForm->m_oFormActions.end() ) 
              {
                CTRL_ACTIONS* poActions = (*oFormActions).second;
                CTRL_ACTIONS_ITER oCtrlActions = poActions->find( eOnComboBoxSelChange );
                if ( oCtrlActions != poActions->end() )
                {
                  std::string oScriptEntry = (*oCtrlActions).second;

                  // the following setup is *REQUIRED* since this is how the 
                  // script engine gets the 'form context' If this work is
                  // *NOT* done the script engine will throw an exception
                  //
                  pxForm->m_poFacade->SetVmXmlFormInfo( poWindow->m_poOwner );
                  pxForm->m_poFacade->SetVar( poWindow->m_poOwner->m_poArguments, 
                                              poWindow->m_poOwner->m_bChildOwnsPointers );
                  pxForm->m_poFacade->SetDebuggerHook( NULL );
                  pxForm->m_poFacade->Execute( oScriptEntry.c_str() );
                }
              }
            }
          }
        }
      }
      return FALSE;
    }
    else
    if ( ( WM_COMMAND == message )
      && ( HIWORD( wParam ) == LBN_SELCHANGE ) )
    {
      if ( poWindow->m_poObserver )
      {
        // execute on click handler 
        //
        P_FORM_DEFINITION     pxForm = NULL;
  
        PAGE_DEFINITION_SET_ITER oPagesIter = poWindow->m_poOwner->m_poFormSetData->find( poWindow->m_poOwner->m_oCurrentSheetName );
        if ( oPagesIter != poWindow->m_poOwner->m_poFormSetData->end() )
        {
          P_FORM_DEFINITION     pxForm = (*oPagesIter).second;

          if ( poWindow->m_poHasFocus != NULL )
          {
            FORM_ACTIONS_ITER oFormActions = pxForm->m_oFormActions.find( poWindow->m_poHasFocus->GetDlgCtrlID() );
            if ( oFormActions != pxForm->m_oFormActions.end() ) 
            {
              CTRL_ACTIONS* poActions = (*oFormActions).second;
              CTRL_ACTIONS_ITER oCtrlActions = poActions->find( eOnListBoxSelChange );
              if ( oCtrlActions != poActions->end() )
              {
                std::string oScriptEntry = (*oCtrlActions).second;

                // the following setup is *REQUIRED* since this is how the 
                // script engine gets the 'form context' If this work is
                // *NOT* done the script engine will throw an exception
                //
                pxForm->m_poFacade->SetVmXmlFormInfo( poWindow->m_poOwner );
                pxForm->m_poFacade->SetVar( poWindow->m_poOwner->m_poArguments, 
                                            poWindow->m_poOwner->m_bChildOwnsPointers );
                pxForm->m_poFacade->SetDebuggerHook( NULL );
                pxForm->m_poFacade->Execute( oScriptEntry.c_str() );
              }
            }
          }
        }
      }
      // all other messages go to the default
      //
      return ::CallWindowProc( pfnXMLFormWndProc, hWnd, message, wParam, lParam );
    }
    else
    if ( ( WM_COMMAND == message )
      && ( ( HIWORD( wParam ) == CBN_KILLFOCUS    ) 
        || ( HIWORD( wParam ) == CBN_SELENDCANCEL ) ) )
    {
      return FALSE;
    }
    else
    // special case for notifies
    if ( message == WM_NOTIFY )
    {
      if ( !poWindow->m_bDestroyed )
      {
        NMHDR* pxNotify = (LPNMHDR) lParam;
        switch ( pxNotify->code )
        {
          case TCN_SELCHANGE: 
          {
            if ( poWindow->m_poObserver )
            {
              // execute on click handler 
              //
              P_FORM_DEFINITION     pxForm = NULL;
  
              PAGE_DEFINITION_SET_ITER oPagesIter = poWindow->m_poOwner->m_poFormSetData->find( poWindow->m_poOwner->m_oCurrentSheetName );
              if ( oPagesIter != poWindow->m_poOwner->m_poFormSetData->end() )
              {
                P_FORM_DEFINITION     pxForm = (*oPagesIter).second;
 
                FORM_ACTIONS_ITER oFormActions = pxForm->m_oFormActions.find( pxNotify->idFrom );
                if ( oFormActions != pxForm->m_oFormActions.end() ) 
                {
                  CTRL_ACTIONS* poActions = (*oFormActions).second;
                  CTRL_ACTIONS_ITER oCtrlActions = poActions->find( eOnTabSelChange );
                  if ( oCtrlActions != poActions->end() )
                  {
                    std::string oScriptEntry = (*oCtrlActions).second;
 
                    // the following setup is *REQUIRED* since this is how the 
                    // script engine gets the 'form context' If this work is
                    // *NOT* done the script engine will throw an exception
                    //
                    pxForm->m_poFacade->SetVmXmlFormInfo( poWindow->m_poOwner );
                    pxForm->m_poFacade->SetVar( poWindow->m_poOwner->m_poArguments, 
                                                poWindow->m_poOwner->m_bChildOwnsPointers );
                    pxForm->m_poFacade->SetDebuggerHook( NULL );
                    pxForm->m_poFacade->Execute( oScriptEntry.c_str() );
                  }
                }
              }
            }
          }
          break;
        }

        long lResult;
        lResult = ::CallWindowProc( pfnXMLFormWndProc, hWnd, message, wParam, lParam );
        return( lResult );
      }
    }

    try
    {
      if ( !poWindow->m_bDestroyed && ::IsWindow( poWindow->m_hWnd ) && ::IsWindow( hWnd ) && CWnd::FromHandlePermanent( hWnd ) )
      {
        // all other messages go to the default
        //
        return ::CallWindowProc( pfnXMLFormWndProc, hWnd, message, wParam, lParam );
      }
    }
    catch( ... )
    {
    }
  }
  return( 0L );
}
/* End of function "CXMLFormWindow::LocalWndProc"
/*****************************************************************************/


/*****************************************************************************/
/*

     FUNCTION NAME:  CXMLFormWindow::OnLButtonDown

       DESCRIPTION:  Just to see if thny like it.......

             INPUT:  nFlags - see MFC docs
                     point - see MFC docs
            OUTPUT:  

           RETURNS:  void 
*/
void CXMLFormWindow::OnLButtonDown( UINT nFlags, CPoint point ) 
{
  CWnd::OnLButtonDown( nFlags, point ); 

  // MJS: May want to make another flag here for 'movable' ?
  //      but this works for now....
  //
  if ( !m_bTreatAsControl )
  {
    // fake windows into thinking your clicking on the caption, does not
    // maximize on double click
    //
    PostMessage( WM_NCLBUTTONDOWN, HTCAPTION, MAKELPARAM( point.x, point.y ) );
  }
} 
/* End of function "CXMLFormWindow::OnLButtonDown"
/*****************************************************************************/


/*****************************************************************************/
/*

     FUNCTION NAME:  CXMLFormWindow::OnRButtonDown

       DESCRIPTION:  Allows user to set colors on this form

             INPUT:  nFlags - see MFC docs
                     point - see MFC docs
            OUTPUT:  

           RETURNS:  void
*/
void CXMLFormWindow::OnRButtonDown( UINT nFlags, CPoint point ) 
{
#ifdef USER_CAN_SET_COLORS

  CONFIGURE_OPTIONS  xOptions;
  COLOR_CONFIG       colors[ 2 ];

  COLORREF           xBackgroundColor = m_xBackgroundColor;
  COLORREF           xTextColor       = m_xTextColor;

  colors[ 0 ].pchDisplay = "Background Color";
  colors[ 0 ].xColor     =  xBackgroundColor;

  colors[ 1 ].pchDisplay = "Text Color";
  colors[ 1 ].xColor     =  xTextColor;

  CDynamicDialog oDlg;

  CRect rect( 10, 5, 80, 20 );  // l t r b


  xOptions.roColorInfo = colors;
  xOptions.iColorCount = 2;

  oDlg.SetWindowTitle( _T( "Color Selector" ) );

  for ( int iLoop = 0; iLoop < xOptions.iColorCount; iLoop++ )
  {
    PCOLOR_CONFIG pxColor = xOptions.roColorInfo + iLoop;

    oDlg.AddDlgControl( _T("STATIC"), pxColor->pchDisplay, STYLE_STATIC, 0, rect, NULL );
    rect.top += 15;
    rect.bottom += 15;
    oDlg.AddDlgControl( _T("ColorButton"), "", STYLE_BUTTON, EXSTYLE_BUTTON, rect, (void*)&pxColor->xColor );
    rect.top += 20;
    rect.bottom += 20;
  }

  int nResponse = oDlg.DoModal();

  if ( IDOK == nResponse )
  {
    m_xTextColor       = colors[ 1 ].xColor;
    m_xBackgroundColor = colors[ 0 ].xColor;
    m_oBrush.DeleteObject();
    m_oBrush.CreateSolidBrush( m_xBackgroundColor );
    InvalidateSpecialKids();
    Invalidate();
  }

#endif
}
/* End of function "CXMLFormWindow::OnRButtonDown"
/*****************************************************************************/


/*****************************************************************************/
/*

     FUNCTION NAME:  CXMLFormWindow::InvalidateSpecialKids

       DESCRIPTION:  Since only statics and radio buttons are affected by color
                     changes, make sure that they are invalidated to prompt a
                     repaint

             INPUT:  void 
            OUTPUT:  none

           RETURNS:  void  
*/
void CXMLFormWindow::InvalidateSpecialKids( void )
{
  CWnd*      poWnd = GetWindow( GW_CHILD );
  do
  {
    DWORD dwStyle  = ::GetWindowLong( poWnd->m_hWnd, GWL_STYLE );
    if ( ( ( dwStyle & BS_AUTORADIOBUTTON ) == BS_AUTORADIOBUTTON )
      || ( ( dwStyle & BS_AUTOCHECKBOX    ) == BS_AUTOCHECKBOX    ) )
    {
      poWnd->Invalidate();
    }  
    else
    {
      char achClassName[ 50 ];
      ::GetClassName( poWnd->m_hWnd, achClassName, 50 );

      // catch all statics that aren't specific colored frames
      //
      if ( 0 == lstrcmp( achClassName, "Static" ) )
      {
        if ( ( ( dwStyle & SS_SIMPLE          ) == SS_SIMPLE         )
          || ( ( dwStyle & SS_RIGHT           ) == SS_RIGHT          )
          || ( ( dwStyle & SS_LEFTNOWORDWRAP  ) == SS_LEFTNOWORDWRAP )
          || ( ( dwStyle & SS_LEFT            ) == SS_LEFT           ) 
          || ( ( dwStyle & SS_CENTER          ) == SS_CENTER         ) )
        {
          poWnd->Invalidate();
        }
      }
    }
    poWnd = poWnd->GetWindow( GW_HWNDNEXT );
  } 
  while ( poWnd != NULL );
}
/* End of function "CXMLFormWindow::InvalidateSpecialKids"
/*****************************************************************************/


/*****************************************************************************/
/*

     FUNCTION NAME:  CXMLFormWindow::OnCtlColor

       DESCRIPTION:  Our chance to provide our own brush for ctrl backgrounds

             INPUT:  pDC - see MFC docs
                     pWnd -  see MFC docs
                     nCtlColor -  see MFC docs
            OUTPUT:  

           RETURNS:  Handle to brush to paint control with
*/
HBRUSH CXMLFormWindow::OnCtlColor( CDC* pDC, CWnd* pWnd, UINT nCtlColor ) 
{
  // Call the base class implementation first! Otherwise, it may
  // undo what we're trying to accomplish here.
  //
  HBRUSH oBrush = CWnd::OnCtlColor( pDC, pWnd, nCtlColor );

  UINT iItemID = pWnd->GetDlgCtrlID();

  char achClassName[ 50 ];

  // catches all radio buttons and check boxes
  //
  DWORD dwStyle  = ::GetWindowLong( pWnd->m_hWnd, GWL_STYLE );
  if ( ( ( dwStyle & BS_AUTORADIOBUTTON ) == BS_AUTORADIOBUTTON )
    || ( ( dwStyle & BS_AUTOCHECKBOX    ) == BS_AUTOCHECKBOX    ) )
  {
      // Set the text color
      //
      pDC->SetTextColor( m_xTextColor );

      // Set the background mode for text to transparent 
      // so background will show thru.
      //
      pDC->SetBkMode( TRANSPARENT );

      // Return handle to our CBrush object
      //
      oBrush = m_oBrush;
  }
  else
  {
    ::GetClassName( pWnd->m_hWnd, achClassName, 50 );

    // catch all statics that aren't specific colored frames
    //
    if ( 0 == lstrcmp( achClassName, "Static" ) )
    {
      if ( ( ( dwStyle & SS_SIMPLE          ) == SS_SIMPLE         )
        || ( ( dwStyle & SS_RIGHT           ) == SS_RIGHT          )
        || ( ( dwStyle & SS_LEFTNOWORDWRAP  ) == SS_LEFTNOWORDWRAP )
        || ( ( dwStyle & SS_LEFT            ) == SS_LEFT           ) 
        || ( ( dwStyle & SS_CENTER          ) == SS_CENTER         ) )
      {
        // Set the text color
        //
        pDC->SetTextColor( m_xTextColor );

        // Set the background mode for text to transparent 
        // so background will show thru.
        //
        pDC->SetBkMode( TRANSPARENT );

        // Return handle to our CBrush object
        //
        oBrush = m_oBrush;
      }
    }
  }
  return oBrush;
}
/* End of function "CXMLFormWindow::OnCtlColor"
/*****************************************************************************/


/*****************************************************************************/
/*

     FUNCTION NAME:  CXMLFormWindow::OnEraseBkgnd

       DESCRIPTION:  handler set up to eliminate flicker

             INPUT:  poDC - ignored
            OUTPUT:  none

           RETURNS:  TRUE -- indicates it was 'handled'
*/
BOOL CXMLFormWindow::OnEraseBkgnd( CDC* poDC ) 
{
  return TRUE;
}
/* End of function "CXMLFormWindow::OnEraseBkgnd"
/*****************************************************************************/



/*****************************************************************************/
/*

     FUNCTION NAME:  CXMLFormWindow::ChildFocus

       DESCRIPTION:  All child controls created here are 'watched focus controls'
                     which means that this will be contacted whenever any of them
                     has a change in focus state

             INPUT:  poChild - pointer to the child sending the focus message
                     bHasFocus - true if gaining focus, false if not
            OUTPUT:  

           RETURNS:  void 
*/
void CXMLFormWindow::ChildFocus( CWnd* poChild, bool bHasFocus )
{
  P_FORM_DEFINITION     pxForm = NULL;
  
  PAGE_DEFINITION_SET_ITER oPagesIter = m_poOwner->m_poFormSetData->find( m_poOwner->m_oCurrentSheetName );
  if ( oPagesIter != m_poOwner->m_poFormSetData->end() )
  {
    pxForm = (*oPagesIter).second;
  }

  if ( bHasFocus )
  {
    m_poHadFocusLast = m_poHasFocus;
    m_poHasFocus     = poChild;

    if ( pxForm != NULL )
    {
      FORM_ACTIONS_ITER oFormActions = pxForm->m_oFormActions.find( m_poHasFocus->GetDlgCtrlID() );
      if ( oFormActions != pxForm->m_oFormActions.end() ) 
      {
        CTRL_ACTIONS* poActions = (*oFormActions).second;
        CTRL_ACTIONS_ITER oCtrlActions = poActions->find( eOnGainFocus );
        if ( oCtrlActions != poActions->end() )
        {
          std::string oScriptEntry = (*oCtrlActions).second;

          // the following setup is *REQUIRED* since this is how the 
          // script engine gets the 'form context' If this work is
          // *NOT* done the script engine will throw an exception
          //
          pxForm->m_poFacade->SetVmXmlFormInfo( m_poOwner );
          pxForm->m_poFacade->SetVar( m_poOwner->m_poArguments, 
                                      m_poOwner->m_bChildOwnsPointers );
          pxForm->m_poFacade->SetDebuggerHook( NULL );
          pxForm->m_poFacade->Execute( oScriptEntry.c_str() );
        }
      }
    }
  }
  else
  {
    m_poHadFocusLast = m_poHasFocus;
    m_poHasFocus     = poChild;

    if ( pxForm != NULL )
    {
      FORM_ACTIONS_ITER oFormActions = pxForm->m_oFormActions.find( poChild->GetDlgCtrlID() );
      if ( oFormActions != pxForm->m_oFormActions.end() ) 
      {
        CTRL_ACTIONS* poActions = (*oFormActions).second;
        CTRL_ACTIONS_ITER oCtrlActions = poActions->find( eOnLoseFocus );
        if ( oCtrlActions != poActions->end() )
        {
          std::string oScriptEntry = (*oCtrlActions).second;

          // the following setup is *REQUIRED* since this is how the 
          // script engine gets the 'form context' If this work is
          // *NOT* done the script engine will throw an exception
          //
          pxForm->m_poFacade->SetVmXmlFormInfo( m_poOwner );
          pxForm->m_poFacade->SetVar( m_poOwner->m_poArguments, 
                                      m_poOwner->m_bChildOwnsPointers );
          pxForm->m_poFacade->SetDebuggerHook( NULL );
          pxForm->m_poFacade->Execute( oScriptEntry.c_str() );
        }
      }
    }
  }

  if ( m_poObserver )
  {
    // notify any observers of focus event
    //
    if ( bHasFocus )
    {
      m_poObserver->ThisChildHasFocus( poChild );
    }
    else
    {
      m_poObserver->ThisChildLostFocus( poChild );
    }
  }
}
/* End of function "CXMLFormWindow::ChildFocus"
/*****************************************************************************/

#define CELL_COUNT( AnArray ) ( sizeof( AnArray )/sizeof( AnArray[ 0 ] ) )


/*****************************************************************************/
/*

     FUNCTION NAME:  CXMLFormWindow::CompareClassName

       DESCRIPTION:  compares the class name associated with a window handle
                     to a given value. 

             INPUT:  hWnd - the window handle to check 
                     pchClassName - the class name to test against
            OUTPUT:  

           RETURNS:  TRUE if matches, FALSE if not
*/
BOOL CXMLFormWindow::CompareClassName( HWND hWnd, LPCTSTR pchClassName )
{
  ASSERT( ::IsWindow( hWnd ) );
  TCHAR  achTemp[ 32 ];

  ::GetClassName( hWnd, achTemp, CELL_COUNT( achTemp ) );
  return( lstrcmpi( achTemp, pchClassName ) == 0 );
}
/* End of function "CXMLFormWindow::CompareClassName"
/*****************************************************************************/


/*****************************************************************************/
/*

     FUNCTION NAME:  CXMLFormWindow::PreTranslateMessage

       DESCRIPTION:  Allows this class to look at messages bound for child
                     windows and act on them as required

             INPUT:  pxMsg - pointer to message structure
            OUTPUT:  none

           RETURNS:  TRUE if message handled here, FALSE if message routing
                     should continue
*/
BOOL CXMLFormWindow::PreTranslateMessage( MSG* pxMsg )
{
  // for modeless processing (or modal)
  //
  ASSERT( m_hWnd != NULL );

  // allow tooltip messages to be filtered
  //
  if ( CWnd::PreTranslateMessage( pxMsg ) )
  {
    return( TRUE );
  }

  // don't translate dialog messages when in Shift+F1 help mode
  //
  CFrameWnd* pFrameWnd = GetTopLevelFrame();
  if ( pFrameWnd != NULL && pFrameWnd->m_bHelpMode )
  {
    return( FALSE );
  }

  // fix around for VK_ESCAPE in a multiline Edit that is on a Dialog
  // that doesn't have a cancel or the cancel is disabled.
  //
  if ( pxMsg->message == WM_KEYDOWN 
    && ( pxMsg->wParam == VK_ESCAPE || pxMsg->wParam == VK_CANCEL ) 
    && ( ::GetWindowLong( pxMsg->hwnd, GWL_STYLE ) & ES_MULTILINE ) 
    && CompareClassName( pxMsg->hwnd, _T( "Edit" ) ) )
  {
    HWND hItem = ::GetDlgItem( m_hWnd, IDCANCEL );
    if ( hItem == NULL || ::IsWindowEnabled( hItem ) )
    {
      SendMessage( WM_COMMAND, IDCANCEL, 0 );
      return( TRUE );
    }
  }
  else
  if ( pxMsg->message == WM_KEYDOWN )
  {
    switch ( pxMsg->wParam )
    {
      case VK_RETURN:
      case VK_UP:
      case VK_DOWN:
      case VK_SPACE:
      case VK_LEFT:
      case VK_RIGHT:
      case VK_TAB:
      {
        // these keys are handled in the specialized key handler, so give that the
        // the first chance to handle the key message. If the key is not handled,
        // then forward for continued processing
        //
        if ( !m_poOwner->SpecialKeyHandler()->SpecialKeyboardHandling( pxMsg->wParam ) )
        {
          return( PreTranslateInput( pxMsg ) );
        }
        else
        {
          return TRUE;
        }
      }
      break;

      // custom accelerator handling
      //
      case '0':
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      case '9':
      case 'A':
      case 'B':
      case 'C':
      case 'D':
      case 'E':
      case 'F':
      case 'G':
      case 'H':
      case 'I':
      case 'J':
      case 'K':
      case 'L':
      case 'M':
      case 'N':
      case 'O':
      case 'P':
      case 'Q':
      case 'R':
      case 'S':
      case 'T':
      case 'U':
      case 'V':
      case 'W':
      case 'X':
      case 'Y':
      case 'Z':
      {
        if ( 0x1000 & GetKeyState( VK_CONTROL ) )
        {
          PAGE_DEFINITION_SET_ITER oPagesIter = m_poOwner->m_poFormSetData->find( m_poOwner->m_oCurrentSheetName );
          if ( oPagesIter != m_poOwner->m_poFormSetData->end() )
          {
            P_FORM_DEFINITION     pxForm = (*oPagesIter).second;
            FORM_CONTROL_MAP_ITER oCtrlIter;

            for ( oCtrlIter = pxForm->m_oControlsMap.begin();
                  oCtrlIter != pxForm->m_oControlsMap.end();
                  oCtrlIter++ )
            {
              P_FORM_CONTROL pxCtrl = (*oCtrlIter).second;
              if ( pxMsg->wParam == pxCtrl->m_chAltNavKey )
              {
                pxCtrl->m_poControl->SetFocus(); 
                return( TRUE );
              }
            }
          }
        }
      }
      break;

      default:
        return( PreTranslateInput( pxMsg ) );
      break;
    }
  }
  // filter both messages to dialog and from children
  //  
  return( PreTranslateInput( pxMsg ) );
}
/* End of function "CXMLFormWindow::PreTranslateMessage"
/*****************************************************************************/


/*****************************************************************************/
/*

     FUNCTION NAME:  CXMLFormWindow::OnNcPaint

       DESCRIPTION:  customized caption bar painting

             INPUT:  void 
            OUTPUT:  none

           RETURNS:  void  
*/
void CXMLFormWindow::OnNcPaint( void ) 
{
  if ( m_bTreatAsControl )
  {
    Default();
    return;
  }
  else
  {
    // let the framework draw the window first
    //
    Default();

    COLORREF xBackgroundColor;
    COLORREF xTextColor;

    xBackgroundColor = GetSysColor( COLOR_ACTIVECAPTION ); //RGB(  58, 110, 165 );
    xTextColor       = GetSysColor( COLOR_CAPTIONTEXT );   //RGB( 255, 255, 255 );

    // To accesses the entire screen area of a CWnd 
    // (both client and nonclient areas).
    //
    CWindowDC oDC( this );
    CRect     oRect, oWinRect;
    GetWindowRect( oWinRect );

    // Compute the caption bar's origin.
    //
    oRect.left = GetSystemMetrics( SM_CXFRAME );

    if ( !IsZoomed() )
    {
      oRect.top = GetSystemMetrics( SM_CYFRAME ) - 1;
    }
    else
    {
      oRect.top = 0;
    }

    CRect oButtonRect;
    oButtonRect.top    = GetSystemMetrics( SM_CYFRAME ); 
    oButtonRect.bottom = oButtonRect.top + GetSystemMetrics( SM_CYSMSIZE ); 
    oButtonRect.left   = GetSystemMetrics( SM_CXFRAME ) + GetSystemMetrics( SM_CXBORDER ) + 1; 
    oButtonRect.right  = oButtonRect.left + GetSystemMetrics( SM_CXSMSIZE ); 

    // 2*x gives twice the bitmap+border+frame size. Since there are
    // only two bitmaps, two borders, and one frame at the end of the
    // caption bar, subtract a frame to account for this.
    //
    oRect.right = oWinRect.right 
                  - oWinRect.left 
                  +  2 * oRect.left
                  - GetSystemMetrics( SM_CXFRAME );

    if ( !IsZoomed() )
    {
      oRect.bottom = GetSystemMetrics( SM_CYSMCAPTION ) 
                   + ( GetSystemMetrics( SM_CXFRAME ) / 2 ) + 3;
    }
    else 
    {
      oRect.bottom = GetSystemMetrics( SM_CYSIZE ) 
                   + GetSystemMetrics( SM_CXBORDER ) 
                   + ( GetSystemMetrics( SM_CXFRAME ) / 2 ) + 1;
    }

    // fill the title bar
    //
    int iRightSide;
    if ( IsZoomed() )
    {
      iRightSide = 0;
    }
    else
    {
      iRightSide = 3 * oRect.left;
    }

    oDC.FillSolidRect( oRect.left, 
                       oRect.top, 
                       oRect.right - iRightSide, 
                       oRect.Height(), 
                       xBackgroundColor ); 
    CString oText;
    GetWindowText( oText );
    oDC.SetBkColor( xBackgroundColor );
    oDC.SetTextColor( xTextColor );

    int iDropText;
    if ( IsZoomed() )
    {
      iDropText = 2;
    }
    else
    {
      iDropText = 1;
    }

    oDC.TextOut( oRect.left + GetSystemMetrics( SM_CXSIZE ) + 5, oRect.top + iDropText, oText );

    // Area for buttons
    //
    oButtonRect.top    = GetSystemMetrics( SM_CYFRAME ) + 1; 
    oButtonRect.bottom = oButtonRect.top + GetSystemMetrics( SM_CYSMSIZE ) - 1; 
    oButtonRect.left   = oRect.right - 1 * oRect.left - oButtonRect.bottom; 
    oButtonRect.right  = oRect.right - 1 * oRect.left - oButtonRect.top; 
    m_oCloseButtonRect = oButtonRect;

    // Put the buttons on the caption
    //
    oDC.DrawFrameControl( m_oCloseButtonRect,      DFC_CAPTION, DFCS_CAPTIONCLOSE );
  }
}
/* End of function "CXMLFormWindow::OnNcPaint"
/*****************************************************************************/


/*****************************************************************************/
/*

     FUNCTION NAME:  CXMLFormWindow::OnActivate

       DESCRIPTION:  invoke caption bar paints when focus changes

             INPUT:  nState - 
                     pWndOther - 
                     bMinimized - 
            OUTPUT:  

           RETURNS:  void 
*/
void CXMLFormWindow::OnActivate( UINT nState, CWnd* pWndOther, BOOL bMinimized ) 
{
  CWnd::OnActivate( nState, pWndOther, bMinimized );
  CWnd* pWnd = GetTopWindow();
  OnNcPaint();
}
/* End of function "CXMLFormWindow::OnActivate"
/*****************************************************************************/


/*****************************************************************************/
/*

     FUNCTION NAME:  CXMLFormWindow::HitTest

       DESCRIPTION:  determines if one of our custom caption buttons was hit

             INPUT:  oPoint - 
            OUTPUT:  none

           RETURNS:  Hit Code
*/
DWORD CXMLFormWindow::HitTest( CPoint oPoint )
{
  if ( m_oCloseButtonRect.PtInRect( oPoint ) )
  {
    return( (DWORD) DHT_CLOSE );
  }
  else
  {
    return( (DWORD) DHT_CAPTION );
  }
}
/* End of function "CXMLFormWindow::HitTest"
/*****************************************************************************/


/*****************************************************************************/
/*

     FUNCTION NAME:  CXMLFormWindow::OnNcLButtonDown

       DESCRIPTION:  captures mouse if click is over our custom button

             INPUT:  iHitTest - 
                     oClickPoint - 
            OUTPUT:  

           RETURNS:  void  
*/
void CXMLFormWindow::OnNcLButtonDown( UINT iHitTest, CPoint oClickPoint ) 
{ 
  // Coords are relative to screen
  //
  CPoint oPoint = oClickPoint;
  ScreenToClient( &oPoint );

  // Adjust for client area
  //
  oPoint.y += GetSystemMetrics( SM_CYCAPTION ) + GetSystemMetrics( SM_CYFRAME );    
  oPoint.y = abs( oPoint.y );
  oPoint.x += 5;

  // Now test for button
  //
  DWORD dwHitTest = HitTest( oPoint );

  switch( dwHitTest )
  {
    case DHT_CLOSE:
    {
      CWindowDC oDC( this );
      DrawFrameControl( oDC.m_hDC,
                        m_oCloseButtonRect,
                        DFC_CAPTION,
                        DFCS_CAPTIONCLOSE | DFCS_PUSHED );

      m_LastHit    = dwHitTest;
      m_ButtonDown = dwHitTest;
      SetCapture();
    }
    break;

    default:
      Default(); 
    break;
  }
} 
/* End of function "CXMLFormWindow::OnNcLButtonDown"
/*****************************************************************************/


/*****************************************************************************/
/*

     FUNCTION NAME:  CXMLFormWindow::OnLButtonUp

       DESCRIPTION:  if one of our custom buttons was hit...process it

             INPUT:  iFlags - 
                     oClickPoint - 
            OUTPUT:  

           RETURNS:  void  
*/
void CXMLFormWindow::OnLButtonUp( UINT iFlags, CPoint oClickPoint ) 
{
  if ( this != GetCapture() )
    return;
	
  // Coords are relative to window now
  //
  CPoint oPoint = oClickPoint;
  oPoint.y += GetSystemMetrics( SM_CYCAPTION ) + GetSystemMetrics( SM_CYFRAME );
  oPoint.y = abs( oPoint.y );
  oPoint.x += 5;

  // Now test for button
  //
  DWORD dwHitTest = HitTest( oPoint );

  switch( m_ButtonDown ) // Release the pressed button
  {
    case DHT_CLOSE:
    {
      CWindowDC oDC( this );

      DrawFrameControl( oDC.m_hDC,
                        m_oCloseButtonRect,
                        DFC_CAPTION,
                        DFCS_CAPTIONCLOSE );
    }
    break;

    default:
    break;
  }

  switch( dwHitTest )
  { 
    // Process command if released at on a button
    //
    case DHT_CLOSE:
    {
      if ( m_bModal )
      {
        SendMessage( WM_COMMAND, IDCANCEL, 0 );
      }
      else
      {
        ShowWindow( SW_HIDE );
      }
    }
    break;

    default:
    {
      CWnd::OnLButtonUp( iFlags, oClickPoint );
    }
    break;
  }
  m_ButtonDown = 0;
  ReleaseCapture();
}
/* End of function "GetSystemMetrics"
/*****************************************************************************/


/*****************************************************************************/
/*

     FUNCTION NAME:  CXMLFormWindow::OnNcHitTest

       DESCRIPTION:  hit testing

             INPUT:  oClickPoint - 
            OUTPUT:  none

           RETURNS:  hit code 
*/
UINT CXMLFormWindow::OnNcHitTest( CPoint oClickPoint ) 
{
//  if ( this != GetCapture() )
//  {
//    return CWnd::OnNcHitTest( oClickPoint );
//  }


  UINT iHitPoint = CWnd::OnNcHitTest( oClickPoint );

  if ( m_bDrawGripper && iHitPoint == HTCLIENT )
  {
    CRect oRect;
    GetWindowRect( oRect );
    oRect.left = oRect.right  - GetSystemMetrics( SM_CXHSCROLL );
    oRect.top  = oRect.bottom - GetSystemMetrics( SM_CYVSCROLL );

    if ( oRect.PtInRect( oClickPoint ) )
    {
      return( HTBOTTOMRIGHT );
    }
  }

  // Coords are relative to screen
  //
  CPoint oPoint = oClickPoint;
  ScreenToClient( &oPoint );
  oPoint.y += GetSystemMetrics( SM_CYCAPTION ) + GetSystemMetrics( SM_CYFRAME );
  oPoint.y = abs( oPoint.y );
  oPoint.x += 5;

  // Now test for button
  //
  DWORD dwHitTest = HitTest( oPoint );

  if ( dwHitTest == m_LastHit )
  {
    return ( iHitPoint );//CWnd::OnNcHitTest( oClickPoint );
  }

  m_LastHit = dwHitTest;

  UINT iPushed = 0;
  if ( m_ButtonDown == dwHitTest )
  {
   iPushed = DFCS_PUSHED;
  }

  CWindowDC oDC( this );
  switch( dwHitTest )
  {
    case DHT_CLOSE:
    {
      DrawFrameControl( oDC.m_hDC,
                        m_oCloseButtonRect,
                        DFC_CAPTION,
                        DFCS_CAPTIONCLOSE | iPushed );
    }
    break;
  }
  return dwHitTest;
}
/* End of function "CXMLFormWindow::OnNcHitTest"
/*****************************************************************************/


/*****************************************************************************/
/*

     FUNCTION NAME:  CXMLFormWindow::OnNcActivate

       DESCRIPTION:  invokde caption bar paints for focus changes

             INPUT:  bActive - 
            OUTPUT:  none

           RETURNS:  TRUE 
*/
BOOL CXMLFormWindow::OnNcActivate( BOOL bActive ) 
{
  OnNcPaint(); 
  return TRUE; 
}
/* End of function "CXMLFormWindow::OnNcActivate"
/*****************************************************************************/



/*****************************************************************************/
/* Check-in history 
   $WorkFile:   $
    $Archive:   $

 *$Log:   $
*/
/*****************************************************************************/


By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions