/*
 * Xailer source code:
 *
 * MonthCalendar.prg
 * Clase TMonthCalendar()
 *
 * Copyright 2003 Manuel Calero
 * Copyright 2003, 2007 Xailer.com
 * All rights reserved
 *
 */

#include "Xailer.ch"
#include "CommCtrl.api"


//--------------------------------------------------------------------------

CLASS XMonthCalendar FROM TStdControl

PUBLISHED:
   PROPERTY nWidth         INIT 200
   PROPERTY nHeight        INIT 158
   PROPERTY lBorder        INIT .T.

   PROPERTY dValue         INIT Date() READ METHOD GetCurSel WRITE METHOD SetCurSel
   PROPERTY dToday         INIT Date() READ METHOD GetToday WRITE METHOD SetToday

   PROPERTY dMinDate       INIT CToD( "" )   WRITE INLINE IIf( ! ::FlMultiSelect, ::SetRange( Value, ::dMaxDate ), ::SetSelRange( Value, ::dMaxDate ) )
   PROPERTY dMaxDate       INIT CToD( "" )   WRITE INLINE IIf( ! ::FlMultiSelect, ::SetRange( ::dMinDate, Value ), ::SetSelRange( ::dMinDate, Value ) )

   PROPERTY lMultiSelect   INIT .F.    WRITE METHOD SetMultiSelect
   PROPERTY lNoToday       INIT .F.    WRITE METHOD SetNoToday
   PROPERTY lNoTodayCircle INIT .F.    WRITE METHOD SetNoTodayCircle
   PROPERTY lWeekNumbers   INIT .F.    WRITE METHOD SetWeekNumbers

   PROPERTY nMaxSelCount   INIT 7      WRITE SetMaxSelCount

   PROPERTY nClrText          INIT clWindowText    WRITE SetTextColor            EDITOR PE_Color
   PROPERTY nClrPane          INIT clWindow        WRITE SetBackgroundColor      EDITOR PE_Color
   PROPERTY nClrMonthPane     INIT clWindow        WRITE SetMonthBackgroundColor EDITOR PE_Color
   PROPERTY nClrTitlePane     INIT clActiveCaption WRITE SetTitleBackgroundColor EDITOR PE_Color
   PROPERTY nClrTitleText     INIT clCaptionText   WRITE SetTitleTextColor       EDITOR PE_Color
   PROPERTY nClrTrailingText  INIT clBtnShadow     WRITE SetTrailingTextColor    EDITOR PE_Color

   EVENT OnChange( oSender, dDate ) // --> Nil
   EVENT OnSelect( oSender, dFirst, dLast ) // --> Nil

PROTECTED:
   DATA cWinClassName INIT MONTHCAL_CLASS
   DATA nCtlStyle     INIT nOr( WS_CHILD, WS_CLIPCHILDREN, WS_CLIPSIBLINGS, MCS_DAYSTATE )

PUBLIC:
   PROPERTY aHolidays   INIT {}  WRITE METHOD SetHolidays
   PROPERTY cText
   PROPERTY lDragAcceptFiles  INIT .F.

   METHOD Create( oParent ) CONSTRUCTOR

