Page 1 of 2

About TCalendar

Posted: Mon Dec 07, 2020 10:07 am
by AntoninoP
Hello, In our program we ask for a range di date, using 2 DatePicker, I would like change it using the Month Calendar Control
that is supported by FiveWin by the TCalendar class.
What I saw, trying the testcal sample is the some animations are missing, I fixed it adding these pieces of code on the sample (and on every use)

Code: Select all

   // my fix
   __objDelMethod(oCal, "HandleEvent" )
   __objAddMethod(oCal, "HandleEvent", @simplyNil())
   __objDelMethod(oCal2, "HandleEvent" )
   __objAddMethod(oCal2, "HandleEvent", @simplyNil())
   // *** ***
and

Code: Select all

static function simplyNil()
return nil
another way is overriding HandleEvent in TCalendar, of course.
Here a couple of video with the missing animations :https://imgur.com/a/vA0lNfn

Another piece that is missing is the query for size of the control, that I would implement in this way:

Code: Select all

//----------------------------------------------------------------------------//

HB_FUNC( MONTHCAL_GETMINREQRECT )     //  hWnd  -->  { nTop, nLeft, nBottom, nRight }
{
   HWND hWnd = ( HWND ) fw_parH( 1 );
   RECT rct;

   rct.top    = 0;
   rct.left   = 0;
   rct.bottom = 0;
   rct.right  = 0;

   if( hWnd )
      MonthCal_GetMinReqRect( hWnd, &rct );

   hb_reta( 4 );

   hb_storvni( rct.top,    -1, 1 );
   hb_storvni( rct.left,   -1, 2 );
   hb_storvni( rct.bottom, -1, 3 );
   hb_storvni( rct.right,  -1, 4 );
}

//----------------------------------------------------------------------------//

HB_FUNC( MONTHCAL_SIZERECTTOMIN )     //  hWnd,{ nTop, nLeft, nBottom, nRight }  -->  { nTop, nLeft, nBottom, nRight }
{
   HWND hWnd = ( HWND ) fw_parH( 1 );
   RECT rct;

   rct.top    = hb_parvni( 2, 1 );
   rct.left   = hb_parvni( 2, 2 );
   rct.bottom = hb_parvni( 2, 3 );
   rct.right  = hb_parvni( 2, 4 );

   if( hWnd )
      MonthCal_SizeRectToMin( hWnd, &rct );

   hb_reta( 4 );

   hb_storvni( rct.top,    -1, 1 );
   hb_storvni( rct.left,   -1, 2 );
   hb_storvni( rct.bottom, -1, 3 );
   hb_storvni( rct.right,  -1, 4 );
}

//----------------------------------------------------------------------------//
From MSDN:

MonthCal_GetMinReqRect
Retrieves the minimum size required to display a full month in a month calendar control. Size information is presented in the form of a RECT structure.

MonthCal_SizeRectToMin
Calculates how many calendars will fit in the given rectangle, and then returns the minimum size that a rectangle needs to be to fit that number of calendars.

Re: About TCalendar

Posted: Wed Dec 09, 2020 1:12 pm
by AntoninoP
another problem:

Code: Select all

METHOD Change() CLASS TCalendar

   static dOldDate

   if ::bChange != nil .and. dOldDate != ::GetDate()
      Eval( ::bChange, Self )
      dOldDate = ::GetDate()
   endif

return NIL
In case of multiselect, if change only the Date end bChange is not called

Re: About TCalendar

Posted: Sun Dec 13, 2020 4:24 pm
by elvira
Hello Antonio,

I'm afraid the class has several unpolished aspects. If you post the complete source code we can help you with the testing.

Thank you!

Re: About TCalendar

Posted: Mon Dec 14, 2020 8:00 am
by AntoninoP
hello,
here a modifed version of testcal.prg from sample folder

Code: Select all

#include "FiveWin.ch"
#include "dtpicker.ch"
#include "calendar.ch"
#include "wcolors.ch"

