/*
 * Xailer source code:
 *
 * OptionList.prg
 * Class TOptionList
 *
 * Copyright 2003, 2007 Jose Lalin
 * Copyright 2003, 2007 Jose F. Gimenez
 * Copyright 2003, 2007 Xailer.com
 * All rights reserved
 *
 */

#include "Xailer.ch"


//--------------------------------------------------------------------------

CLASS XOptionList FROM TStdControl

PUBLISHED:
   PROPERTY nWidth         INIT 100
   PROPERTY nHeight        INIT 100
   PROPERTY nClrPane       INIT clBtnFace
   PROPERTY nClrText       INIT clHighLight
   PROPERTY nClrTextHot    INIT clActiveCaption EDITOR PE_Color
   PROPERTY nBorderStyle   INIT bvNONE
   PROPERTY nBorderSides
   PROPERTY nHotStyle      INIT hsUNDERLINE  VALUES hsUNDERLINE, hsMENU, hsMENUXP, hsMENU2003

   PROPERTY oFont          WRITE METHOD SetFont AS TFont

   PROPERTY nTopMargin     INIT 8
   PROPERTY nLeftMargin    INIT 8
   PROPERTY lTabStop       INIT .T.
   PROPERTY lTransparent   INIT .T.
   PROPERTY nOpacity       INIT 0
   PROPERTY lAutoSize      INIT .F. WRITE METHOD SetAutoSize
   PROPERTY nItemHeight    INIT 16  WRITE INLINE ::FnItemHeight := Value, ::SetAutoSize(), ::FnItemHeight   EDITOR PE_Scale

   PROPERTY oImageList     AS TImageList  WRITE METHOD SetImageList  EDITOR PE_ImageList

   PROPERTY nScrollIncrement  INIT 8

   EVENT OnScrollUp( oSender, nPos ) // --> Nil
   EVENT OnScrollDown( oSender, nPos ) // --> Nil
   EVENT OnScrollPageUp( oSender, nPos ) // --> Nil
   EVENT OnScrollPageDown( oSender, nPos ) // --> Nil
   EVENT OnThumbTrackV( oSender, nPos ) // --> Nil
   EVENT OnThumbPosV( oSender, nPos ) // --> Nil

PROTECTED:
   DATA nClassStyle  INIT nOr( CS_HREDRAW, CS_VREDRAW )
   DATA nCtlStyle    INIT nOr( WS_CHILD, WS_CLIPCHILDREN, WS_CLIPSIBLINGS )
   DATA nHotItem     INIT 0

   PROPERTY nClientTop     INIT 0 WRITE METHOD SetScroll
   PROPERTY nVirtualHeight INIT 0 WRITE INLINE ::SetScroll( , Value )

   EVENT OnDblClick

PUBLIC:
   PROPERTY nMargin  INIT 8  WRITE INLINE ::nLeftMargin := Value, ::nTopMargin := Value
   PROPERTY aItems   INIT {} WRITE INLINE ( ::FaItems := Value, ::SetShortCuts(), Value ) AS TOptionItem[]

   METHOD New( oParent ) CONSTRUCTOR
   METHOD Create( oParent ) CONSTRUCTOR
   METHOD Free()
   METHOD Scale( nScale )

   METHOD InsertItem( nPos, cText, nImage, nType, lMultiline, lEnabled, lChecked, lCollapsable, lExpanded, nChildIndent, nImageDisabled ) // --> oItem
   METHOD AddItem( cText, nImage, nType, lMultiline, lEnabled, lChecked, lCollapsable, lExpanded, nChildIndent, nImageDisabled ) // --> oItem
   METHOD AddSeparator()   INLINE ::AddItem( ,, otSEPARATOR ) // --> oItem

   METHOD GetItemByPos( nPos ) // --> oItem
   METHOD GetItemPos( oItem ) // --> nPosition
   METHOD GetItemCount() // --> nCount

   METHOD SetShortCuts()
   METHOD ShortCut( cKey )
   METHOD HitTest( x, y )