RESERVED:
   METHOD GetCurSel()
   METHOD SetCurSel( dValue )

   METHOD Change()

   METHOD SetHolidays()

   METHOD GetToday()
   METHOD SetToday( dValue )
   METHOD Reset()                   INLINE ::SetToday( Nil )

   METHOD GetMaxSelCount()          INLINE ::SendMsg( MCM_GETMAXSELCOUNT, 0, 0 )
   METHOD SetMaxSelCount( Value )   INLINE ::FnMaxSelCount := Value, ::SendMsg( MCM_SETMAXSELCOUNT, Value, 0 )

   METHOD SetMonthDelta( Value )    INLINE ::SendMsg( MCM_SETMONTHDELTA, Value, 0 )
   METHOD GetMonthDelta()           INLINE ::SendMsg( MCM_GETMONTHDELTA, 0, 0 )

   METHOD SetMultiSelect( lMultiSelect )
   METHOD SetNoToday( lNoToday )
   METHOD SetNoTodayCircle( lNoTodayCircle )
   METHOD SetWeekNumbers( lWeekNumbers )

   METHOD GetFirstDayOfWeek()          INLINE LoWord( ::SendMsg( MCM_GETFIRSTDAYOFWEEK, 0, 0 ) )
   METHOD SetFirstDayOfWeek( nDay )  ;
      INLINE ( nDay := IIf( nDay != Nil, nDay, -1 ), ;
               ::SendMsg( MCM_SETFIRSTDAYOFWEEK, 0, nDay ) )

   METHOD GetMaxTodayWidth()        INLINE ::SendMsg( MCM_GETMAXTODAYWIDTH, 0, 0 )
   METHOD GetMinReqRect()
   METHOD GetMonthRange( Value, nFlags )
   METHOD GetRange()
   METHOD SetRange( dMin, dMax )

   METHOD GetSelRange()
   METHOD SetSelRange( dMin, dMax )

   //METHOD GetUnicodeFormat()           INLINE ::SendMsg( MCM_GETUNICODEFORMAT, 0, 0 )
   //METHOD SetUnicodeFormat( lUnicode ) INLINE ::SendMsg( MCM_SETUNICODEFORMAT, lUnicode, 0 )

   METHOD HitTest( x, y )

   METHOD SetBackgroundColor( nColor )       INLINE ::FnClrPane         := nColor, ::SendMsg( MCM_SETCOLOR, MCSC_BACKGROUND, nColor )
   METHOD SetMonthBackgroundColor( nColor )  INLINE ::FnClrMonthPane    := nColor, ::SendMsg( MCM_SETCOLOR, MCSC_MONTHBK, nColor )
   METHOD SetTextColor( nColor )             INLINE ::FnClrText         := nColor, ::SendMsg( MCM_SETCOLOR, MCSC_TEXT, nColor )
   METHOD SetTitleBackgroundColor( nColor )  INLINE ::FnClrTitlePane    := nColor, ::SendMsg( MCM_SETCOLOR, MCSC_TITLEBK, nColor )
   METHOD SetTitleTextColor( nColor )        INLINE ::FnClrTitleText    := nColor, ::SendMsg( MCM_SETCOLOR, MCSC_TITLETEXT, nColor )
   METHOD SetTrailingTextColor( nColor )     INLINE ::FnClrTrailingText := nColor, ::SendMsg( MCM_SETCOLOR, MCSC_TRAILINGTEXT, nColor )

   METHOD Notify()
   METHOD WMXailer()
   METHOD WMEraseBkgnd()   INLINE 1
   METHOD WMPaint()        EXTERN XControl_EraseAndPaint()
   METHOD WMPrintClient()  VIRTUAL

ENDCLASS

//--------------------------------------------------------------------------

METHOD Create( oParent ) CLASS XMonthCalendar

   InitCommonControls( ICC_DATE_CLASSES )

   ::SetMultiSelect()
   ::SetNoToday()
   ::SetNoTodayCircle()
   ::SetWeekNumbers()

   ::Super:Create( oParent )

   AllowDblClk( ::Handle )

   ::SetMaxSelCount( ::FnMaxSelCount )
   ::SetToday( ::FdToday )
   ::SetCurSel( ::FdValue )

   IF ::FnClrPane == Nil
      ::FnClrPane := ::SendMsg( MCM_GETCOLOR, MCSC_BACKGROUND, 0 )
   ELSE
      ::SetBackgroundColor( ::FnClrPane )
   ENDIF

   IF ::FnClrMonthPane == Nil
      ::FnClrMonthPane := ::SendMsg( MCM_GETCOLOR, MCSC_MONTHBK, 0 )
   ELSE
      ::SetMonthBackgroundColor( ::FnClrMonthPane )
   ENDIF

   IF ::FnClrText == Nil
      ::FnClrText := ::SendMsg( MCM_GETCOLOR, MCSC_TEXT, 0 )
   ELSE
      ::SetTextColor( ::FnClrText )
   ENDIF

   IF ::FnClrTitlePane == Nil
      ::FnClrTitlePane := ::SendMsg( MCM_GETCOLOR, MCSC_TITLEBK, 0 )
   ELSE
      ::SetTitleBackgroundColor( ::FnClrTitlePane )
   ENDIF

   IF ::FnClrTitleText == Nil
      ::FnClrTitleText := ::SendMsg( MCM_GETCOLOR, MCSC_TITLETEXT, 0 )
   ELSE
      ::SetTitleTextColor( ::FnClrTitleText )
   ENDIF

   IF ::FnClrTrailingText == Nil
      ::FnClrTrailingText := ::SendMsg( MCM_GETCOLOR, MCSC_TRAILINGTEXT, 0 )
   ELSE
      ::SetTrailingTextColor( ::FnClrTrailingText )
   ENDIF