FUNCTION Main()
   LOCAL oWnd, oCal, oDtp1, oDtp2, oDtp3, oDtp4, oCbx
   LOCAL oSayClr
   LOCAL nColor
   LOCAL dDate1, dDate2, dDate3, dDate4, dDate5, dDate6
   LOCAL cItemClr
   LOCAL lWeekNumbers   := .F.
   LOCAL lNoTodayCircle := .F.
   LOCAL lNoToday       := .F.
   LOCAL lDayState      := .F.
   LOCAL oRange3, aRanges2 := { , }
   LOCAL oRange4
   LOCAL aColorItems    := { "MCSC_BACKGROUND  " ,;
                             "MCSC_TEXT        " ,;
                             "MCSC_TITLEBK     " ,;
                             "MCSC_TITLETEXT   " ,;
                             "MCSC_MONTHBK     " ,;
                             "MCSC_TRAILINGTEXT" }
   LOCAL oDayOfWeek, cDayOfWeek:="Monday", aDayOfWeek:={"Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday"}

   LOCAL oCal2
   LOCAL oRange1, aRanges := { , }
   LOCAL oRange2
   LOCAL oMax, nMax
   LOCAL lSunday   := .T.
   LOCAL lSaturday := .T.



     SET DATE TO BRITISH
     SET EPOCH TO 1980
   dDate1 = Date()
   dDate2 = Date()
   dDate3 = Date()
   dDate4 = Date() + 7
   dDate5 = Date()
   dDate6 = Date()

   DEFINE WINDOW oWnd TITLE "Test Calendar" FROM 0, 0 TO 600, 600 PIXEL

   // Start Calendar 1


  @ 001, 205 CALENDAR oCal VAR dDate1 OF oWnd PIXEL;
              DBLCLICK MsgInfo( oCal:GetDate() );
              ON CHANGE oDtp2:cText := oCal:GetDate() SIZE 200, 170;
              ACTION( MsgInfo( "ok" ) );
              WEEKNUMBER

   @ 001, 001 BUTTON "Get Today" OF oWnd PIXEL SIZE 100, 020 ACTION oDtp1:cText := oCal:GetToday()
   @ 025, 001 BUTTON "Set Today" OF oWnd PIXEL SIZE 100, 020 ACTION oCal:SetToday( dDate1 )
   @ 012, 105 DTPICKER oDtp1 VAR dDate1 OF oWnd PIXEL
   @ 050, 001 BUTTON "Get Color" OF oWnd PIXEL SIZE 100, 020 ACTION( oSayClr:SetColor( CLR_BLACK, oCal:GetColors( oCbx:nAt - 1 ) ), oSayClr:Refresh() )
   @ 050, 105 BUTTON "Set Color" OF oWnd PIXEL SIZE 100, 020 ACTION( nColor := ChooseColor(), ;
                                                                     oCal:SetColor( oCbx:nAt - 1, nColor ), ;
                                                                     oSayClr:SetColor( CLR_BLACK, nColor ),;
                                                                     oSayClr:Refresh() )

   @ 075, 001 COMBOBOX oCbx VAR cItemClr PROMPTS aColorItems PIXEL SIZE 205, 200 OF oWnd
   @ 100, 001 SAY oSayClr VAR "        " PIXEL SIZE 100, 020 OF oWnd BORDER

   @ 125, 001 BUTTON "Get 1 Day Week" OF oWnd SIZE 100, 20 PIXEL ACTION( cDayofWeek := aDayOfWeek[ oCal:GetFirstDayOfWeek() + 1 ], oDayOfWeek:Refresh() )
   @ 125, 105 BUTTON "Set 1 Day Week" OF oWnd SIZE 100, 20 PIXEL ACTION( oCal:SetFirstDayOfWeek( oDayOfWeek:FindString( cDayOfWeek ) - 1 ) )

   @ 150, 001 COMBOBOX oDayOfWeek VAR cDayofWeek ITEMS aDayOfWeek OF oWnd SIZE 205, 200 PIXEL

   @ 175, 001 BUTTON "Get Selected Day" OF oWnd PIXEL SIZE 100, 020 ACTION Msginfo( oCal:GetDate() )
   @ 200, 001 BUTTON "Set Selected Day" OF oWnd PIXEL SIZE 100, 020 ACTION oCal:SetDate( dDate2 )
   @ 186, 105 DTPICKER oDtp2 VAR dDate2 OF oWnd PIXEL

   @ 175, 210 BUTTON "Get Range" OF oWnd PIXEL SIZE 100, 020 ;
              ACTION( aRanges2 := oCal:GetRange(), oRange3:Refresh(), oRange4:Refresh() )
   @ 175, 310 GET oRange3 VAR aRanges2[ 1 ] OF oWnd SIZE 100, 20 PIXEL
   @ 175, 420 GET oRange4 VAR aRanges2[ 2 ] OF oWnd SIZE 100, 20 PIXEL

   @ 200, 210 BUTTON "Set Range" OF oWnd PIXEL SIZE 100, 020 ACTION oCal:SetRange( dDate5, dDate6 )
   @ 200, 315 DTPICKER oDtp3 VAR dDate5 OF oWnd PIXEL
   @ 200, 420 DTPICKER oDtp4 VAR dDate6 OF oWnd PIXEL

   @ 001, 410 CHECKBOX oCal:lWeekNumbers PROMPT "Week Numbers" OF oWnd SIZE 100, 20 PIXEL;
              ON CHANGE  oCal:SetWeekNumbers( oCal:lWeekNumbers )

   @ 025, 410 CHECKBOX oCal:lNoTodayCircle PROMPT "No Today Circle" OF oWnd SIZE 100, 20 PIXEL;
              ON CHANGE  oCal:SetNoTodayCircle( oCal:lNoTodayCircle )

   @ 050, 410 CHECKBOX oCal:lNoToday PROMPT "No Today" OF oWnd SIZE 100, 20 PIXEL;
              ON CHANGE  oCal:SetNoToday( oCal:lNoToday )

     oCal:bGotFocus  := {|| oCal:SetTitleBk( CLR_YELLOW ) }
     oCal:bLostFocus := {|| oCal:SetTitleBk( GetSysColor( COLOR_ACTIVECAPTION ) ) }

   // Start Calendar 2

   @ 250, 001 CALENDAR oCal2 VAR dDate3, dDate4 OF oWnd PIXEL MULTISELECT DAYSTATE;
              DBLCLICK MsgInfo( oCal2:GetDate() ) SIZE 550, 170 COLOR CLR_BLACK, CLR_HRED ;
              on change iif(empty(oCal2),,( aRanges := oCal2:GetDateRange(), oRange1:Refresh(), oRange2:Refresh() ))
   // I Added On Change
   @ 230, 001 SAY "MONTHS DISPLAYED: " + StrZero( ocal2:GetVisibleMonths(), 2 )  OF oWnd PIXEL COLOR CLR_WHITE, CLR_BLACK

   @ 430, 001 BUTTON "Get Selected Range" OF oWnd SIZE 100, 20 PIXEL ;
              ACTION( aRanges := oCal2:GetDateRange(), oRange1:Refresh(), oRange2:Refresh() )
   @ 430, 105 GET oRange1 VAR aRanges[ 1 ] OF oWnd SIZE 100, 20 PIXEL
   @ 430, 210 GET oRange2 VAR aRanges[ 2 ] OF oWnd SIZE 100, 20 PIXEL

     oCal2:bGotFocus  := {|| oCal2:SetTitleBk( CLR_YELLOW ) }
     oCal2:bLostFocus := {|| oCal2:SetTitleBk( CLR_HRED ) }

   nMax = oCal2:GetMaxSelCount()

   @ 455, 001 BUTTON "Set Max Selected Day" OF oWnd SIZE 150, 20 PIXEL ;
              ACTION( oCal2:SetMaxSelCount( nMax ) )

   @ 455, 155 GET oMax VAR nMax OF oWnd SIZE 50, 20 PIXEL SPINNER ;
              MIN 1 MAX 60

   @ 480, 001 CHECKBOX oCal2:lDayState PROMPT "Day State" OF oWnd SIZE 100, 20 PIXEL;
              ON CHANGE( oCal2:SetDayStateStyle( oCal2:lDayState ), ;
                        If( oCal2:lDayState, ( OnGetState( oCal2, lSunday, lSaturday ), oCal2:SetDayState() ), ) )

   @ 505, 001 CHECKBOX lSunday PROMPT "Bold Sunday" OF oWnd SIZE 100, 20 PIXEL

   @ 530, 001 CHECKBOX lSaturday PROMPT "Bold Saturday" OF oWnd SIZE 100, 20 PIXEL

    OnGetState( oCal2, lSunday, lSaturday )
    oCal2:SetDayState()
    oCal2:bOnGetState = { | oCal | OnGetState( oCal, lSunday, lSaturday ) }

   // my fixes
   __objDelMethod(oCal2, "HandleEvent" )
   __objAddMethod(oCal2, "HandleEvent", @simplyNil())
   __objDelMethod(oCal2, "Change" )
   __objAddMethod(oCal2, "Change", @TCal_Method_Change())
   // *** ***

   ACTIVATE WINDOW oWnd