RESERVED:
   PROPERTY cText

   METHOD SetImageList( oImageList )
   METHOD GetItemRect( nPos )
   METHOD SetAutoSize( lAutoSize )
   METHOD SetScroll( nClientTop, nVirtualHeight )
   METHOD SetFont( oFont, lParentFont )

   METHOD AlignControls()     INLINE ::Refresh()

   METHOD WMEraseBkgnd()      INLINE 1
   METHOD WMPaint()
   METHOD WMLButtonDown()
   METHOD WMSetCursor()       VIRTUAL
   METHOD WMMouseMove()
   METHOD WMMouseLeave()      INLINE IIf( ::nHotItem > 0, ( ::nHotItem := 0, ::Refresh( .F. ) ), )
   METHOD WMKillFocus( hCtl ) INLINE ( ::Super:WMKillFocus( hCtl ), ::Refresh( .F. ) )
   METHOD WMSetFocus( hCtl )  INLINE ( ::Super:WMSetFocus( hCtl ), ::Refresh( .F. ) )
   METHOD WMVScroll()         EXTERN XScrollingWinControl_WMVScroll()
   METHOD WMWindowPosChanged()

ENDCLASS

//--------------------------------------------------------------------------

METHOD New( oParent ) CLASS XOptionList

   ::oImageList := TImageList():Create( Self )

RETURN ::Super:New( oParent )

//--------------------------------------------------------------------------

METHOD Create( oParent ) CLASS XOptionList

   ::Super:Create( oParent )
   ::SetAutoSize()
   ::SetShortCuts()

RETURN Self

//--------------------------------------------------------------------------

METHOD Free() CLASS XOptionList

   LOCAL n

   FOR n := Len( ::aItems ) TO 1 STEP -1
      ::aItems[ n ]:End()
   NEXT
   ::oImageList := Nil

RETURN ::Super:Free()

//--------------------------------------------------------------------------

METHOD Scale( nScale ) CLASS XOptionList

   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 )
      ::nItemHeight := MulDiv( ::nItemHeight, Application:nScale, 100 )
   ENDIF

RETURN Nil

//----------------------------------------------------------------------------

METHOD SetImageList( oImageList ) CLASS XOptionList

   IF ::FoImageList != Nil .AND. ::FoImageList:oParent == Self
      ::FoImageList:Destroy()
   ENDIF
   ::FoImageList := oImageList

RETURN ::FoImageList

//--------------------------------------------------------------------------

METHOD InsertItem( nPos, cText, nImage, nType, lMultiline, lEnabled, lChecked, lCollapsable, lExpanded, nChildIndent, nImageDisabled ) CLASS XOptionList
RETURN TOptionItem():Create( Self, nPos, cText, nImage, nType, lMultiline, lEnabled, lChecked, lCollapsable, lExpanded, nChildIndent, nImageDisabled )

//--------------------------------------------------------------------------

METHOD AddItem( cText, nImage, nType, lMultiline, lEnabled, lChecked, lCollapsable, lExpanded, nChildIndent, nImageDisabled ) CLASS XOptionList
RETURN TOptionItem():Create( Self, -1, cText, nImage, nType, lMultiline, lEnabled, lChecked, lCollapsable, lExpanded, nChildIndent, nImageDisabled )

//--------------------------------------------------------------------------

METHOD SetAutoSize( lAutoSize ) CLASS XOptionList

   LOCAL aRect

   UPDATE ::FlAutoSize TO lAutoSize

   IF ! Empty( ::Handle )
      aRect := ::GetItemRect( -1 )
      IF ::FlAutoSize
         ::nHeight := aRect[ 4 ] + ::nTopMargin
         ::oParent:AlignControls()
      ELSE
         ::nVirtualHeight := aRect[ 4 ] - ::nClientTop + ::nTopMargin
      ENDIF
      ::Refresh()
   ENDIF

RETURN ::FlAutoSize

//--------------------------------------------------------------------------

METHOD SetScroll( nClientTop, nVirtualHeight ) CLASS XOptionList

   UPDATE ::FnClientTop TO nClientTop
   UPDATE ::FnVirtualHeight TO nVirtualHeight

   IF ! Empty( ::Handle )
      IF ::FnClientTop + ::FnVirtualHeight < ::nClientHeight
         ::FnClientTop := Min( ::nClientHeight - ::FnVirtualHeight, 0 )
      ENDIF
      SetScrollInfo( ::Handle, SB_VERT, 0, ::FnVirtualHeight - 1, ::nClientHeight, -::FnClientTop, .F., .T. )
   ENDIF