RETURN Self

//--------------------------------------------------------------------------

METHOD Change( dValue ) CLASS XMonthCalendar

   IF ::Fdvalue != dValue
      ::Fdvalue := dValue
      ::OnChange( dValue )
   ENDIF

RETURN Nil

//--------------------------------------------------------------------------

METHOD SetMultiSelect( lMultiSelect ) CLASS XMonthCalendar

   DEFAULT lMultiSelect TO ::FlMultiSelect

   ::FlMultiSelect   := lMultiSelect
   ::ChangeCtlStyle( MCS_MULTISELECT, lMultiSelect )

RETURN ( ::FlMultiSelect )

//--------------------------------------------------------------------------

METHOD SetNoToday( lNoToday ) CLASS XMonthCalendar

   DEFAULT lNoToday  TO ::FlNoToday

   ::FlNoToday       := lNoToday
   ::ChangeCtlStyle( MCS_NOTODAY, lNoToday )

RETURN ( ::FlNoToday )

//--------------------------------------------------------------------------

METHOD SetNoTodayCircle( lNoTodayCircle ) CLASS XMonthCalendar

   DEFAULT lNoTodayCircle  TO ::FlNoTodayCircle

   ::FlNoTodayCircle := lNoTodayCircle
   ::ChangeCtlStyle( MCS_NOTODAYCIRCLE, lNoTodayCircle )

RETURN ( ::FlNoTodayCircle )

//--------------------------------------------------------------------------

METHOD SetWeekNumbers( lWeekNumbers ) CLASS XMonthCalendar

   DEFAULT lWeekNumbers    TO ::FlWeekNumbers

   ::FlWeekNumbers   := lWeekNumbers
   ::ChangeCtlStyle( MCS_WEEKNUMBERS, lWeekNumbers )

RETURN ( ::FlWeekNumbers )

//--------------------------------------------------------------------------

#pragma BEGINDUMP

#define _WIN32_IE 0x0400

#include <windows.h>
#include <commctrl.h>
#include <xailer.h>

/* NOTA: Haya un bug en MinGW 7.3 y esta constante tiene un valor incorrecto - [JFG] */
#undef MCN_GETDAYSTATE
#define MCN_GETDAYSTATE -747

#define WM_XAILER WM_USER + 1

//--------------------------------------------------------------------------

static void Holidays( int nYear, int nMonth, int nMonths, MONTHDAYSTATE *pDayState, PHB_ITEM aHolidays )
{
   int nStart = hb_dateEncode( nYear, nMonth, 1 );
   int nEnd, nDate, nLen = hb_arrayLen( aHolidays ), n, m;
   LONG *aMonths = hb_xgrab( sizeof( LONG ) * nMonths ), *pMonth = aMonths;
   char cDate[9];

   for( n = 1; n <= nMonths; n++ )
      {
      *pMonth++ = hb_dateEncode( nYear, nMonth, 1 );
      if( nMonth == 12 )
         {
         nYear++;
         nMonth = 1;
         }
      else
         nMonth++;
      }
   nEnd = hb_dateEncode( nYear, nMonth, 1 ) - 1;

   memset( pDayState, 0, sizeof( MONTHDAYSTATE ) * nMonths );
   for( n = 1; n <= nLen; n++ )
      {
      nDate = hb_arrayGetDL( aHolidays, n );
      if( ( nDate >= nStart ) && ( nDate <= nEnd ) )
         {
         m = 1;
         while( ( m < nMonths ) && ( nDate >= aMonths[ m ] ) )
            m++;
         m--;
         pDayState[ m ] |= ( 1 << ( nDate - aMonths[ m ] ) );
         hb_dateDecStr( cDate, nDate );
         }
      }

   hb_xfree( aMonths );
}

