/*
 * Xailer source code:
 *
 * ToolBar.prg
 * Clase TToolBar()
 *
 * Copyright 2003, 2007 Jose F. Gimenez
 * Copyright 2003, 2007 Xailer.com
 * All rights reserved
 *
 */

#include "Xailer.ch"
#include "CommCtrl.api"


//--------------------------------------------------------------------------

CLASS XToolBar FROM TControl

PUBLISHED:
   PROPERTY nWidth         INIT 120
   PROPERTY nHeight        INIT 28

   PROPERTY nBtnWidth      INIT 0   EDITOR PE_Scale
   PROPERTY nBtnHeight     INIT 0   EDITOR PE_Scale
   PROPERTY nIndent        INIT 0
   PROPERTY lFlat          INIT .T. WRITE INLINE ::ChangeCtlStyle( TBSTYLE_FLAT, Value ), ::Adjust(), ::FlFlat := Value
   PROPERTY lTransparent   INIT .T. WRITE INLINE ::ChangeCtlStyle( TBSTYLE_TRANSPARENT, Value ), ::Adjust(), ::FlTransparent := Value
   PROPERTY lList          INIT .F. WRITE INLINE ::ChangeCtlStyle( TBSTYLE_LIST, Value ), ::Adjust(), ::FlList := Value
   PROPERTY nAlign         INIT alTOP WRITE METHOD SetAlign
   PROPERTY lAutoSize      INIT .T.
   PROPERTY lAlwaysTip     INIT .F.
   PROPERTY lBalloons      INIT .F.
   PROPERTY nBorderStyle   INIT bvNONE
   PROPERTY nBorderSides

   PROPERTY oImageList     AS TImageList  WRITE METHOD SetImageList     EDITOR PE_ImageList
   PROPERTY oImageListHot  AS TImageList  WRITE METHOD SetImagelistHot  EDITOR PE_ImageList
   PROPERTY oImageListDis  AS TImageList  WRITE METHOD SetImagelistDis  EDITOR PE_ImageList

   EVENT OnDropDown( oSender, nItem )

PROTECTED:
   DATA cWinClassName INIT TOOLBARCLASSNAME
   DATA nCtlStyle     INIT nOR( WS_CHILD, WS_CLIPCHILDREN, WS_CLIPSIBLINGS, CCS_NOPARENTALIGN, CCS_NORESIZE, CCS_NODIVIDER, ;
                                TBSTYLE_TOOLTIPS, TBSTYLE_FLAT, TBSTYLE_TRANSPARENT )
   DATA nExStyle      INIT 0

   PROPERTY cText
   PROPERTY lBorder

PUBLIC:
   PROPERTY aItems   INIT {}  READONLY AS TToolButton[]
   DATA nBitmaps     INIT 0   READONLY

   // NOTA: Esto es para mantener la compatibilidad, pero se quitara mas adelante - [JFG]
   METHOD aButtons()    INLINE ::aItems
   PROPERTY oHots       WRITE METHOD SetImagelistHot  READ INLINE ::FoImageListHot AS TImageList
   PROPERTY oDisables   WRITE METHOD SetImagelistDis  READ INLINE ::FoImageListDis AS TImageList

   METHOD New( oParent ) CONSTRUCTOR
   METHOD Create( oParent, nBtnWidth, nBtnHeight, lFlat, lList ) CONSTRUCTOR
   METHOD Free()

   METHOD AddItem( cText, nImage, cToolTip, lAutoSize, lGroup, lChecked, lEnabled, lVisible, oMenu ) // --> oToolButton
   METHOD InsertItem( nPos, cText, nImage, cToolTip, lAutoSize, lGroup, lChecked, lEnabled, lVisible, oMenu ) // --> oToolButton
   METHOD DeleteItem( nItem ) // --> Nil
   METHOD AddButton( cText, cImage, cImage2, cImage3, cToolTip, OnClick, oMenu ) // --> oToolButton
   METHOD AddSeparator( nWidth ) // --> oToolButton
   METHOD InsertSeparator( nPos, nWidth ) // --> oToolButton

