/**********************************************************************/
/**                       Microsoft Windows/NT                       **/
/**                Copyright(c) Microsoft Corp., 1991                **/
/**********************************************************************/

/*
    bltwin.hxx
    Base of the BLT WINDOW hierarchy

    FILE HISTORY
        RustanL     20-Nov-1990 Created
        RustanL     04-Mar-1991 Added OWNER_WINDOW::QueryError mechanism
        Johnl       12-Mar-1991 Removed _hwndOwner member
        beng        14-May-1991 Hack for separate compilation
        terryk      10-Jul-1991 Add IsEnable to the window class
        terryk      20-Jul-1991 Add QueryClientRect in WINDOW class.
        terryk      02-Aug-1991 Add QueryWindowRect in WINDOW class.
        beng        30-Sep-1991 Added ASSOCHWNDTHIS helper class
        KeithMo     23-Oct-1991 Added forward references.
        terryk      04-Apr-1992 Added Z position in SetPos
        Yi-HsinS    10-Dec-1992 Added CalcFixedHeight
*/

#ifndef _BLT_HXX_
#error "Don't include this file directly; instead, include it through blt.hxx"
#endif // _BLT_HXX_

#ifndef _BLTWIN_HXX_
#define _BLTWIN_HXX_

#include "base.hxx"
#include "bltglob.hxx"  // for CID
#include "bltmisc.hxx"  // for XYPOINT, XYDIMENSION
#include "bltevent.hxx"


//
//  Forward references.
//

DLL_CLASS WINDOW;
DLL_CLASS CONTROL_TABLE;    // declared and defined in bltowin.cxx
DLL_CLASS CONTROL_WINDOW;   // declared in bltctrl.hxx
DLL_CLASS ITER_CTRL;
DLL_CLASS OWNER_WINDOW;
DLL_CLASS ASSOCCHWNDTHIS;
DLL_CLASS PROC_INSTANCE;
DLL_CLASS NLS_STR;          // (declared in string.hxx)
DLL_CLASS XYRECT;           // (declared in bltrect.hxx)


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

    NAME:       WINDOW

    SYNOPSIS:   Base of the "window" hierarchy.

        This class provides access to general window-manipulation
        functionality common to control, client, and dialog windows.
        It represents a single "window" object in the system, either
        created by the system or explicitly by the client.

    INTERFACE:
        WINDOW()            - constructor
        ~WINDOW()           - destructor
        QueryHwnd()         - return the window handle
        QueryOwnerHwnd()    - return the owner window handle
        Command()           - command
        Show()              - show window
        QueryClientRect()   - return the clinet window dimension and position
        QueryWindowRect()   - return the clinet window dimension and position
                              in screen coordinate.
        Enable()            - enable the window
        IsEnabled()         - return the current status of the window
        QueryStyle()        - return the current window style
        SetStyle()          - set the window's style bits (protected)
        SetText()           - set the window caption
        QueryTextLength()   - return caption length
        QueryTextSize()     - return size of caption, in bytes
        QueryText()         - return current caption
        ClearText()         - clear caption
        SetRedraw()         - redraw the window
        Invalidate()        - invalidate some or all of the window,
                              optionally erasing the window
        RepaintNow()        - force an immediate repaint of the window
        IsChild()           - check whether the window is a child window
        SetPos()            - set window position
        QueryPos()          - return current window position
        SetSize()           - set the window size
        QuerySize()         - return current window size
        IsClientGeneratedMessage() - Returns TRUE if the current
                                     message was generated by us, thus it
                                     should be ignored.
        HasFocus()          - returns TRUE if the current window has the focus.
        Center()            - centers the window above another window.

    PARENT:     BASE

    USES:       XYPOINT, XYDIMENSION

    CAVEATS:

    NOTES:
        Should destructor be virtual?

    HISTORY:
        rustanl     20-Nov-1990 Created
        rustanl     04-Mar-1991 Added OWNER_WINDOW::QueryError mechanism
        johnl       12-Mar-1991 Removed _hwndOwner member
        beng        25-Apr-1991 Relocated QueryOwnerHwnd implementation;
                                removed unused constructor forms
        rustanl     27-Apr-1991 Changed SetText( PSZ ) to
                                SetText( const TCHAR * )
        beng        07-May-1991 Added CreateWindow version of ctor
        beng        10-May-1991 Added ResetCreator for errors
        Johnl       10-May-1991 Moved client generated message flag here
        beng        15-May-1991 Pruned constructors; enhanced
                                Query/Set Pos/Size to grok XY* objects
        beng        23-May-1991 Changed return type of QueryText
        beng        10-Jun-1991 Added QueryTextSize; changed QTxtLen
                                return type to INT
        terryk      10-Jul-1991 Added IsEnable function to the window class
        terryk      20-Jul-1991 Added QueryClientRect function to the class
        beng        31-Jul-1991 Added ShowFirst, static _fClientGen'd
        terryk      02-Aug-1991 Added QueryWindowRect function to the class
        beng        04-Oct-1991 Win32 conversion
        Yi-HsinS    08-Jan-1992 Added HasFocus method
        beng        13-Feb-1992 Moved RepaintNow here from CLIENT_WINDOW;
                                add SetStyle
        KeithMo     11-Nov-1992 Added new ctor form and Center method.

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