//------------------------------------------------------------------------------

HB_FUNC_STATIC( XMONTHCALENDAR_NOTIFY )
{
   PHB_ITEM Self = hb_stackSelfItem();
   LPNMSELCHANGE nmsc = (LPNMSELCHANGE) hb_parnl( 2 );
   UINT uiCode = nmsc->nmhdr.code;

   switch( uiCode )
   {
      case MCN_SELCHANGE:
         // NOTA: En Windows XP, si se llama a MessageBox antes de retornar del evento, se queda pillado cuando el
         // usuario usa los botones para cambiar de mes. Por eso, hay que diferir el evento usando un WM_XAILER - [JFG]
         {
         LPNMSELCHANGE nm = hb_xgrab( sizeof( NMSELCHANGE ) );

         memcpy( nm, nmsc, sizeof( NMSELCHANGE ) );
         PostMessage( GetHandleOf( Self ), WM_XAILER, 0, (LPARAM) nm );
         break;
         }

      case MCN_SELECT:
         {
            PHB_ITEM pStart = hb_itemPutD( NULL, nmsc->stSelStart.wYear, nmsc->stSelStart.wMonth, nmsc->stSelStart.wDay );
            PHB_ITEM pEnd = hb_itemPutD( NULL, nmsc->stSelEnd.wYear, nmsc->stSelEnd.wMonth, nmsc->stSelEnd.wDay );

            XA_ObjSendItem2( Self, "OnSelect", pStart, pEnd );

            hb_itemRelease( pStart );
            hb_itemRelease( pEnd );
         }
         break;

      case MCN_GETDAYSTATE:
         {
            LPNMDAYSTATE nmds = (LPNMDAYSTATE) nmsc;
            PHB_ITEM aHolidays = XA_ObjGetItemCopy( Self, "aHolidays" );

            Holidays( nmds->stStart.wYear, nmds->stStart.wMonth, nmds->cDayState, nmds->prgDayState, aHolidays );
            hb_itemRelease( aHolidays );
         }
         break;
   }
   hb_ret();
}

//------------------------------------------------------------------------------

HB_FUNC_STATIC( XMONTHCALENDAR_WMXAILER )
{
   PHB_ITEM Self = hb_stackSelfItem();
   LPNMSELCHANGE nmsc = (LPNMSELCHANGE) hb_parnl( 2 );

   if( nmsc->nmhdr.code )
      {
      PHB_ITEM pDate = hb_itemPutD( NULL, nmsc->stSelStart.wYear, nmsc->stSelStart.wMonth, nmsc->stSelStart.wDay );

      XA_ObjSendItem( Self, "Change", pDate );
      hb_itemRelease( pDate );
      hb_xfree( nmsc );
      }

   hb_ret();
}

//--------------------------------------------------------------------------

HB_FUNC_STATIC( XMONTHCALENDAR_SETHOLIDAYS )
{
   PHB_ITEM Self = hb_stackSelfItem();
   HWND hWnd = GetHandleOf( Self );
   PHB_ITEM aHolidays = hb_param( 1, HB_IT_ARRAY );
   SYSTEMTIME aSysTime[ 2 ];
   MONTHDAYSTATE *pDayState;
   int nMonths;

   XA_ObjSendItem( Self, "_FaHolidays", aHolidays );
   if( hWnd )
      {
      nMonths = SendMessage( hWnd, MCM_GETMONTHRANGE, GMR_DAYSTATE, (LPARAM) aSysTime );
      pDayState = hb_xgrab( sizeof( MONTHDAYSTATE ) * nMonths );
      Holidays( aSysTime[0].wYear, aSysTime[0].wMonth, nMonths, pDayState, aHolidays );
      SendMessage( hWnd, MCM_SETDAYSTATE, nMonths, (LPARAM) pDayState );
      hb_xfree( pDayState );
      }
}

//--------------------------------------------------------------------------