RESERVED:
   PROPERTY cBalloon
   PROPERTY cTooltip
   PROPERTY cTooltipTitle
   PROPERTY nTooltipIcon

   METHOD CreateHandle()
   METHOD Scale( nScale )
   METHOD SetAlign( nAlign )
   METHOD Adjust()
   METHOD AddImages( aImages, aImagesHot, aImagesDisabled )
   METHOD SetImageList()
   METHOD SetImageListHot()
   METHOD SetImageListDis()
   METHOD ShortCut( cKey )
   METHOD Click( cKey )
   METHOD SetShortCuts()
   METHOD FillImageList()
   METHOD BtnEnable( nButton, lEnable )    INLINE ::SendMsg( TB_ENABLEBUTTON, nButton + TB_ID_FIRST, IIF( lEnable == Nil, -1, lEnable ) )
   METHOD BtnDisable( nButton )            INLINE ::SendMsg( TB_ENABLEBUTTON, nButton + TB_ID_FIRST, 0 )
   METHOD BtnShow( nButton )               INLINE ::PostMsg( TB_HIDEBUTTON, nButton + TB_ID_FIRST, 0 )
   METHOD BtnHide( nButton )               INLINE ::PostMsg( TB_HIDEBUTTON, nButton + TB_ID_FIRST, -1 )
   METHOD BtnCheck( nButton, lCheck )      INLINE ::PostMsg( TB_CHECKBUTTON, nButton + TB_ID_FIRST, IIF( lCheck == Nil, -1, lCheck ) )
   METHOD BtnUncheck( nButton )            INLINE ::PostMsg( TB_CHECKBUTTON, nButton + TB_ID_FIRST, 0 )
   METHOD DropMenu( nButton, nLeft, nTop ) INLINE ::ShowPopupMenu( ::aItems[ nButton ]:oMenu, nLeft, nTop )
   METHOD Command( nNotifyCode, nId )
   METHOD Notify()
   METHOD WMSize()   INLINE IIF( ::lAutoSize, ::SendMsg( TB_AUTOSIZE, 0, 0 ), ), 0
   METHOD WMNCCalcSize()   EXTERN XControl_WMNCCalcSize()
   METHOD WMNCPaint()      EXTERN XControl_WMNCPaint()
   METHOD WMPrintClient()  VIRTUAL
   METHOD WMLButtonDown()

   METHOD ResetButtons()
   METHOD GetItemRect( nItem )
   METHOD HitTest( x, y )

ENDCLASS

//--------------------------------------------------------------------------

METHOD New( oParent ) CLASS XToolbar

   ::oParent := oParent
   ::FoImageList    := TImageList():Create( Self )
   ::FoImageListHot := TImageList():Create( Self )
   ::FoImageListDis := TImageList():Create( Self )

RETURN Self

//--------------------------------------------------------------------------