RETURN NIL

static function simplyNil()
return nil

function TCal_Method_Change()
   local Self := QSelf(), aTmp
   static dOldDate, dOldDate2

   if ::bChange != nil
      Eval( ::bChange, Self )
      if ::lMultiselect
         aTmp := ::GetDateRange()
         if dOldDate != aTmp[1] .or. dOldDate2 != aTmp[2]
            Eval( ::bChange, Self )
            dOldDate := aTmp[1]
            dOldDate2 := aTmp[2]
         endif
      else
         if dOldDate != ::GetDate()
            Eval( ::bChange, Self )
            dOldDate = ::GetDate()
         endif
      endif
   endif

return NIL



Function OnGetState( oCal, lSun, lSat )
   LOCAL i, imax, j, jmax, nDay, nDayState, nMonth
   LOCAL dStartDate
   LOCAL dCurrentDay := oCal:dDate

   oCal:GetMonthRange()

   dStartDate = oCal:dDate

   imax   := Len( oCal:aDayState )
   nMonth := Month( dStartDate )


   FOR i:=1 TO imax
      nDayState := 0

      FOR j:=1 TO 31
         nDay := DoW( dStartDate ) - 2
         IF nDay < 0
            nDay += 7
         ENDIF

         IF nDay == 5 .AND. lSat
            oCal:SetArrayDayState( i, j )
         ENDIF

         IF nDay == 6 .AND. lSUN
            oCal:SetArrayDayState( i, j )
         ENDIF

         dStartDate ++

         IF Month( dStartDate ) <> nMonth
            EXIT
         ENDIF
      NEXT

      nMonth       := Month( dStartDate )
   NEXT

   oCal:SetDate( dCurrentDay )