HB_FUNC_STATIC( XMONTHCALENDAR_GETTODAY )
{
   PHB_ITEM Self = hb_stackSelfItem();
   HWND hwnd = GetHandleOf( Self );
   SYSTEMTIME st;
   PHB_ITEM pDate;

   SendMessage( hwnd, MCM_GETTODAY, 0, (LPARAM) &st );

   pDate = hb_itemPutD( NULL, st.wYear, st.wMonth, st.wDay );
   XA_ObjSendItem( Self, "_FdToday", pDate );
   hb_itemRelease( pDate );

   hb_retd( st.wYear, st.wMonth, st.wDay);
}

//--------------------------------------------------------------------------

HB_FUNC_STATIC( XMONTHCALENDAR_GETCURSEL )
{
   PHB_ITEM Self = hb_stackSelfItem();
   HWND hwnd = GetHandleOf( Self );
   SYSTEMTIME st = { 0, 0, 0, 0, 0, 0, 0, 0 };
   PHB_ITEM pDate;

   SendMessage( hwnd, MCM_GETCURSEL, 0, (LPARAM) &st );

   pDate = hb_itemPutD( NULL, st.wYear, st.wMonth, st.wDay );
   XA_ObjSendItem( Self, "_FdValue", pDate );
   hb_itemRelease( pDate );

   hb_retd( st.wYear, st.wMonth, st.wDay );
}

//--------------------------------------------------------------------------

HB_FUNC_STATIC( XMONTHCALENDAR_GETMINREQRECT )
{
   PHB_ITEM Self = hb_stackSelfItem();
   HWND hwnd = GetHandleOf( Self );
   RECT rect = { 0, 0, 0, 0 };

   SendMessage( hwnd, MCM_GETMINREQRECT, 0, (LPARAM) &rect );

   hb_reta( 4 );
   hb_storvnl( rect.left, -1, 1 );
   hb_storvnl( rect.top, -1, 2 );
   hb_storvnl( rect.bottom, -1, 3 );
   hb_storvnl( rect.right, -1, 4 );
}

//--------------------------------------------------------------------------

HB_FUNC_STATIC( XMONTHCALENDAR_SETTODAY )
{
   PHB_ITEM Self = hb_stackSelfItem();
   HWND hwnd = GetHandleOf( Self );
   SYSTEMTIME st;
   PHB_ITEM pDate = hb_param( 1, HB_IT_DATE );

   if( pDate )
   {
      int lYear, lMonth, lDay;

      XA_ObjSendItem( Self, "_FdToday", pDate );
      hb_dateDecode( hb_itemGetDL( pDate ), &lYear, &lMonth, &lDay );

      st.wYear          = lYear;
      st.wMonth         = lMonth;
      st.wDay           = lDay;
      st.wDayOfWeek     = 0;

      st.wHour          = 0;
      st.wMinute        = 0;
      st.wSecond        = 0;
      st.wMilliseconds  = 0;

      SendMessage( hwnd, MCM_SETTODAY, 0, (LPARAM) &st);
   }
   else
      SendMessage( hwnd, MCM_SETTODAY, 0, 0 );

   hb_ret();
}

//--------------------------------------------------------------------------

HB_FUNC_STATIC( XMONTHCALENDAR_SETCURSEL )
{
   PHB_ITEM Self = hb_stackSelfItem();
   HWND hwnd = GetHandleOf( Self );
   SYSTEMTIME st;
   PHB_ITEM pDate = hb_param( 1, HB_IT_DATE );

   if( pDate )
   {
      int lYear, lMonth, lDay;

      XA_ObjSendItem( Self, "_FdValue", pDate );
      hb_dateDecode( hb_itemGetDL( pDate ), &lYear, &lMonth, &lDay );

      st.wYear          = lYear;
      st.wMonth         = lMonth;
      st.wDay           = lDay;
      st.wDayOfWeek     = 0;

      st.wHour          = 0;
      st.wMinute        = 0;
      st.wSecond        = 0;
      st.wMilliseconds  = 0;

      hb_retl( SendMessage( hwnd, MCM_SETCURSEL, 0, (LPARAM) &st) );
   }

   hb_retl( FALSE );
}

//--------------------------------------------------------------------------