METHOD Create( oParent, nBtnWidth, nBtnHeight, lFlat, lList ) CLASS XToolBar

   LOCAL hTooltips

   UPDATE  ::oParent    TO oParent
   UPDATE  ::nBtnWidth  TO nBtnWidth
   UPDATE  ::nBtnHeight TO nBtnHeight
   UPDATE  ::lFlat      TO lFlat
   UPDATE  ::lList      TO lList

   InitCommonControls( ICC_COOL_CLASSES + ICC_BAR_CLASSES )

   ::Super:Create()

   ::SendMsg( TB_BUTTONSTRUCTSIZE, TBBUTTON_SIZE, 0 )
   ::SendMsg( TB_SETINDENT, ::nIndent, 0 )
   ::SendMsg( TB_SETEXTENDEDSTYLE, 0, TBSTYLE_EX_DRAWDDARROWS )
   ::SendMsg( TB_SETSTYLE, 0, nOr( ::nCtlStyle, TBSTYLE_CUSTOMERASE ) )
   ::SendMsg( TB_SETIMAGELIST, 0, ::oImageList:Handle )
   ::SendMsg( TB_SETHOTIMAGELIST, 0, ::oImageListHot:Handle )
   ::SendMsg( TB_SETDISABLEDIMAGELIST, 0, ::oImageListDis:Handle )
   ::SendMsg( TB_SETBUTTONSIZE, 0, MakeLong( ::nBtnWidth, ::nBtnHeight ) )

   IF ::lBalloons
      ::SendMsg( TB_SETTOOLTIPS, TBalloon():Create( Self ):Handle )
   ENDIF
   IF ::lAlwaysTip
      hTooltips := ::SendMsg( TB_GETTOOLTIPS, 0, 0 )
      SetWindowLong( hTooltips, GWL_STYLE, nOr( GetWindowLong( hTooltips, GWL_STYLE ), TTS_ALWAYSTIP ) )
      SetWindowPos( hTooltips, HWND_TOPMOST, 0, 0, 0, 0, nOr( SWP_NOACTIVATE, SWP_NOMOVE, SWP_NOSIZE, SWP_NOREDRAW ) )
   ENDIF

   ::FillImagelist()
   ::ResetButtons()
   ::SetShortCuts()
   ::Adjust()

   IF ::FoParent != Nil .AND. lAnd( ::nCtlStyle, WS_CHILD )
      ::FoParent:InsertControl( Self )
   ENDIF

RETURN Self

//--------------------------------------------------------------------------

METHOD CreateHandle() CLASS XToolbar

   ::GetForm()
   ::Register()
   IF ::FlVisible
      ::nCtlStyle := nOr( ::nCtlStyle, WS_VISIBLE )
   ENDIF
   IF .NOT. ::FlEnabled
      ::nCtlStyle := nOr( ::nCtlStyle, WS_DISABLED )
   ENDIF
   ::hTheme := Nil
   ::nId := ::oForm:GetNewID()
   ::OnBeforeCreate()
   ::Link()
   ::Scale( Application:nScale )
   IF ( ::Handle := CreateWindow( ::ClassName, ::FcText, ::nCtlStyle, ::nExStyle, ;
                                  ::FnLeft, ::FnTop, ::FnWidth, ::FnHeight, ;
                                  IIf( ::FoParent != Nil, ::FoParent:Handle, 0 ), ::nId ) ) != 0
      ::SetTheme()
      ::SetFont()
      ::SetBorderStyle()
      ::UpdateBounds()
      ::SetAnchors()
      ::SetTooltip( ::FcTooltip )
      ::SetBalloon( ::FcBalloon )
      ::SendMsg( WM_CHANGEUISTATE, MakeLong( UIS_INITIALIZE, UISF_HIDEFOCUS + UISF_HIDEACCEL ) )
      /* NOTA: No llamar a oParent:InsertControl( Self ) hasta que se hayan creado los botones, porque
               cuando oParent es una TRebar y Application:nScale != 100 se calcula mal el tamaņo [JFG]
      */
   ENDIF

RETURN ::Handle

//--------------------------------------------------------------------------

METHOD Free() CLASS XToolBar

   IF ::oImageList:oParent == Self
      ::oImageList:End()
   ENDIF
   IF ::oImageListHot:oParent == Self
      ::oImageListHot:End()
   ENDIF
   IF ::oImageListDis:oParent == Self
      ::oImageListDis:End()
   ENDIF

RETURN ::Super:Free()

//----------------------------------------------------------------------------

METHOD Scale( nScale ) CLASS XToolbar

   DEFAULT nScale TO Application:nScale

   IF nScale != 100
      ::FnLeft    := MulDiv( ::FnLeft, nScale, 100 )
      ::FnTop     := MulDiv( ::FnTop, nScale, 100 )
      ::FnWidth   := MulDiv( ::FnWidth, nScale, 100 )
      ::FnHeight  := MulDiv( ::FnHeight, nScale, 100 )
      ::nBtnWidth  := MulDiv( ::nBtnWidth, nScale, 100 )
      ::nBtnHeight := MulDiv( ::nBtnHeight, nScale, 100 )
   ENDIF