RETURN Nil

//--------------------------------------------------------------------------

METHOD SetFont( oFont, lParentFont ) CLASS XOptionList

   IF PCount() == 0
      ::Super:SetFont()
   ELSEIF PCount() == 1
      ::Super:SetFont( oFont )
   ELSE
      ::Super:SetFont( oFont, lParentFont )
   ENDIF
   ::SetAutoSize()

RETURN ::FoFont

//--------------------------------------------------------------------------

METHOD WMWindowPosChanged() CLASS XOptionList

   ::UpdateBounds()
   ::SetAutoSize()

RETURN Nil

//--------------------------------------------------------------------------

STATIC FUNCTION GetItemByPos( aItems, nPos )

   LOCAL oItem, nItem := 1, nItems := Len( aItems )

   WHILE nPos > 0 .AND. nItem <= nItems .AND. oItem == Nil
      IF ( --nPos ) == 0
         oItem := aItems[ nItem ]
      ELSEIF !Empty( aItems[ nItem ]:aItems )
         oItem := GetItemByPos( aItems[ nItem ]:aItems, @nPos )
      ENDIF
      nItem++
   ENDDO

RETURN oItem

//--------------------------------------------------------------------------

METHOD GetItemByPos( nPos ) CLASS XOptionList
RETURN GetItemByPos( ::aItems, @nPos )

//--------------------------------------------------------------------------

STATIC FUNCTION GetItemPos( oItem, aItems, nPos, lOnlyVisible )

   LOCAL nItem := 1, nItems := Len( aItems )

   WHILE nItem <= nItems
      nPos++
      IF aItems[ nItem ] == oItem
         RETURN nPos
      ELSEIF !Empty( aItems[ nItem ]:aItems ) .AND. ( !lOnlyVisible .OR. aItems[ nItem ]:lExpanded )
         IF ( nPos := GetItemPos( oItem, aItems[ nItem ]:aItems, @nPos, lOnlyVisible ) ) > 0
            RETURN nPos
         ENDIF
      ENDIF
      nItem++
   ENDDO

RETURN 0

//--------------------------------------------------------------------------

METHOD GetItemPos( oItem, lOnlyVisible ) CLASS XOptionList

   LOCAL nPos := 0

   DEFAULT lOnlyVisible TO .F.

RETURN GetItemPos( oItem, ::aItems, @nPos, lOnlyVisible )

//--------------------------------------------------------------------------

STATIC FUNCTION GetItemCount( aItems )

   LOCAL nCount := 0, nItem, nItems := Len( aItems )

   FOR nItem := 1 TO nItems
      IF !Empty( aItems[ nItem ]:aItems )
         nCount += GetItemCount( aItems[ nItem ]:aItems, @nCount )
      ENDIF
      nCount++
   NEXT

RETURN nCount

//--------------------------------------------------------------------------

METHOD GetItemCount() CLASS XOptionList
RETURN GetItemCount( ::aItems )

//--------------------------------------------------------------------------

METHOD SetShortCuts() CLASS XOptionList

   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 ShortCut( cKey ) CLASS XOptionList

   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 0

//--------------------------------------------------------------------------

#pragma BEGINDUMP

#include <windows.h>
#include <commctrl.h>
#include <xailer.h>
#include <constants.ch>

//--------------------------------------------------------------------------