HB_FUNC_STATIC( XMONTHCALENDAR_GETMONTHRANGE )
{
   PHB_ITEM Self = hb_stackSelfItem();
   HWND hwnd = GetHandleOf( Self );
   SYSTEMTIME st[ 2 ];
   DWORD dwFlags = HB_ISNUM( 2 ) ? hb_parnl( 2 ) : GMR_DAYSTATE; //GMR_VISIBLE
   PHB_ITEM pArray = hb_itemArrayNew( 2 );
   PHB_ITEM pDate;

   SendMessage( hwnd, MCM_GETMONTHRANGE, dwFlags, (LPARAM) &st );

   pDate = hb_itemPutD( NULL, st[0].wYear, st[0].wMonth, st[0].wDay );
   hb_itemArrayPut( pArray, 1, pDate );
   hb_itemRelease( pDate );

   pDate = hb_itemPutD( NULL, st[1].wYear, st[1].wMonth, st[1].wDay );
   hb_itemArrayPut( pArray, 2, pDate );
   hb_itemRelease( pDate );

   hb_itemReturnForward( pArray );
   hb_itemRelease( pArray );
}

//--------------------------------------------------------------------------

HB_FUNC_STATIC( XMONTHCALENDAR_GETRANGE )
{
   PHB_ITEM Self = hb_stackSelfItem();
   HWND hwnd = GetHandleOf( Self );
   SYSTEMTIME st[ 2 ];
   DWORD dwFlags;
   PHB_ITEM pArray = hb_itemArrayNew( 2 );
   PHB_ITEM pDate;

   dwFlags = SendMessage( hwnd, MCM_GETRANGE, 0, (LPARAM) &st );

   if( dwFlags & GDTR_MIN )
      pDate = hb_itemPutD( NULL, st[0].wYear, st[0].wMonth, st[0].wDay );
   else
      pDate = hb_itemPutD( NULL, 0, 0, 0 );

   hb_itemArrayPut( pArray, 1, pDate );
   hb_itemRelease( pDate );

   if( dwFlags & GDTR_MAX )
      pDate = hb_itemPutD( NULL, st[1].wYear, st[1].wMonth, st[1].wDay );
   else
      pDate = hb_itemPutD( NULL, 0, 0, 0 );

   hb_itemArrayPut( pArray, 2, pDate );
   hb_itemRelease( pDate );

   hb_itemReturnForward( pArray );
   hb_itemRelease( pArray );

}

//--------------------------------------------------------------------------

HB_FUNC_STATIC( XMONTHCALENDAR_SETRANGE )
{
   PHB_ITEM Self = hb_stackSelfItem();
   HWND hwnd = GetHandleOf( Self );
   SYSTEMTIME st[ 2 ];
   PHB_ITEM pDateMax = hb_param( 1, HB_IT_DATE );
   PHB_ITEM pDateMin = hb_param( 2, HB_IT_DATE );

   if( pDateMin && pDateMax )
   {
      int lYear, lMonth, lDay;
      BOOL bSuccess;

      XA_ObjSendItem( Self, "_FdMinDate", pDateMin );
      hb_dateDecode( hb_itemGetDL( pDateMin ), &lYear, &lMonth, &lDay );

      st[0].wYear          = lYear;
      st[0].wMonth         = lMonth;
      st[0].wDay           = lDay;
      st[0].wDayOfWeek     = 0;

      st[0].wHour          = 0;
      st[0].wMinute        = 0;
      st[0].wSecond        = 0;
      st[0].wMilliseconds  = 0;

      XA_ObjSendItem( Self, "_FdMaxDate", pDateMax );
      hb_dateDecode( hb_itemGetDL( pDateMax ), &lYear, &lMonth, &lDay );

      st[1].wYear          = lYear;
      st[1].wMonth         = lMonth;
      st[1].wDay           = lDay;
      st[1].wDayOfWeek     = 0;

      st[1].wHour          = 0;
      st[1].wMinute        = 0;
      st[1].wSecond        = 0;
      st[1].wMilliseconds  = 0;

      bSuccess = SendMessage( hwnd, MCM_SETRANGE, GDTR_MIN, (LPARAM) &st[0] );
      bSuccess &= SendMessage( hwnd, MCM_SETRANGE, GDTR_MAX, (LPARAM) &st[1] );
      hb_retl( bSuccess );
   }
   hb_retl( FALSE );
}

