The ExCalendar library contains two components, simple version and drop-down version that allow you to select a date with a nice GUI. You can select the date between 1/1/100 and 12/31/9999, Both versions support images, colors, font attributes, tooltips for any date.
The idea of adding recurring events to eXCalendar consists in:
Handle the DateChanged event of the eXCalendar component
Collects the occurrences of the recurrence expression between
FirstVisibleDate, LastVisibleDate properties of the eXCalendar
component, using the RecurRange method of the eXICalendar library
For each occurrence found, add a new events using the Add method of
the Events collection of eXCalendar component
The following VB sample adds recurring events to eXCalendar :
Private Sub Calendar1_DateChanged()
DoEvents
With Calendar1
.BeginUpdate
Dim o As Variant
For Each o In CreateObject("Exontrol.ICalendar").RecurRange("DTSTART=20151201;FREQ=WEEKLY;BYDAY=FR", .FirstVisibleDate, .LastVisibleDate)
.Events.Add(o).Marker = True
Next
.EndUpdate
End With
End Sub
Private Sub Form_Load()
With Calendar1
.FirstDay = Monday
.AlignmentDay = CenterAlignment
.GridLineColor = RGB(128, 128, 128)
Calendar1_DateChanged
End With
End Sub
and you should get:
The same sample in C++, should look such as:
void C...Dlg::DateChangedCalendar1()
{
DoEvents();
EXCALENDARLib::ICalendarPtr spCalendar1 = GetDlgItem(IDC_CALENDAR1)->GetControlUnknown();
if ( spCalendar1 != NULL )
{
EXCALENDARLib::IEventsPtr spEvents = spCalendar1->Events;
spCalendar1->BeginUpdate();
EXICALENDARLib::IICalendarPtr spICal = ::CreateObject(L"Exontrol.ICalendar");
if ( spICal != NULL )
{
_variant_t vtRecurRange = spICal->GetRecurRange(L"DTSTART=20151201;FREQ=WEEKLY;BYDAY=FR",spCalendar1->FirstVisibleDate,spCalendar1->LastVisibleDate);
if ( V_VT( &vtRecurRange ) == ( VT_ARRAY | VT_DATE ) )
{
SAFEARRAY* pArray = V_ARRAY( &vtRecurRange );
DATE* pData = NULL;
if ( SUCCEEDED( SafeArrayAccessData( pArray, (LPVOID*)&pData ) ) )
{
long lowerBound = 0, upperBound = 0;
SafeArrayGetLBound(pArray, 1 , &lowerBound);
SafeArrayGetUBound(pArray, 1, &upperBound);
long nCount = upperBound - lowerBound + 1;
SafeArrayUnaccessData( pArray );
for ( long i = 0; i < nCount; i++, pData++ ) // iterate through returned values
spEvents->Add( *pData )->Marker = VARIANT_TRUE;
}
}
}
spCalendar1->EndUpdate();
}
}
BOOL C...Dlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
...
EXCALENDARLib::ICalendarPtr spCalendar1 = GetDlgItem(IDC_CALENDAR1)->GetControlUnknown();
if ( spCalendar1 != NULL )
{
spCalendar1->PutAlignmentDay(EXCALENDARLib::CenterAlignment);
spCalendar1->PutFirstDay(EXCALENDARLib::Monday);
spCalendar1->PutGridLineColor(RGB(128,128,128));
DateChangedCalendar1();
}
return TRUE; // return TRUE unless you set the focus to a control
}
where the definitions for CreateObject, DoEvents is:
The control provides events like Click or DblClick that notifies once
the user clicks / double clicks the control. The control's DateFromPoint(-1,-1)
property determines the date from the current cursor position. The Item
property of the Events collection can be of Date type, which indicates
that you can check if there is any event associated with the date.
The following VB sample displays the date being clicked:
Private Sub Calendar1_Click()
Dim d As Date
With Calendar1
d = .DateFromPoint(-1, -1)
If Not (d = 0) Then
MsgBox "You have clicked: " & d
End If
End With
End Sub
The following VB sample displays the date being clicked, including the associated event:
Private Sub Calendar1_Click()
Dim d As Date, s As String
With Calendar1.Object
d = .DateFromPoint(-1, -1)
If Not (d = 0) Then
s = "You have clicked: " & d
Dim e As EXCALENDARLibCtl.Event
Set e = .Events.Item(CDate(d))
If Not e Is Nothing Then
s = s + vbCrLf + "The date has associated an event"
End If
End If
End With
If (Len(s) > 0) Then
MsgBox s
End If
End Sub
In VBA/MSAccess, you need to replace the EXCALENDARLibCtl with EXCALENDARLib, else you will be prompted for a compiler error: "Can't find project or library"