return nil
Without the lines that overwrites HandleEvent andCheck we can see the bugs I already pointed out:
  • No animation clicking on mount title
  • No selection on click and drag on range mode
  • No change event changing only end date (it is visible very well if the previous one is fixed)
Regards

Re: About TCalendar

Posted: Mon Dec 14, 2020 11:41 am
by Antonio Linares
Antonino,

Many thanks for your feedback and help. It will be included in the next FWH build.

We have implemented it this way:

In class TCalendar:

METHOD HandleEvent() VIRTUAL

METHOD GetMinReqRect() INLINE MonthCal_GetMinReqRect( ::hWnd )

METHOD SizeRectToMin( aSize ) INLINE MonthCal_SizeRectToMin( ::hWnd, aSize )

Code: Select all

METHOD Change() CLASS TCalendar

   local aTmp
   
   static dOldDate, dOldDate2

   if ::bChange != nil
      Eval( ::bChange, Self )
      if ::lMultiselect
         aTmp = ::GetDateRange()
         if dOldDate != aTmp[ 1 ] .or. dOldDate2 != aTmp[ 2 ]
            Eval( ::bChange, Self )
            dOldDate  = aTmp[ 1 ]
            dOldDate2 = aTmp[ 2 ]
         endif
      else
         if dOldDate != ::GetDate()
            Eval( ::bChange, Self )
            dOldDate = ::GetDate()
         endif
      endif
   endif

return nil
 

Re: About TCalendar

Posted: Mon Dec 14, 2020 2:35 pm
by AntoninoP
ops, there is a bug, bChange is called 2 time by Change method, here the fix:

Code: Select all

METHOD Change() CLASS TCalendar

   local aTmp
   
   static dOldDate, dOldDate2

   if ::bChange != nil
      if ::lMultiselect
         aTmp = ::GetDateRange()
         if dOldDate != aTmp[ 1 ] .or. dOldDate2 != aTmp[ 2 ]
            Eval( ::bChange, Self )
            dOldDate  = aTmp[ 1 ]
            dOldDate2 = aTmp[ 2 ]
         endif
      else
         if dOldDate != ::GetDate()
            Eval( ::bChange, Self )
            dOldDate = ::GetDate()
         endif
      endif
   endif

return nil
It is a mistake of my code

Re: About TCalendar

Posted: Mon Dec 14, 2020 3:28 pm
by Antonio Linares
thanks! :-)

Re: About TCalendar

Posted: Wed Dec 23, 2020 1:08 pm
by AntoninoP
Hello,
I share my Last test, where added bViewChanged called when the view changes, SetCurrentView and GetCurrentView to set and get the current view. I tried to do a only month selection, but id does a little weird animation:

Code: Select all

#include <fivewin.ch>
#include <calendar.ch>

// MyCalendar
#define MCMV_MONTH      0
#define MCMV_YEAR       1
#define MCMV_DECADE     2
#define MCMV_CENTURY    3
#define MCMV_MAX        MCMV_CENTURY

