I've been asked by a few people for a short .prg that shows how to use codejock extreme calendar with dbfcdx.
Below is a single short .prg that syncs "events" on the calendar to a dbf/fpt/cdx. I'm trying to keep the sample short. Keep in mind that each event on the calendar may have as many fields as you'd like for things such as "recurring", "reminder", "send email alert", "email address", "medical record", etc... each of these fields would be kept on each event as a custom property. On this short sample I'm implementing only a single custom property "id" to keep the corresponding primary key on file for each event on the calendar.
I hope it helps, but if there are more questions; please feel free to ask, I'm more than willing to help.
- Code: Select all Expand view RUN
- /*----------------------------------------------------------------------------*/
#include "fivewin.ch"
//---------- theme constants
#define xtpCalendarThemeOffice2000 0
#define xtpCalendarThemeOfficeXP 1
#define xtpCalendarThemeOffice2003 2
#define xtpCalendarThemeOffice2007 3
//----------- views
#define xtpCalendarDayView 0
#define xtpCalendarWorkWeekView 1
#define xtpCalendarWeekView 2
#define xtpCalendarMonthView 3
static cAlias
*--------------------------------------------------------------------------
function Main()
create_dbf()
MpCal():New()
(cAlias)->( dbCloseArea() )
return nil
//---------------------------------------------------//
static function create_dbf()
local astruc := { { "id", "C", 12, 0 },;
{ "starttime" , "C", 18, 0 },;
{ "endtime" , "C", 18, 0 },;
{ "subject" , "C", 50, 0 },;
{ "body" , "M", 10, 0 } }
cAlias := "Calendar"
if !file( "calendar.dbf")
dbcreate( cAlias, aStruc, "DBFCDX", .t., cAlias )
(cAlias)->( OrdCreate( cAlias, "id", "id" ) )
(cAlias)->( OrdCreate( cAlias, "starttime", "starttime" ) )
else
dbuseArea( .t., "DBFCDX", cAlias, cAlias, .t. )
endif
(cAlias)->( OrdListAdd( cAlias ) )
Return Nil
//---------------------------------------------------//
CLASS MpCal
DATA dCurrentDate AS DATE INIT Date()
DATA oCalex, oCalexCapBar
DATA oDtPick
DATA oExBar
DATA oPanelExplorer
DATA oPanelCalex
DATA oWnd
METHOD New()
METHOD BuildCalex()
METHOD BuildDatePicker()
METHOD BuildPanels()
METHOD SetSize( nType, nWidth, nHeight )
METHOD xTrmCalTriggeredEvents( Event, Parms )
METHOD RetrieveDayEvents( aParms )
METHOD InsertEvent( oEvent )
METHOD UpdateEvent( oEvent )
METHOD DeleteEvent( oEvent )
ENDCLASS
//---------------------------------------------------//
METHOD New() CLASS MpCal
local oMenu
local oSelf := Self
MENU oMenu
ENDMENU
DEFINE WINDOW ::oWnd MDI MENU oMenu Title "CodeJock Xtrme Calendar FWH Sample"
::BuildPanels() //two panels -left and right
::BuildCalex() //CodeJock calendar on the right
::BuildDatePicker() //CodeJock DatePicker on the left
ACTIVATE WINDOW ::oWnd MAXIMIZED;
ON RESIZE oSelf:SetSize( nSizeType, nWidth, nHeight )
RETURN Self
//-----------------------------------------------------------------------------------------------------//
METHOD xTrmCalTriggeredEvents( Event, aParms ) CLASS MpCal
if valType( Event ) == "C"
Do Case
Case Event == "DoRetrieveDayEvents"
::RetrieveDayEvents( aParms )
case Event == "EventAddedEx"
::InsertEvent( aParms[ 1 ] )
case Event == "EventChangedEx" .and. aParms[ 1 ]:CustomProperties:Property( "id" ) != Nil
::UpdateEvent( aParms[ 1 ] )
case Event == "EventDeletedEx" .and. aParms[ 1 ]:CustomProperties:Property( "id" ) != Nil
::DeleteEvent( aParms[ 1 ] )
/* other useful triggered events that may be catched.
Case Event == "DblClick"
Case Event == "MouseMove"
Case Event == "MouseDown"
case Event == "KeyDown"
case Event == "IsEditOperationDisabled"
case Event == "IsEditOperationDisabledV"
case Event == "DoUpdateEvent"
case Event == "BeforeEditOperation"
Return ::BeforeEditOperation( aParms[ 1 ] )
otherwise
Logfile( "trace.log", { EventInfo( event, aParms ) } ) */
End
endif
Return nil
//-----------------------------------------------------------------------------------------------------//
METHOD InsertEvent( oEvent ) CLASS MpCal
local cId := GetUniqueId()
(cAlias)->( dbappend() )
(cAlias)->( rLock() )
(cAlias)->id := cId
(cAlias)->Subject := oEvent:Subject()
(cAlias)->StartTime := Left( TtoS( oEvent:StartTime() ), 14 )
(cAlias)->EndTime := Left( TtoS( oEvent:EndTime() ), 14 )
(cAlias)->body := oEvent:Body()
(cAlias)->( dbrUnlock() )
//load custom property for the newly created event with a unique id that will
//match field "id" on calendar.dbf
oEvent:CustomProperties:Property( "id", cId )
//every time a new appointment is added on the calendar control
//you could expand appntmnt details with a custom form where you may pickup
//other values.
//::EventDetails( oEvent )
Return oEvent
//-----------------------------------------------------------------------------------------------------//
METHOD UpdateEvent( oEvent ) CLASS MpCal
local cid := oEvent:CustomProperties:Property( "id" )
(cAlias)->( OrdSetFocus( "id" ) )
(cAlias)->( dbseek( cId ) )
if (cAlias)->( found() ) .and. (cAlias)->( rLock() )
(cAlias)->Subject := oEvent:Subject()
(cAlias)->StartTime := Left( TtoS( oEvent:StartTime() ),14 )
(cAlias)->EndTime := Left( TtoS( oEvent:EndTime() ), 14 )
(cAlias)->body := oEvent:body
(cAlias)->( dbrUnlock() )
endif
//if there is more data that's being pickedup as part of the calendar appointment
//then call that screen to allow modification of those values also
//::EventDetails( oEvent )
return oEvent
//-----------------------------------------------------------------------------------------------------//
METHOD DeleteEvent( oEvent ) CLASS MpCal
local cid := oEvent:CustomProperties:Property( "id" )
(cAlias)->( OrdSetFocus( "id" ) )
(cAlias)->( dbseek( cId ) )
if (cAlias)->( found() ) .and. (cAlias)->( rLock() )
(cAlias)->( delete() )
endif
return oEvent
//-----------------------------------------------------------------------------------------------------//
//aParms[ 1 ] contains a datetime value. This function should return all the events found on
//calendar.dbf for that date. To extract only the date portion, we convert the datetime
//value to string and then pullout the first 8 chars asin YYYYMMDD.
//keep in mind that the control calls this function each time the control changes dates,
//or changes views or just about any time the control feels it needs to load data from
//file. So it gets called a lot!
METHOD RetrieveDayEvents( aParms ) CLASS MpCal
local oEvents := aParms[ 2 ]
local oEvent
local cDate := Left( TtoS( aParms[ 1 ] ), 8 )
(cAlias)->( OrdSetFocus( "StartTime" ) )
(cAlias)->( dbSeek( cDate ) )
While !(cAlias)->( eof() ) .and. left( (cAlias)->StartTime, 8 ) == cDate
oEvent := ::oCalex:DataProvider:CreateEvent()
With Object oEvent
:Subject := (cAlias)->Subject
:StartTime := StoT( (cAlias)->StartTime )
:EndTime := StoT( (cAlias)->EndTime )
:body := (cAlias)->body
//custom property "id" will hold the contents of field "id" on calendar.dbf
//to help us match each event displayed on the calendar to a unique record
//on the calendar table.
:CustomProperties:Property( "id", (cAlias)->id )
End
oEvents:add( oEvent )
(cAlias)->( dbSkip() )
end
Retur Nil
//---------------------------------------------------------------------------------------------------//
METHOD BuildCalex() CLASS MpCal
local oErr
local cIni := "patients.ini"
TRY
::oCalex := tActiveX():New( ::oPanelCalex, "Codejock.CalendarControl.13.4.2" )
CATCH oErr
MsgStop( "Missing installation Components", "Aborting" )
Quit
END
with object ::oCalex
:VisualTheme( xtpCalendarThemeOffice2007 )
:bOnEvent = { | event, aParms | ::xTrmCalTriggeredEvents( Event, aParms ) }
:SetDataProvider( "Provider=custom" )
:DataProvider:open()
:ShowCaptionBar( .t. )
:ShowCaptionBarSwitchViewButtons( .t. ) //switch from day, week, month view on capbar
:ViewType( xtpCalendarDayView )
:DayView:TimeScaleMinTime( [8:00:00 AM] )
:DayView:TimeScaleMaxTime( [6:00:00 PM] )
:DayView:TimeScale( 15 )
:DayView:ScrollToWorkDayBegin() //scroll the view to the work day starting time
:Options:DayViewTimeScaleShowMinutes( .t. )
end
::oPanelCalex:oClient = ::oCalex
Return Nil
//---------------------------------------------------//
METHOD BuildDatePicker() CLASS MpCal
local nTmp
local oPanel, oErr, oWnd
TRY
::oDtPick := tActiveX():New( ::oPanelExplorer,"Codejock.DatePicker.13.4.2" )
With Object ::oDtPick
:Enabled( .t. )
:ShowWeekNumbers( .t. )
:VisualTheme( xtpCalendarThemeOffice2007 )
:AttachToCalendar( TOleAuto():New( ActXPdisp( ::oCalex:hActiveX ) ) )
End
::oPanelExplorer:oClient := ::oDtPick
CATCH oErr
END
RETURN nil
//---------------------------------------------------//
METHOD BuildPanels() CLASS MpCal
local oBrush
local nHeight := ::oWnd:nHeight
::oPanelCalex = TPanel():New( 0, 175, nHeight, ::oWnd:nWidth, ::oWnd:oWndClient )
::oPanelExplorer = TPanel():New( 0, 0, nHeight, ::oPanelCalex:nLeft, ::oWnd:oWndClient )
RETURN nil
//---------------------------------------------------//
METHOD SetSize( nType, nWidth, nHeight ) CLASS MpCal
if nWidth != nil
::oPanelExplorer:Move( , , , nHeight )
::oPanelCalex:Move( , , nWidth - ::oPanelExplorer:nRight, nHeight )
endif
RETURN nil
*-------------------------------------------------------------------------------------------------------------------------------
procedure RddInit()
Set Century On
Set Deleted On
Set SoftSeek On
Set Date Format "MM/DD/YYYY"
set epoch to 1950
rddsetdefault( "ADS" )
REQUEST HB_LANG_EN
REQUEST DBFCDX, DBFFPT
return
*-------------------------------------------------------------------------------------------------------------------------------
//I would recommend a better unique value to id each event saved to calendar.dbf
//A better choice of unique Id would be ADS's field defaulting to NewIdString( 'M' )
//but this will do for the this short sample
//
static Function GetUniqueId()
local cJulian := StrZero( DoY( date() ), 3 )
Local cId := Right( StrZero( Year( Date() ), 4 ), 2 ) + cJulian + StrTran( StrZero( Seconds(), 7, 1 ), ".", "" )
Return ( cId )
Regards;
Reinaldo.