RETURN Nil

//----------------------------------------------------------------------------

METHOD SetAlign( nAlign ) CLASS XToolbar

   UPDATE ::FnAlign TO nAlign

   ::nCtlStyle := nExclude( ::nCtlStyle, CCS_TOP, CCS_BOTTOM, CCS_LEFT, CCS_RIGHT )
   IF ::FnAlign == alTOP
      ::nCtlStyle := nOr( ::nCtlStyle, CCS_TOP )
   ELSEIF ::FnAlign == alBOTTOM
      ::nCtlStyle := nOr( ::nCtlStyle, CCS_BOTTOM )
   ELSEIF ::FnAlign == alLEFT
      ::nCtlStyle := nOr( ::nCtlStyle, CCS_LEFT )
   ELSEIF ::FnAlign == alRIGHT
      ::nCtlStyle := nOr( ::nCtlStyle, CCS_RIGHT )
   ENDIF
   ::ChangeCtlStyle( TBSTYLE_WRAPABLE, ::FnAlign == alLEFT .OR. ::FnAlign == alRIGHT )
   ::ChangeExStyle()

RETURN ::FnAlign

//--------------------------------------------------------------------------

METHOD SetImageList( oImageList ) CLASS XToolbar

   IF ::FoImageList != Nil
      ::FoImageList:End()
   ENDIF
   ::FoImageList := oImageList
   ::SendMsg( TB_SETIMAGELIST, 0, ::FoImageList:Handle )
   ::FillImageList()

RETURN oImageList

//----------------------------------------------------------------------------

METHOD SetImageListHot( oImageList ) CLASS XToolbar

   IF ::FoImageListHot != Nil
      ::FoImageListHot:End()
   ENDIF
   ::FoImageListHot := oImageList
   ::SendMsg( TB_SETHOTIMAGELIST, 0, ::FoImageListHot:Handle )
   ::FillImageList()

RETURN oImageList

//----------------------------------------------------------------------------

METHOD SetImageListDis( oImageList ) CLASS XToolbar

   IF ::FoImageListDis != Nil
      ::FoImageListDis:End()
   ENDIF
   ::FoImageListDis := oImageList
   ::SendMsg( TB_SETDISABLEDIMAGELIST, 0, ::FoImageListDis:Handle )
   ::FillImageList()

RETURN oImageList

//----------------------------------------------------------------------------

METHOD FillImageList() CLASS XToolbar

   LOCAL nImages := ::oImageList:GetImageCount(), nImage

   IF ::oImageListHot:GetImageCount() == 0
      ::oImageListHot:SetIconSize( ::oImageList:nWidth, ::oImageList:nHeight )
   ENDIF
   FOR nImage := ::oImageListHot:GetImageCount() + 1 TO nImages
      ::oImageListHot:Add( ::oImageList:GetBitmap( nImage ) )
   NEXT

   IF ::oImageListDis:GetImageCount() == 0
      ::oImageListDis:SetIconSize( ::oImageList:nWidth, ::oImageList:nHeight )
   ENDIF
   FOR nImage := ::oImageListDis:GetImageCount() + 1 TO nImages
      ::oImageListDis:Add( ::oImageList:GetBitmap( nImage ), .T. )
   NEXT

RETURN Nil

//----------------------------------------------------------------------------

METHOD ShortCut( cKey ) CLASS XToolBar

   ::Click( cKey )

RETURN 0

//--------------------------------------------------------------------------

METHOD Click( cKey ) CLASS XToolBar

   LOCAL n, nAt

   IF ! Empty( cKey )
      cKey := Upper( cKey )
      FOR n := 1 TO Len( ::aItems )
         IF ( nAt := At( "&", ::aItems[ n ]:cText ) ) > 0 .AND. Upper( Substr( ::aItems[ n ]:cText, nAt + 1, 1 ) ) == cKey
            ::aItems[ n ]:Click()
            EXIT
         ENDIF
      NEXT
   ENDIF