// TEST CODE
proc main()
   LOCAL oDlg, oMonth, dData1 := Date(),dData2 := Date(), oMonth2, dMese := Date()
   DEFINE DIALOG oDlg SIZE 700,400 PIXEL TRUEPIXEL;
      TITLE "Test MonthCal"
   //@ 10,10 CALENDAR oMonth VAR dData1,dData2 PIXEL NOTADAY NOTODAYCIRCLE SIZE 500,20
   oMonth := MyCalendar():New( 10, 10, { | u | If( PCount()==0, dData1, dData1:= u ) }, { | u | If( PCount()==0, dData2, dData2:= u ) },, 500, 20,,,,, .F.,, .T.,, .F., .F.,,,,,, .F., .T., .T., .F. )
   // only month calendar test
   //@ 210,10 CALENDAR oMonth2 VAR dMese PIXEL NOTADAY NOTODAYCIRCLE SIZE 700,20
   oMonth2 := MyCalendar():New( 210, 10, { | u | If( PCount()==0, dMese, dMese:= u ) }, nil,, 700, 20,,,,, .F.,, .T.,, .F., .F.,,,,,, .F., .T., .T., .F. )
   oMonth2:bViewChanged := {|Self,nOld,nNew| iif(nNew<MCMV_YEAR,::SetCurrentView(MCMV_YEAR),) }
   ACTIVATE DIALOG oDlg CENTERED ON INIT (oMonth2:SetCurrentView(MCMV_YEAR))


// MyCalendar
#define SWP_NOSIZE        0x0001
#define SWP_NOMOVE        0x0002
#define SWP_NOZORDER      0x0004

#define MCN_VIEWCHANGE      (-750)

CLASS MyCalendar FROM TCalendar
   DATA bViewChanged

   METHOD New(...) CONSTRUCTOR

   METHOD HandleEvent( nMsg, nWParam, nLParam )
   METHOD Change()
   METHOD Notify( nIdCtrl, nPtrNMHDR )

   // use SetGet?
   METHOD Initiate( hDlg )
   METHOD SetCurrentView(id) INLINE MonthCal_SetCurrentView(::hWnd, id)
   METHOD GetCurrentView() INLINE MonthCal_GetCurrentView(::hWnd)

endclass

METHOD New(...) CLASS MyCalendar
   LOCAL rc
   ::Super:new(...)
   if !Empty( ::hWnd )
      rc := MonthCal_SizeRectToMin( ::hWnd, GetClientRect( ::hWnd ) )
      SetWindowPos(::hWnd, 0, 0, 0, rc[4], rc[3], nOr(SWP_NOZORDER, SWP_NOMOVE))
      ::CoorsUpdate()
   endif
return Self

METHOD Initiate( hDlg )  CLASS MyCalendar
   LOCAL rc
   ::Super:Initiate(hDlg)
   if !Empty( ::hWnd )
      rc := MonthCal_SizeRectToMin( ::hWnd, GetClientRect( ::hWnd ) )
      SetWindowPos(::hWnd, 0, 0, 0, rc[4], rc[3], nOr(SWP_NOZORDER, SWP_NOMOVE))
      ::CoorsUpdate()
   endif
return nil

METHOD HandleEvent( nMsg, nWParam, nLParam ) CLASS MyCalendar
   // TODO: Verify others messages
   if nMsg==WM_LBUTTONUP
      ::Super:HandleEvent( nMsg, nWParam, nLParam )
   endif
return nil

METHOD Change() CLASS MyCalendar
   local aTmp
   static dOldDate, dOldDate2

   if ::bChange != nil
      if ::lMultiselect
         aTmp := ::GetDateRange()
         if dOldDate != aTmp[1] .or. dOldDate2 != aTmp[2]
            Eval( ::bChange, Self )
            dOldDate := aTmp[1]
            dOldDate2 := aTmp[2]
         endif
      else
         if dOldDate != ::GetDate()
            Eval( ::bChange, Self )
            dOldDate = ::GetDate()
         endif
      endif
   endif
return NIL

METHOD Notify( nIdCtrl, nPtrNMHDR ) CLASS MyCalendar
   local nCode := GetNMHDRCode( nPtrNMHDR ), nOld, nNew
   if nCode == MCN_VIEWCHANGE
      if !empty(::bViewChanged)
         MonthCal_GetViewChangeValues(nPtrNMHDR, @nOld, @nNew)
         eval(::bViewChanged, self, nOld, nNew)
      endif
      return nil
   endif
return ::Super:Notify( nIdCtrl, nPtrNMHDR )

//----------------------------------------------------------------------------//

#pragma BEGINDUMP
#include <Windows.h>
#include <CommCtrl.h>
#include <hbapi.h>
#include <hbdate.h>
#include <fwh.h>

//----------------------------------------------------------------------------//

HB_FUNC( MONTHCAL_GETMINREQRECT )     //  hWnd  -->  { nTop, nLeft, nBottom, nRight }
{
   HWND hWnd = ( HWND ) fw_parH( 1 );
   RECT rct;

   rct.top    = 0;
   rct.left   = 0;
   rct.bottom = 0;
   rct.right  = 0;

   if( hWnd )
      MonthCal_GetMinReqRect( hWnd, &rct );

   hb_reta( 4 );

   hb_storvni( rct.top,    -1, 1 );
   hb_storvni( rct.left,   -1, 2 );
   hb_storvni( rct.bottom, -1, 3 );
   hb_storvni( rct.right,  -1, 4 );
}