DLL_CLASS WINDOW: public BASE
{
private:
    HWND _hwnd;
    BOOL _fCreator;

    // This flag indicates that the message was generated internally and not
    // by the user manipulating controls.  It is used where we may want
    // to ignore internally generated changes (for example, in SetText,
    // windows sends out an EN_CHANGE message to the control, so anything
    // that responds and does a SetText will be caught in an infinite loop).
    //
    // See SetClientGeneratedMsgFlag and IsClientGeneratedMessage.
    //
    static BOOL _fClientGeneratedMessage;

protected:
    VOID SetHwnd( HWND hwnd );
    VOID ResetCreator();

    static VOID SetClientGeneratedMsgFlag( BOOL fClientGeneratedMessage ) ;
    static BOOL CalcFixedHeight( HWND hwnd, UINT *pnHeight );

public:
    WINDOW();
    WINDOW( const TCHAR *   pszClassName,
            ULONG          flStyle,
            const WINDOW * pwndOwner = 0,
            CID            cid = 0 );
    WINDOW( HWND hwnd );
    ~WINDOW();

    // These two methods are prime candidates for inlining.
    //
    HWND QueryHwnd() const;
    HWND QueryOwnerHwnd() const;

    // Note.  This method may change things in the window itself, but
    // will not change any data member per se.    The method needs to be
    // const, however, since many other const methods may call it for
    // real const kind of operations, e.g. LIST_CONTROL::QueryCount.
    //
    // (Should this become a protected method?)
    // (Also, can I replace it with something that passes an EVENT?)
    //
    ULONG Command( UINT nMsg, WPARAM wParam = 0, LPARAM lParam = 0L ) const;

    BOOL Show( BOOL f = TRUE );
    VOID Enable( BOOL f = TRUE );
    BOOL IsEnabled() const;

    ULONG QueryStyle() const;

    VOID   SetText( const TCHAR * psz );
    VOID   SetText( const NLS_STR & nls );
    INT    QueryTextLength() const;
    INT    QueryTextSize() const;

    APIERR QueryText( TCHAR * pszBuffer, UINT cbBufSize ) const;
    APIERR QueryText( NLS_STR * pnls ) const;
    VOID   ClearText();

    VOID SetRedraw( BOOL f = TRUE );

    VOID Invalidate( BOOL fErase = FALSE ); // entire client area
    VOID Invalidate( const XYRECT & rect ); // selective inval
    VOID RepaintNow();

    VOID ShowFirst();

    // Returns TRUE if child style bit is set
    //
    BOOL IsChild() const;

    VOID SetPos( XYPOINT xy, BOOL fRepaint = TRUE, WINDOW *pwin = NULL );
    XYPOINT QueryPos() const;

    VOID SetSize( INT nWidth, INT nHeight, BOOL fRepaint = TRUE );
    VOID SetSize( XYDIMENSION dxy, BOOL fRepaint = TRUE );

    VOID QuerySize( INT *pnWidth, INT * pnHeight ) const;
    XYDIMENSION QuerySize() const;

    VOID QueryClientRect( RECT * pRect ) const;
    VOID QueryClientRect( XYRECT * pxycd ) const;
    VOID QueryWindowRect( RECT * pRect ) const;
    VOID QueryWindowRect( XYRECT * pxycd ) const;

    static BOOL IsClientGeneratedMessage();

    BOOL HasFocus( VOID ) const;

    VOID SetStyle( ULONG nValue );

    VOID Center( HWND hwnd = NULL );

    // For the anglophiles & dyslexics in the crowd.
    // You know who you are...

    VOID Centre( HWND hwnd = NULL )
        { Center( hwnd ); }

};


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

    NAME:       OWNER_WINDOW

    SYNOPSIS:   Owner window class - base of any window owning others.

    INTERFACE:
        OWNER_WINDOW()      - constructor
        ~OWNER_WINDOW()     - destructor
        QueryRobustHwnd()   - return the handle
        SetFocus()          - set window focus
        SetDialogFocus()    - set window focus to a dialog control.  Handles
                              default pushbuttons correctly.

    PARENT:     WINDOW

    USES:       CONTROL_TABLE, ITER_CTRL

    CAVEATS:

    NOTES:

    HISTORY:
        rustanl     20-Nov-1990 Created
        rustanl     04-Mar-1991 Added OWNER_WINDOW::QueryError mechanism
        Johnl       12-Mar-1991 Removed _hwndOwner member
        beng        25-Apr-1991 Removed it from constructor as well;
                                inherits from BASE
        beng        15-May-1991 Trimmed constructor
        beng        21-May-1991 Added sundry owner-draw support
        beng        15-Oct-1991 Win32 conversion
        beng        30-Oct-1991 Added ITER_CTRL as a friend
        KeithMo     14-Oct-1992 Added OnUserMessage.

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