static BOOL GetItemRect( LPRECT rect, PHB_ITEM aItems, int nItem, int *nLine, HDC hdc, LPSIZE imgSize, int nItemHeight )
{
   int nItems = hb_arrayLen( aItems ), nChilds;
   int n, nIndent;

   for( n = 1; ( ( nItem == -1 ) || ( *nLine <= nItem ) ) && ( n <= nItems ); n++ )
      {
      PHB_ITEM oItem = hb_itemArrayGet( aItems, n ), aChilds;
      LPSTR cText = XA_ObjGetCBuf( oItem, "cText" );
      int nType = XA_ObjGetNL( oItem, "nType" ), nIncY;
      SIZE size;

      nIndent = 0;
      nIncY = nItemHeight;
      if( ( nType == otCHECK ) || ( nType == otRADIO ) )
         nIndent = 18;
      else if( nType == otSEPARATOR )
         nIncY = 8;
      else if( ( nType == otBUTTON ) && ( imgSize->cx > 0 ) )
         {
         nIndent = imgSize->cx + 4;
         if( nIncY < imgSize->cy )
            nIncY = imgSize->cy;
         }
      if( cText && *cText && ( nType != otSEPARATOR ) )
         {
         if( XA_ObjGetL( oItem, "lMultiline" ) )
            {
            RECT textRect;

            textRect.left = rect->left + nIndent;
            textRect.top = rect->top;
            textRect.right = rect->right;
            if( textRect.right <= textRect.left )
               textRect.right = textRect.left + 1;
            textRect.bottom = 0;
            DrawText( hdc, cText, -1, &textRect, DT_LEFT | DT_WORDBREAK | DT_CALCRECT );
            if( textRect.bottom - textRect.top > nIncY )
               nIncY = textRect.bottom - textRect.top;
            }
         else
            GetTextExtentPoint32( hdc, cText, strlen( cText ), &size );
         }
      else
         {
         size.cx = 0;
         size.cy = 0;
         }
      size.cx += nIndent;

      rect->top = rect->bottom;
      rect->bottom += nIncY + 2;
      (*nLine)++;

      if( ( n < nItem ) || ( nItem == - 1 ) )
         {
         aChilds = XA_ObjGetItemCopy( oItem, "aItems" );
         if( ( nChilds = hb_arrayLen( aChilds ) ) != 0 )
            {
            if( XA_ObjGetL( oItem, "lExpanded" ) )
               {
               int nChildIndent = XA_ObjGetNL( oItem, "nChildIndent" );

               rect->left += nIndent + nChildIndent;
               GetItemRect( rect, aChilds, nItem, nLine, hdc, imgSize, nItemHeight );
               rect->left -= nIndent + nChildIndent;
               }
            else
               *nLine += nChilds;
            }
         hb_itemRelease( aChilds );
         }

      XA_FreeCBuf( cText );
      hb_itemRelease( oItem );
      }

   return( n == nItem );
}

//--------------------------------------------------------------------------

HB_FUNC_STATIC( XOPTIONLIST_GETITEMRECT )
{
   PHB_ITEM Self = hb_stackSelfItem();
   HWND hWnd = GetHandleOf( Self );
   HDC hdc = GetDC( hWnd );
   PHB_ITEM aItems = XA_ObjGetItemCopy( Self, "aItems" );
   HFONT hFont = (HFONT) GetHandleOf( XA_ObjGetItem( Self, "oFont" ) );
   HFONT hOldFont = SelectObject( hdc, hFont );
   HANDLE hIL = GetHandleOf( XA_ObjGetItem( Self, "oImageList" ) );
   int nItem = hb_parnl( 1 ), nLine = 1;
   int nItemHeight = XA_ObjGetNL( Self, "nItemHeight" );
   SIZE imgSize = { 0, 16 };
   RECT rect = { 0, 0, 0, 0 };
   TEXTMETRIC tm;

   GetTextMetrics( hdc, &tm );
   if( tm.tmHeight > nItemHeight )
      nItemHeight = tm.tmHeight;

   if( hIL && ImageList_GetImageCount( hIL ) )
      ImageList_GetIconSize( hIL, (int *) &imgSize.cx, (int *) &imgSize.cy );

   if( hb_arrayLen( aItems ) > 0 )
      {
      rect.left = XA_ObjGetNL( Self, "nLeftMargin" );
      rect.right = XA_ObjGetNL( Self, "nClientWidth" ) - 4;
      rect.bottom = XA_ObjGetNL( Self, "nClientTop" ) + XA_ObjGetNL( Self, "nTopMargin" );
      GetItemRect( &rect, aItems, nItem, &nLine, hdc, &imgSize, nItemHeight );
      }

   hb_itemRelease( aItems );

   SelectObject( hdc, hOldFont );

   ReleaseDC( hWnd, hdc );

   hb_reta( 4 );
   hb_storvnl( rect.left, -1, 1 );
   hb_storvnl( rect.top, -1, 2 );
   hb_storvnl( rect.right, -1, 3 );
   hb_storvnl( rect.bottom, -1, 4 );
}