//----------------------------------------------------------------------------//

HB_FUNC( MONTHCAL_SIZERECTTOMIN )     //  hWnd,{ nTop, nLeft, nBottom, nRight }  -->  { nTop, nLeft, nBottom, nRight }
{
   HWND hWnd = ( HWND ) fw_parH( 1 );
   RECT rct;

   rct.top    = hb_parvni( 2, 1 );
   rct.left   = hb_parvni( 2, 2 );
   rct.bottom = hb_parvni( 2, 3 );
   rct.right  = hb_parvni( 2, 4 );

   if( hWnd )
      MonthCal_SizeRectToMin( hWnd, &rct );

   hb_reta( 4 );

   hb_storvni( rct.top,    -1, 1 );
   hb_storvni( rct.left,   -1, 2 );
   hb_storvni( rct.bottom, -1, 3 );
   hb_storvni( rct.right,  -1, 4 );
}

//----------------------------------------------------------------------------//

HB_FUNC( MONTHCAL_SETCURRENTVIEW )     //  hWnd, id
{
   MonthCal_SetCurrentView(( HWND ) fw_parH( 1 ), hb_parni( 2 ));
}

//----------------------------------------------------------------------------//

HB_FUNC( MONTHCAL_GETCURRENTVIEW )     //  hWnd -> id
{
   hb_retni(MonthCal_GetCurrentView(( HWND ) fw_parH( 1 )));
}

//----------------------------------------------------------------------------//

HB_FUNC( MONTHCAL_GETVIEWCHANGEVALUES )     //  NMVIEWCHANGE, @bOld, @nNew
{
   LPNMVIEWCHANGE lParam = (LPNMVIEWCHANGE) fw_parH( 1 );
   hb_storni(lParam->dwOldView, 2 );
   hb_storni(lParam->dwNewView, 3 );
}

#pragma ENDDUMP
I added some code to automatic resize to best dimension at init

Re: About TCalendar

Posted: Thu Dec 24, 2020 12:13 pm
by Antonio Linares
Antonino,

many thanks.

We have included the new DATA and the new Methods SetCurrentView() and GetCurrentView() for the next FWH build

When we run your posted code we get this:
Image

Re: About TCalendar

Posted: Tue Dec 29, 2020 8:02 am
by AntoninoP
I just re-try with FiveWin 18.01
Image
in your screenshot these lines are not executed:

Code: Select all

      rc := MonthCal_SizeRectToMin( ::hWnd, GetClientRect( ::hWnd ) )
      SetWindowPos(::hWnd, 0, 0, 0, rc[4], rc[3], nOr(SWP_NOZORDER, SWP_NOMOVE))
      ::CoorsUpdate()
I did put them on New and on Initiate

Re: About TCalendar

Posted: Tue Dec 29, 2020 9:59 am
by Silvio.Falconi
A question..
I have the calendar on my Project as you see on this picture
I use sample01.prg

, if I resize the splitter on right

Image

I wish the calendar resize until the splitter, showing 3 months per row or depending on the space created up to the splitter
How can I solve?
probable on dialog tcalendar not resize good?

Re: About TCalendar

Posted: Tue Dec 29, 2020 10:43 am
by Silvio.Falconi
I tried

oPanel := ::oExBar:AddPanel( Upper( "Jump To Date" ), "d:\fwh\bitmaps\32x32\calendar.bmp", 480 )
// @ 40, 15 CALENDAR ::oDtPick VAR ::dDateStart OF oPanel PIXEL SIZE 220, 157 WEEKNUMBER DAYSTATE
::oDtPick := MyCalendar():New( 40, 10, { | u | If( PCount()==0, ::dDateStart, ::dDateStart:= u ) }, nil,oPanel, 700, 520,,,,, .F.,, .T.,, .F., .F.,,,,,, .F., .T., .T., .F. )
::oDtPick:bViewChanged := {|Self,nOld,nNew| iif(nNew<MCMV_YEAR,::SetCurrentView(MCMV_YEAR),) }

::oDtPick:bChange = { | o | ::ChangeDate( o ) }

but I have this result

Image

then if I resize the splitter

I have this result not seeing the sequence of the mounths

Image

Re: About TCalendar

Posted: Tue Dec 29, 2020 11:10 am
by Silvio.Falconi
Now I tried with

::oDtPick := MyCalendar():New( 30, 1, { | u | If( PCount()==0, ::dDateStart, ::dDateStart:= u ) }, nil,oPanel, 200, 160,,,,, .F.,, .T.,, .F., .F.,,,,,, .F., .T., .T., .F. )