DLL_CLASS OWNER_WINDOW : public WINDOW
{
friend class CONTROL_WINDOW;
friend class ITER_CTRL;

private:
    CONTROL_TABLE * _pctrltable;

    //  Generic control attributes word.  By convention, BLT controls
    //  lower 16 bits, users have upper 16 bits.
    DWORD _dwAttributes ;

    // This is called by the constructor of CONTROL_WINDOW
    //
    BOOL AddControl( CONTROL_WINDOW * pctrlwin );

protected:
    CONTROL_WINDOW * CidToCtrlPtr( CID cid ) const;

    // Provide for custom drawn ("owner-draw" in Win parlance) controls.
    //
    INT OnCDMessages( UINT nMsg, WPARAM wParam, LPARAM lParam );

    static INT OnLBIMessages( UINT nMsg, WPARAM wParam, LPARAM lParam );
    static BOOL CalcFixedCDMeasure( HWND hwnd, MEASUREITEMSTRUCT * pmis );

    virtual BOOL OnUserMessage( const EVENT & );

public:
    OWNER_WINDOW();
    OWNER_WINDOW( const TCHAR  *   pszClassName,
                  ULONG            flStyle,
                  const WINDOW *   pwndOwner );
    ~OWNER_WINDOW();

    // QueryRobustHwnd returns the hwnd of the window if it locks down the
    // parent window.  Otherwise, it returns the hwnd of the parent
    // window.
    // This method is used (especially) by the MsgPopup API, which
    // may be called before a window has locked down its parent.  If
    // QueryHwnd is called instead of this method, the MsgPopup may
    // accidentally become modeless if called before the window locks
    // down its parent.
    //
    virtual HWND QueryRobustHwnd() const = 0;

    VOID SetFocus( CID cid );
    VOID SetDialogFocus( CONTROL_WINDOW & ctrlwin );

    //  Return the entire attributes DWORD
    DWORD QueryAttributeFlags ()
        { return _dwAttributes ; }

    //  Set the entire attributes DWORD
    VOID SetAttributeFlags ( DWORD dwAttributes )
        { _dwAttributes = dwAttributes ; }

    //  Set a single attribute
    VOID SetAttribute ( DWORD dwAttribute, BOOL fOn = TRUE )
        {  if ( fOn )
              _dwAttributes |= dwAttribute ;
           else
              _dwAttributes &= ~ dwAttribute ;
        }

    //  Test a single attribute
    BOOL QueryAttribute ( DWORD dwAttribute )
        { return (_dwAttributes & dwAttribute) > 0 ; }
};


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

    NAME:       ASSOCHWNDTHIS

    SYNOPSIS:   Keeps a this-pointer in a window's properties

    INTERFACE:  ASSOCHWNDTHIS()     - ctor, associating the tuple
                ~ASSOCHWNDTHIS()    - dtor, removing the wndprops

                HwndToThis()        - given a hwnd, locates the
                                      corresponding this-pointer

    PARENT:     BASE

    HISTORY:
        beng        30-Sep-1991 Created

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