RETURN Nil

//--------------------------------------------------------------------------

METHOD SetShortCuts() CLASS XToolBar

   LOCAL aKeys := {}, nAt

   IF ::oForm != Nil
      ::oForm:DelShortCut( Self )
      AEval( ::aItems, {| oItem | IIf( ( nAt := At( "&", oItem:cText ) ) > 0, AAdd( aKeys, Substr( oItem:cText, nAt + 1, 1 ) ), ) } )
      IF !Empty( aKeys )
         ::oForm:AddShortCut( Self, aKeys )
      ENDIF
   ENDIF

RETURN Nil

//--------------------------------------------------------------------------

METHOD AddItem( cText, nImage, cToolTip, lAutoSize, lGroup, lChecked, lEnabled, lVisible, oMenu ) CLASS XToolBar
RETURN TToolButton():Create( Self, 0, .F., cText, nImage, cToolTip, lAutoSize, lGroup, lChecked, lEnabled, lVisible, oMenu )

//----------------------------------------------------------------------------

METHOD InsertItem( nPos, cText, nImage, cToolTip, lAutoSize, lGroup, lChecked, lEnabled, lVisible, oMenu ) CLASS XToolBar
RETURN TToolButton():Create( Self, nPos, .F., cText, nImage, cToolTip, lAutoSize, lGroup, lChecked, lEnabled, lVisible, oMenu )

//----------------------------------------------------------------------------

METHOD DeleteItem( nItem ) CLASS XToolBar

   IF nItem > 0 .AND. nItem <= Len( ::aItems )
      ADel( ::aItems, nItem )
      ASize( ::aItems, Len( ::aItems ) - 1 )
      ::ResetButtons()
      ::SetShortCuts()
      ::Adjust()
   ENDIF

RETURN Nil

//----------------------------------------------------------------------------

METHOD AddButton( cText, cImage, cImage2, cImage3, cToolTip, OnClick, oMenu ) CLASS XToolBar

   LOCAL oItem

   ::AddImages( { cImage }, { cImage2 }, { cImage3 } )
   WITH OBJECT oItem := TToolButton():Create( Self, 0, .F., cText, ::nBitmaps, cToolTip,,,,,, oMenu )
      :OnClick := OnClick
      :SetInfo()
   END
   ::SetShortCuts()
   ::Adjust()

RETURN oItem

//----------------------------------------------------------------------------

METHOD AddSeparator( nWidth, lVisible ) CLASS XToolBar
RETURN ::InsertSeparator( 0, nWidth, lVisible )

//----------------------------------------------------------------------------

METHOD InsertSeparator( nPos, nWidth, lVisible ) CLASS XToolBar

   DEFAULT nWidth TO 0

   IF nWidth != 0 .AND. Application:nScale != 100
      nWidth := MulDiv( nWidth, Application:nScale, 100 )
   ENDIF

RETURN TToolButton():Create( Self, nPos, .T.,, nWidth,,,,,, lVisible )

//----------------------------------------------------------------------------

METHOD AddImages( aImages, aImagesHot, aImagesDisabled ) CLASS XToolBar

   LOCAL n

   FOR n := 1 TO Len( aImages )
      ::oImageList:Add( aImages[ n ] )
      IF Empty( aImagesHot ) .OR. Len( aImagesHot ) < n .OR. ValType( aImagesHot[ n ] ) != "C"
         ::oImageListHot:Add( aImages[ n ] )
      ELSE
         ::oImageListHot:Add( aImagesHot[ n ] )
      ENDIF
      IF Empty( aImagesDisabled ) .OR. Len( aImagesDisabled ) < n .OR. ValType( aImagesDisabled[ n ] ) != "C"
         ::oImageListDis:Add( aImages[ n ], .T. )
      ELSE
         ::oImageListDis:Add( aImagesDisabled[ n ] )
      ENDIF
      ::nBitmaps++
   NEXT