//--------------------------------------------------------------------------

static int _HitTest( int x, int y, PHB_ITEM aItems, HDC hdc, int *nLeft, int *nTop, int *nRight,
                     int *nLine, PHB_ITEM oHitItem, LPSIZE imgSize, int nItemHeight, BOOL lFullWidth )
{
   int nItems = hb_arrayLen( aItems ), nChilds;
   int nItem = 0, n, nIndent;
   RECT rect = { 0, 0, 0, 0 };

   for( n = 1; ( n <= nItems ) && ( nItem == 0 ); n++ )
      {
      PHB_ITEM oItem = hb_itemArrayGet( aItems, n ), aChilds;
      LPSTR cText = XA_ObjGetCBuf( oItem, "cText" );
      int nType = XA_ObjGetNL( oItem, "nType" ), nIncY;
      SIZE size;

      nIndent = 0;
      nIncY = nItemHeight;
      if( ( nType == otCHECK ) || ( nType == otRADIO ) )
         nIndent = 18;
      else if( nType == otSEPARATOR )
         nIncY = 8;
      else if( ( nType == otBUTTON ) && ( imgSize->cx > 0 ) )
         {
         nIndent = imgSize->cx + 4;
         if( nIncY < imgSize->cy )
            nIncY = imgSize->cy;
         }
      if( cText && *cText && ( nType != otSEPARATOR ) )
         {
         if( XA_ObjGetL( oItem, "lMultiline" ) )
            {
            rect.right = *nRight - nIndent;
            rect.bottom = 0;
            DrawText( hdc, cText, -1, &rect, DT_LEFT | DT_WORDBREAK | DT_CALCRECT );
            if( rect.bottom > nIncY )
               nIncY = rect.bottom;
            size.cx = rect.right;
            }
         else
            GetTextExtentPoint32( hdc, cText, strlen( cText ), &size );
         }
      else
         {
         size.cx = 0;
         size.cy = 0;
         }
      size.cx += nIndent;

      if( ( y >= *nTop ) && ( y <= *nTop + nIncY ) )
         {
         if( ( x >= *nLeft ) && ( lFullWidth || ( x <= *nLeft + size.cx ) ) )
            {
            nItem = *nLine;
            if( oHitItem )
               hb_itemCopy( oHitItem, oItem );
            }
         else
            nItem = -1;
         }

      (*nTop) += nIncY + 2;
      (*nLine)++;

      if( nItem == 0 )
         {
         aChilds = XA_ObjGetItemCopy( oItem, "aItems" );
         if( ( nChilds = hb_arrayLen( aChilds ) ) != 0 )
            {
            if( XA_ObjGetL( oItem, "lExpanded" ) )
               {
               int nChildIndent = XA_ObjGetNL( oItem, "nChildIndent" );

               *nLeft += nIndent + nChildIndent;
               nItem = _HitTest( x, y, aChilds, hdc, nLeft, nTop, nRight, nLine, oHitItem, imgSize, nItemHeight, lFullWidth );
               *nLeft -= nIndent + nChildIndent;
               }
            else
               *nLine += nChilds;
            }
         hb_itemRelease( aChilds );
         }

      XA_FreeCBuf( cText );
      hb_itemRelease( oItem );
      }

   return( nItem );
}

//--------------------------------------------------------------------------