//--------------------------------------------------------------------------

HB_FUNC_STATIC( XMONTHCALENDAR_SETSELRANGE )
{
   PHB_ITEM Self = hb_stackSelfItem();
   HWND hwnd = GetHandleOf( Self );
   SYSTEMTIME st[ 2 ];
   PHB_ITEM pDateMin = hb_param( 1, HB_IT_DATE );
   PHB_ITEM pDateMax = hb_param( 2, HB_IT_DATE );

   if( pDateMin && pDateMax )
   {
      int lYear, lMonth, lDay;

      XA_ObjSendItem( Self, "_FdMinDate", pDateMin );
      hb_dateDecode( hb_itemGetDL( pDateMin ), &lYear, &lMonth, &lDay );

      st[0].wYear          = lYear;
      st[0].wMonth         = lMonth;
      st[0].wDay           = lDay;
      st[0].wDayOfWeek     = 0;

      st[0].wHour          = 0;
      st[0].wMinute        = 0;
      st[0].wSecond        = 0;
      st[0].wMilliseconds  = 0;

      XA_ObjSendItem( Self, "_FdMaxDate", pDateMax );
      hb_dateDecode( hb_itemGetDL( pDateMax ), &lYear, &lMonth, &lDay );

      st[1].wYear          = lYear;
      st[1].wMonth         = lMonth;
      st[1].wDay           = lDay;
      st[1].wDayOfWeek     = 0;

      st[1].wHour          = 0;
      st[1].wMinute        = 0;
      st[1].wSecond        = 0;
      st[1].wMilliseconds  = 0;

      hb_retl( SendMessage( hwnd, MCM_SETSELRANGE, 0, (LPARAM) &st ) );
   }
   hb_retl( FALSE );
}

//--------------------------------------------------------------------------

HB_FUNC_STATIC( XMONTHCALENDAR_GETSELRANGE )
{
   PHB_ITEM Self = hb_stackSelfItem();
   HWND hwnd = GetHandleOf( Self );
   SYSTEMTIME st[ 2 ];
   DWORD dwFlags;
   PHB_ITEM pArray = hb_itemArrayNew( 2 );
   PHB_ITEM pDate;

   dwFlags = SendMessage( hwnd, MCM_GETSELRANGE, 0, (LPARAM) &st );

   if( dwFlags & GDTR_MIN )
      pDate = hb_itemPutD( NULL, st[0].wYear, st[0].wMonth, st[0].wDay );
   else
      pDate = hb_itemPutD( NULL, 0, 0, 0 );

   XA_ObjSendItem( Self, "_FdMinDate", pDate );
   hb_itemArrayPut( pArray, 1, pDate );
   hb_itemRelease( pDate );

   if( dwFlags & GDTR_MAX )
      pDate = hb_itemPutD( NULL, st[1].wYear, st[1].wMonth, st[1].wDay );
   else
      pDate = hb_itemPutD( NULL, 0, 0, 0 );

   XA_ObjSendItem( Self, "_FdMaxDate", pDate );
   hb_itemArrayPut( pArray, 2, pDate );
   hb_itemRelease( pDate );

   hb_itemReturnForward( pArray );
   hb_itemRelease( pArray );
}

//--------------------------------------------------------------------------

HB_FUNC_STATIC( XMONTHCALENDAR_HITTEST )
{
   PHB_ITEM Self = hb_stackSelfItem();
   HWND hwnd = GetHandleOf( Self );
   MCHITTESTINFO mchti;

   mchti.cbSize = sizeof( MCHITTESTINFO );
   mchti.pt.x = hb_parnl( 1 );
   mchti.pt.y = hb_parnl( 2 );

   hb_retnl( SendMessage( hwnd, MCM_HITTEST, 0, (LPARAM) &mchti ) );
}

//--------------------------------------------------------------------------

HB_FUNC_STATIC( ALLOWDBLCLK )
{
   HWND hWnd = ( HWND ) hb_parnl( 1 );

   SetClassLong( hWnd, GCL_STYLE, GetClassLong( hWnd, GCL_STYLE ) | CS_DBLCLKS );
   hb_ret();
}

#pragma ENDDUMP

//--------------------------------------------------------------------------