DLL_CLASS ASSOCHWNDTHIS: public BASE
{
private:
    static const TCHAR * _pszPropThisLo;
    static const TCHAR * _pszPropThisHi;

    HWND _hwnd;

public:
    ASSOCHWNDTHIS( HWND hwnd, const VOID * pwnd );
    ~ASSOCHWNDTHIS();

    static VOID * HwndToThis( HWND hwnd );
};


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

    NAME:       PROC_INSTANCE

    SYNOPSIS:   Procedure instance class

    INTERFACE:
        PROC_INSTANCE()  - constructor
        ~PROC_INSTANCE() - destructor
        QueryProc()      - return the procedure instance address

    PARENT:     BASE

    NOTES:
        This is a simple wrapper around MakeProcInstance.

        MakeProcInstance is a no-op on Win32.

    HISTORY:
        RustanL     21-Nov-1990 Created
        beng        30-Sep-1991 Changed op() to QueryProc, inlined
        beng        17-Oct-1991 Made conditional on not-Win32

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

DLL_CLASS PROC_INSTANCE : public BASE
{
private:
    MFARPROC _fpInstance;

public:
    PROC_INSTANCE( MFARPROC fp );
    ~PROC_INSTANCE();

    MFARPROC QueryProc() const
        { return _fpInstance; }
};


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

    NAME:       ITER_CTRL

    SYNOPSIS:   Iterate over each control within an owner window

    INTERFACE:  ITER_CTRL()     - ctor, taking owner window as argument
                Reset()         - resets iterator to its initial state
                Next()          - gets the next element in the sequence
                operator()()    - synonym for "Next"

    USES:       CONTROL_WINDOW, OWNBER_WINDOW, CONTROL_TABLE

    NOTES:
        The iterator returns controls in the order which they
        were constructed.

    CAVEATS:
        This is a pretty lightweight little iterator.  It performs
        no locking or other checking in the case of overlapping control
        add/deletes in the window.  Should you elect to add or remove
        a control, however, a Reset will correct the iterator.

    HISTORY:
        beng        30-Oct-1991 Created

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

DLL_CLASS ITER_CTRL
{
private:
    const OWNER_WINDOW *  _pwndOwning;
    const CONTROL_TABLE * _pctrltable;
    UINT _ictrl;
    UINT _cctrl;

public:
    ITER_CTRL( const OWNER_WINDOW * pwnd );

    VOID Reset();
    CONTROL_WINDOW * Next();
    CONTROL_WINDOW * operator()() { return Next(); }
};


#endif // _BLTWIN_HXX_ - end of file