static int HitTest( PHB_ITEM Self, HWND hWnd, int x, int y, PHB_ITEM oHitItem, BOOL lFullWidth )
{
   HDC hdc = GetDC( hWnd );
   PHB_ITEM aItems = XA_ObjGetItemCopy( Self, "aItems" );
   HFONT hFont = (HFONT) GetHandleOf( XA_ObjGetItem( Self, "oFont" ) );
   HFONT hOldFont = SelectObject( hdc, hFont );
   HANDLE hIL = GetHandleOf( XA_ObjGetItem( Self, "oImageList" ) );
   int nItemHeight = XA_ObjGetNL( Self, "nItemHeight" );
   int nLeft = XA_ObjGetNL( Self, "nLeftMargin" ), nTop = XA_ObjGetNL( Self, "nClientTop" ) + XA_ObjGetNL( Self, "nTopMargin" );
   int nRight = XA_ObjGetNL( Self, "nClientWidth" ) - nLeft - 4;
   int nItem = 0, nLine = 1;
   SIZE imgSize = { 0, 16 };
   TEXTMETRIC tm;

   if( ( x >= nLeft ) && ( y >= nTop ) )
      {
      GetTextMetrics( hdc, &tm );
      if( tm.tmHeight > nItemHeight )
         nItemHeight = tm.tmHeight;

      if( hIL && ImageList_GetImageCount( hIL ) )
         ImageList_GetIconSize( hIL, (int *) &imgSize.cx, (int *) &imgSize.cy );
      nItem = _HitTest( x, y, aItems, hdc, &nLeft, &nTop, &nRight, &nLine, oHitItem, &imgSize, nItemHeight, lFullWidth );
      if( nItem < 0 )
         nItem = 0;
      }

   hb_itemRelease( aItems );

   SelectObject( hdc, hOldFont );

   ReleaseDC( hWnd, hdc );
   return( nItem );
}

//--------------------------------------------------------------------------

HB_FUNC_STATIC( XOPTIONLIST_HITTEST )
{
   PHB_ITEM Self = hb_stackSelfItem();

   hb_retnl( HitTest( Self, GetHandleOf( Self ), hb_parnl( 1 ), hb_parnl( 2 ), NULL, hb_parl( 3 ) ) );
}

//--------------------------------------------------------------------------

HB_FUNC_STATIC( XOPTIONLIST_WMLBUTTONDOWN )
{
   PHB_ITEM Self = hb_stackSelfItem();
   HWND hWnd = GetHandleOf( Self );
   WPARAM wParam = hb_parnl( 1 );
   LPARAM lParam = hb_parnl( 2 );
   int nType;
   PHB_ITEM oItem = hb_itemNew( NULL );

   XA_ObjSendNL2( XA_ObjGetItem( Self, "TStdControl" ), "WMLButtonDown", wParam, lParam );

   if( HitTest( Self, hWnd, LOWORD( lParam ), HIWORD( lParam ), oItem, XA_ObjGetNL( Self, "nHotStyle" ) != hsUNDERLINE ) )
      {
      nType = XA_ObjGetNL( oItem, "nType" );
      if( ( nType != otTEXT ) && ( nType != otSEPARATOR ) )
         XA_ObjSend( oItem, "Click" );
      }
   hb_itemRelease( oItem );

   hb_ret();
}

//--------------------------------------------------------------------------

HB_FUNC_STATIC( XOPTIONLIST_WMMOUSEMOVE )
{
   PHB_ITEM Self = hb_stackSelfItem();
   HWND hWnd = GetHandleOf( Self );
   WPARAM wParam = hb_parnl( 1 );
   LPARAM lParam = hb_parnl( 2 );
   int nItem, nType = otSEPARATOR;
   PHB_ITEM oItem = hb_itemNew( NULL );

   nItem = HitTest( Self, hWnd, LOWORD( lParam ), HIWORD( lParam ), oItem, XA_ObjGetNL( Self, "nHotStyle" ) != hsUNDERLINE );
   if( nItem )
      nType = XA_ObjGetNL( oItem, "nType" );

   if( nItem != XA_ObjGetNL( Self, "nHotItem" ) )
      {
      XA_ObjSendNL( Self, "_nHotItem", nItem );
      InvalidateRect( hWnd, NULL, FALSE );
      if( nItem && ( nType != otTEXT ) && ( nType != otSEPARATOR ) )
         {
         TRACKMOUSEEVENT tme;

         tme.cbSize = sizeof( TRACKMOUSEEVENT );
         tme.dwFlags = TME_LEAVE;
         tme.hwndTrack = hWnd;
         TrackMouseEvent( &tme );

         CursorHand();
         }
      }
   if( ( nItem == 0 ) || ( nType == otTEXT ) || ( nType == otSEPARATOR ) )
      CursorArrow();
   hb_itemRelease( oItem );

   XA_ObjSendNL3( Self, "OnMouseMove", wParam, LOWORD( lParam ), HIWORD( lParam ) );

   hb_ret();
}

#pragma ENDDUMP

//--------------------------------------------------------------------------