::oDtPick:bViewChanged := {|Self,nOld,nNew| iif(nNew<MCMV_YEAR,::SetCurrentView(MCMV_YEAR),) }
::oDtPick:bChange = { | o | ::ChangeDate( o ) }


oPanel:bResized := <||
local oRect :=oPanel:GetCliRect()
::oDtPick:nWidth := oRect:nRight
return nil
>

seem to run , but there is something bad

Re: About TCalendar

Posted: Tue Dec 29, 2020 12:39 pm
by Silvio.Falconi
the test of Antonino run ok
I add resizable system to resize the calendar

Image

Code: Select all

    #include <fivewin.ch>
    #include <calendar.ch>

    // MyCalendar
    #define MCMV_MONTH      0
    #define MCMV_YEAR       1
    #define MCMV_DECADE     2
    #define MCMV_CENTURY    3
    #define MCMV_MAX        MCMV_CENTURY

    // TEST CODE
    proc main()
       LOCAL oDlg, oMonth, dData1 := Date(),dData2 := Date(), oMonth2, dMese := Date()
       DEFINE DIALOG oDlg SIZE 700,400 PIXEL TRUEPIXEL;
          TITLE "Test MonthCal"   RESIZABLE
       //@ 10,10 CALENDAR oMonth VAR dData1,dData2 PIXEL NOTADAY NOTODAYCIRCLE SIZE 500,20
       oMonth := MyCalendar():New( 10, 10, { | u | If( PCount()==0, dData1, dData1:= u ) }, { | u | If( PCount()==0, dData2, dData2:= u ) },, 500, 20,,,,, .F.,, .T.,, .F., .F.,,,,,, .F., .T., .T., .F. )
       // only month calendar test
       //@ 210,10 CALENDAR oMonth2 VAR dMese PIXEL NOTADAY NOTODAYCIRCLE SIZE 700,20
       oMonth2 := MyCalendar():New( 210, 10, { | u | If( PCount()==0, dMese, dMese:= u ) }, nil,, 700, 160,,,,, .F.,, .T.,, .F., .F.,,,,,, .F., .T., .T., .F. )
       oMonth2:bViewChanged := {|Self,nOld,nNew| iif(nNew<MCMV_YEAR,::SetCurrentView(MCMV_YEAR),) }


                           oDlg:bResized  := <||
                           local oRect       := oDlg:GetCliRect()
                              oMonth2:nWidth     := oRect:nRight
                           return nil
                     >

       ACTIVATE DIALOG oDlg CENTERED;
       ON INIT (oMonth2:SetCurrentView(MCMV_YEAR),EVAL( oDlg:bResized))


    // MyCalendar
    #define SWP_NOSIZE        0x0001
    #define SWP_NOMOVE        0x0002
    #define SWP_NOZORDER      0x0004

    #define MCN_VIEWCHANGE      (-750)

    CLASS MyCalendar FROM TCalendar
       DATA bViewChanged

       METHOD New(...) CONSTRUCTOR

       METHOD HandleEvent( nMsg, nWParam, nLParam )
       METHOD Change()
       METHOD Notify( nIdCtrl, nPtrNMHDR )

       // use SetGet?
       METHOD Initiate( hDlg )
       METHOD SetCurrentView(id) INLINE MonthCal_SetCurrentView(::hWnd, id)
       METHOD GetCurrentView() INLINE MonthCal_GetCurrentView(::hWnd)

    endclass

    METHOD New(...) CLASS MyCalendar
       LOCAL rc
       ::Super:new(...)
       if !Empty( ::hWnd )
          rc := MonthCal_SizeRectToMin( ::hWnd, GetClientRect( ::hWnd ) )
          SetWindowPos(::hWnd, 0, 0, 0, rc[4], rc[3], nOr(SWP_NOZORDER, SWP_NOMOVE))
          ::CoorsUpdate()
       endif
    return Self

    METHOD Initiate( hDlg )  CLASS MyCalendar
       LOCAL rc
       ::Super:Initiate(hDlg)
       if !Empty( ::hWnd )
          rc := MonthCal_SizeRectToMin( ::hWnd, GetClientRect( ::hWnd ) )
          SetWindowPos(::hWnd, 0, 0, 0, rc[4], rc[3], nOr(SWP_NOZORDER, SWP_NOMOVE))
          ::CoorsUpdate()
       endif
    return nil

    METHOD HandleEvent( nMsg, nWParam, nLParam ) CLASS MyCalendar
       // TODO: Verify others messages
       if nMsg==WM_LBUTTONUP
          ::Super:HandleEvent( nMsg, nWParam, nLParam )
       endif
    return nil

    METHOD Change() CLASS MyCalendar
       local aTmp
       static dOldDate, dOldDate2

       if ::bChange != nil
          if ::lMultiselect
             aTmp := ::GetDateRange()
             if dOldDate != aTmp[1] .or. dOldDate2 != aTmp[2]
                Eval( ::bChange, Self )
                dOldDate := aTmp[1]
                dOldDate2 := aTmp[2]
             endif
          else
             if dOldDate != ::GetDate()
                Eval( ::bChange, Self )
                dOldDate = ::GetDate()
             endif
          endif
       endif
    return NIL

    METHOD Notify( nIdCtrl, nPtrNMHDR ) CLASS MyCalendar
       local nCode := GetNMHDRCode( nPtrNMHDR ), nOld, nNew
       if nCode == MCN_VIEWCHANGE
          if !empty(::bViewChanged)
             MonthCal_GetViewChangeValues(nPtrNMHDR, @nOld, @nNew)
             eval(::bViewChanged, self, nOld, nNew)
          endif
          return nil
       endif
    return ::Super:Notify( nIdCtrl, nPtrNMHDR )

    //----------------------------------------------------------------------------//

    #pragma BEGINDUMP
    #include <Windows.h>
    #include <CommCtrl.h>
    #include <hbapi.h>
    #include <hbdate.h>
    #include <fwh.h>

    //----------------------------------------------------------------------------//

    HB_FUNC( MONTHCAL_GETMINREQRECT )     //  hWnd  -->  { nTop, nLeft, nBottom, nRight }
    {
       HWND hWnd = ( HWND ) fw_parH( 1 );
       RECT rct;

       rct.top    = 0;
       rct.left   = 0;
       rct.bottom = 0;
       rct.right  = 0;

       if( hWnd )
          MonthCal_GetMinReqRect( hWnd, &rct );

       hb_reta( 4 );

       hb_storvni( rct.top,    -1, 1 );
       hb_storvni( rct.left,   -1, 2 );
       hb_storvni( rct.bottom, -1, 3 );
       hb_storvni( rct.right,  -1, 4 );
    }

    //----------------------------------------------------------------------------//

    HB_FUNC( MONTHCAL_SIZERECTTOMIN )     //  hWnd,{ nTop, nLeft, nBottom, nRight }  -->  { nTop, nLeft, nBottom, nRight }
    {
       HWND hWnd = ( HWND ) fw_parH( 1 );
       RECT rct;

       rct.top    = hb_parvni( 2, 1 );
       rct.left   = hb_parvni( 2, 2 );
       rct.bottom = hb_parvni( 2, 3 );
       rct.right  = hb_parvni( 2, 4 );

       if( hWnd )
          MonthCal_SizeRectToMin( hWnd, &rct );

       hb_reta( 4 );

       hb_storvni( rct.top,    -1, 1 );
       hb_storvni( rct.left,   -1, 2 );
       hb_storvni( rct.bottom, -1, 3 );
       hb_storvni( rct.right,  -1, 4 );
    }

    //----------------------------------------------------------------------------//

    HB_FUNC( MONTHCAL_SETCURRENTVIEW )     //  hWnd, id
    {
       MonthCal_SetCurrentView(( HWND ) fw_parH( 1 ), hb_parni( 2 ));
    }

    //----------------------------------------------------------------------------//

    HB_FUNC( MONTHCAL_GETCURRENTVIEW )     //  hWnd -> id
    {
       hb_retni(MonthCal_GetCurrentView(( HWND ) fw_parH( 1 )));
    }

    //----------------------------------------------------------------------------//

    HB_FUNC( MONTHCAL_GETVIEWCHANGEVALUES )     //  NMVIEWCHANGE, @bOld, @nNew
    {
       LPNMVIEWCHANGE lParam = (LPNMVIEWCHANGE) fw_parH( 1 );
       hb_storni(lParam->dwOldView, 2 );
       hb_storni(lParam->dwNewView, 3 );
    }

    #pragma ENDDUMP


When I put the resize system on sample01 ( tcalex) not run !!

Re: About TCalendar

Posted: Tue Dec 29, 2020 7:29 pm
by Antonio Linares
Antonino,

function MonthCal_SizeRectToMin() seems not to be working at all, in example:

rc := MonthCal_SizeRectToMin( ::hWnd, { 1, 1, 20, 20 } )
XBrowse( rc ) // you get { 1, 1, 20, 20 }

It seems to be working fine this way:
rc := MonthCal_GetMinReqRect( ::hWnd )
XBrowse( rc )