RETURN Nil

//--------------------------------------------------------------------------

METHOD Command( nNotifyCode, nId ) CLASS XToolbar

   IF nNotifyCode == BN_CLICKED .AND. nId >= TB_ID_FIRST + 1 .AND. nId <= TB_ID_FIRST + Len( ::aItems )
      ::aItems[ nId - TB_ID_FIRST ]:Click()
      RETURN 0
   ENDIF

RETURN Nil

//--------------------------------------------------------------------------

METHOD WMLButtonDown( nWParam, nLParam ) CLASS XToolbar

   IF GetCapture() == ::Handle
      PrevWindowProc( ::Handle, WM_RBUTTONUP, 0, 0 )
      ProcessMessages()
   ENDIF

RETURN ::Super:WMLButtonDown( nWParam, nLParam )

//--------------------------------------------------------------------------

#pragma BEGINDUMP

#define _WIN32_IE 0x0501

#include <windows.h>
#include <commctrl.h>
#include <xailer.h>
#include <constants.ch>

//--------------------------------------------------------------------------

HB_FUNC_STATIC( XTOOLBAR_RESETBUTTONS )
{
   PHB_ITEM Self = hb_stackSelfItem();
   HWND hWnd = GetHandleOf( Self );
   PHB_ITEM aItems = XA_ObjGetItemCopy( Self, "aItems" );
   int nItems, nItem;
   int nBmpWidth, nBmpHeight;
   int nBtnWidth = XA_ObjGetNL( Self, "nBtnWidth" );
   int nBtnHeight = XA_ObjGetNL( Self, "nBtnHeight" );
   TBBUTTON *tb;

   nItems = SendMessage( hWnd, TB_BUTTONCOUNT, 0, 0 );
   while( nItems-- )
      SendMessage( hWnd, TB_DELETEBUTTON, 0, 0 );

   ImageList_GetIconSize( (HANDLE) SendMessage( hWnd, TB_GETIMAGELIST, 0, 0 ), &nBmpWidth, &nBmpHeight );
   SendMessage( hWnd, TB_BUTTONSTRUCTSIZE, sizeof( TBBUTTON ), 0 );
   SendMessage( hWnd, TB_SETBITMAPSIZE, 0, MAKELONG( nBmpWidth, nBmpHeight ) );

   nItems = hb_arrayLen( aItems );
   if( nItems == 1 )
      {
      if( nBtnHeight == 0 )
         nBtnHeight = XA_ObjGetNL( Self, "nHeight" ) - 2;
      SendMessage( hWnd, TB_SETBUTTONSIZE, 0, MAKELONG( nBtnWidth ? nBtnWidth : 2048, nBtnHeight ) );
      SendMessage( hWnd, TB_AUTOSIZE, 0, 0 );
      }

   if( nItems )
      {
      tb = hb_xgrab( nItems * sizeof( TBBUTTON ) );
      memset( tb, 0, nItems * sizeof( TBBUTTON ) );

      for( nItem = 0; nItem < nItems; nItem++ )
         {
         PHB_ITEM oItem = hb_itemArrayGet( aItems, nItem + 1 );
         int nImage = XA_ObjGetNL( oItem, "nImage" );
         char * cText = XA_ObjGetC( oItem, "cText" );

         XA_ObjSendNL( oItem, "_nIndex", nItem + 1 );
         if( XA_ObjGetL( oItem, "lSeparator" ) )
            {
            tb[ nItem ].fsStyle   = BTNS_SEP;
            tb[ nItem ].iString   = -1;
            }
         else
            {
            if( --nImage < 0 )
               nImage   = I_IMAGENONE;
            tb[ nItem ].fsStyle   = BTNS_BUTTON;
            tb[ nItem ].fsStyle  |= ( XA_ObjGetL( oItem, "lAutoSize" ) ? BTNS_AUTOSIZE : 0 );
            if( ( nBtnWidth == 0 ) || ( nBtnHeight == 0 ) || XA_ObjGetL( Self, "lList" ) )
               tb[ nItem ].fsStyle  |= BTNS_AUTOSIZE;
            tb[ nItem ].fsStyle  |= ( XA_ObjGetL( oItem, "lGroup" ) ? BTNS_GROUP | BTNS_CHECK : 0 );
            if( XA_ObjGetItem( oItem, "oMenu" ) )
               tb[ nItem ].fsStyle  |= ( XA_EventAssigned( oItem, "OnClick" ) ? BTNS_DROPDOWN : BTNS_WHOLEDROPDOWN );
            tb[ nItem ].dwData    = 0;
            tb[ nItem ].iString   = ( ( cText && *cText ) ? (INT_PTR) cText : -1 );
            }
         tb[ nItem ].idCommand = nItem + TB_ID_FIRST + 1;
         tb[ nItem ].iBitmap   = nImage;
         tb[ nItem ].fsState   = XA_ObjGetL( oItem, "lEnabled" ) ? TBSTATE_ENABLED : 0;
         tb[ nItem ].fsState  |= XA_ObjGetL( oItem, "lChecked" ) ? TBSTATE_CHECKED : 0;
         tb[ nItem ].fsState  |= XA_ObjGetL( oItem, "lVisible" ) ? 0 : TBSTATE_HIDDEN;
         hb_itemRelease( oItem );
         }
      SendMessage( hWnd, TB_ADDBUTTONS, nItems, (LPARAM) tb );
      if( nBtnHeight != 0 )
         SendMessage( hWnd, TB_SETBUTTONSIZE, 0, MAKELONG( nBtnWidth, nBtnHeight ) );
      hb_xfree( tb );
      }

   hb_itemRelease( aItems );
}

//--------------------------------------------------------------------------

HB_FUNC_STATIC( XTOOLBAR_ADJUST )
{
   PHB_ITEM Self = hb_stackSelfItem();
   HANDLE handle = GetHandleOf( Self );
   RECT rct = { 0, 0, 0, 0 };
   UINT nBorderStyle;

   if ( XA_ObjGetL( Self, "lAutoSize" ) )
      {
      /* NOTA: Este metodo para calcular las dimensiones de la toolbar deberia
               ser el correcto, pero en Win98 no funciona bien.
               El segundo metodo funciona en Win98 y XP, pero habria
               que calcular sobre el ultimo boton que este visible.
      */
      int nButton = SendMessage( handle, TB_BUTTONCOUNT, 0, 0 ) - 1;

      if( GetWindowLong( handle, GWL_STYLE ) & CCS_VERT )
         {
         DWORD nBtnSize = SendMessage( handle, TB_GETBUTTONSIZE, 0, 0 );

         SetWindowPos( handle, NULL, 0, 0, LOWORD( nBtnSize ) + 3, HIWORD( nBtnSize ) + 2,
                       SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOZORDER );
         }

      if( nButton >= 0 )
         {
         while( ( nButton >= 0 ) && !SendMessage( handle, TB_GETITEMRECT, nButton, (LPARAM) &rct ) )
            nButton--;
         nBorderStyle = XA_ObjGetNL( Self, "nBorderStyle" );
         switch ( nBorderStyle )
            {
            case bvFLAT:
            case bvHALFRAISED:
            case bvHALFSUNKEN: rct.bottom += 1; break;
            case bvRAISED:
            case bvSUNKEN:
            case bvBUMP:
            case bvETCHED:
            case bvWIN10: rct.bottom += 2; break;
            }
         SetWindowPos( handle, NULL, 0, 0, rct.right + 3, rct.bottom + 2,
                       SWP_NOMOVE | SWP_NOSENDCHANGING | SWP_NOZORDER );

         hb_vmPushDynSym( hb_dynsymFindName( "SetBounds" ) );
         hb_vmPush( Self );
         hb_vmPushNil();
         hb_vmPushNil();
         hb_vmPushLong( rct.right + 3 );
         hb_vmPushLong( rct.bottom + 2 );
         hb_vmSend( 4 );
         }
      }
   hb_ret();
}

//--------------------------------------------------------------------------

HB_FUNC_STATIC( XTOOLBAR_NOTIFY )
{
   PHB_ITEM Self = hb_stackSelfItem();
   LPNMHDR nmhdr = (LPNMHDR) hb_parnl( 2 );

   hb_ret();
   switch( nmhdr->code )
      {
      case TBN_DROPDOWN:
         {
         LPNMTOOLBAR nmtb = (LPNMTOOLBAR) nmhdr;
         UINT nButton = nmtb->iItem - TB_ID_FIRST;
         RECT rct;
         POINT pt;

         XA_ObjSendNL( Self, "OnDropDown", nButton );
         if( HB_ISNIL( -1 ) || hb_parl( -1 ) )
            {
            SendMessage( nmtb->hdr.hwndFrom, TB_GETITEMRECT, nButton - 1, (LPARAM) &rct );
            pt.x = rct.left;
            pt.y = rct.bottom;
            XA_ObjSendNL3( Self, "DropMenu", nButton, pt.x, pt.y );
            }
         hb_retnl( TBDDRET_DEFAULT );
         break;
         }

      case TBN_GETINFOTIP:
         {
         LPNMTBGETINFOTIP nmgit = (LPNMTBGETINFOTIP) nmhdr;
         int nButton = nmgit->iItem - TB_ID_FIRST;
         PHB_ITEM oButton = hb_itemArrayGet( XA_ObjGetItem( Self, "aItems" ), nButton );
         char *cText = XA_ObjGetC( oButton, "cTooltip" );

         if( cText )
            strncpy( nmgit->pszText, cText, nmgit->cchTextMax );
         hb_itemRelease( oButton );
         break;
         }

      case NM_CUSTOMDRAW:
         {
         LPNMCUSTOMDRAW nmcd = (LPVOID) nmhdr;

         switch ( nmcd->dwDrawStage )
            {
            case CDDS_PREERASE:
               hb_retnl( CDRF_NOTIFYPOSTERASE );
               break;

            case CDDS_POSTERASE:
               {
               HWND hWnd = GetHandleOf( Self );
               RECT rect;

               GetClientRect( hWnd, &rect );
               if( XA_ObjGetL( Self, "lTransparent" ) )
                  XA_DrawParentBackground( hWnd, nmcd->hdc, &rect );
               else
                  {
                  HBRUSH hbr = CreateSolidBrush( XA_ObjGetNL( Self, "nClrPane" ) );
                  FillRect( nmcd->hdc, &rect, hbr );
                  DeleteObject( hbr );
                  }
               hb_retnl( CDRF_DODEFAULT );
               }
            }
         }
      }
}

//--------------------------------------------------------------------------

HB_FUNC_STATIC( XTOOLBAR_GETITEMRECT )
{
   PHB_ITEM Self = hb_stackSelfItem();
   HWND hWnd = GetHandleOf( Self );
   RECT rct;

   SendMessage( hWnd, TB_GETITEMRECT, hb_parnl( 1 ) - 1, (LPARAM) &rct );

   hb_reta( 4 );
   hb_storvnl( rct.left  , -1, 1 );
   hb_storvnl( rct.top   , -1, 2 );
   hb_storvnl( rct.right , -1, 3 );
   hb_storvnl( rct.bottom, -1, 4 );
}

//--------------------------------------------------------------------------

HB_FUNC_STATIC( XTOOLBAR_HITTEST )
{
   PHB_ITEM Self = hb_stackSelfItem();
   HWND hWnd = GetHandleOf( Self );
   POINT pt;

   pt.x = hb_parnl( 1 );
   pt.y = hb_parnl( 2 );
   hb_retnl( SendMessage( hWnd, TB_HITTEST, 0, (LPARAM) &pt ) + 1 );
}

#pragma ENDDUMP

//--------------------------------------------------------------------------
