Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
Control for spinner for time (not timer)
Message
De
08/04/2015 08:26:43
 
 
À
07/04/2015 17:37:48
Information générale
Forum:
Visual FoxPro
Catégorie:
Codage, syntaxe et commandes
Versions des environnements
Visual FoxPro:
VFP 9 SP2
OS:
Windows Server 2012
Network:
Windows 2008 Server
Database:
Visual FoxPro
Application:
Desktop
Divers
Thread ID:
01617987
Message ID:
01618014
Vues:
69
In all these years I have never been asked to have a time value that worked like a spinner control. (in fact, I don't know if I have ever used time values much except to stamp records in the background). This client wants to have the time thrown onto a form and then be able to back up by a few minutes if need be via a spinner like control.

But spinners work on numerics, not time. Is there something like this or do I just have to create my own spinner like object (i.e. group of objects).

Any ideas...late in the day so brain not firing very well!
**************************************************
*-- Class:        spntime (f:\wwnew\libs\basectrl.vcx)
*-- ParentClass:  spnbase (f:\wwnew\libs\basectrl.vcx)
*-- BaseClass:    spinner
*-- Time Stamp:   03/22/04 05:25:03 PM
*-- Time Spinner Class - can be configured to show seconds by setting the lShowSeconds property to true
*
DEFINE CLASS spntime AS spnbase


	Increment =   0.00
	SpinnerHighValue = 235959.00
	SpinnerLowValue =   0.00
	Width = 132
	Format = "RL"
	*-- Saves original controlsoource since it is a character string
	ccontrolsource = ""
	nselstart = 0
	*-- Used to keep the current segment from losing focus if the user types in an invalid value for hours, minutes, or second
	lsegmentisvalid = .T.
	Name = "spntimebase"

	*-- True if we are using seconds in the spinner
	lshowseconds = .F.


	PROCEDURE incrementhours
		LPARAMETERS tlDecrement
		LOCAL lnHours, lnRest

		WITH This
			lnRest = .Value % IIF( .lShowSeconds, 10000, 100 )
			IF .lShowSeconds
				lnHours = VAL( LEFT ( PADL ( INT( .Value ), 6, '0' ) , 2 ) )
			ELSE
				lnHours = VAL( LEFT ( PADL ( INT( .Value ), 4, '0' ) , 2 ) )
			ENDIF
			IF tlDecrement
				lnHours = IIF( lnHours = 00 OR lnHours > 23, 23, lnHours - 1 ) 
			ELSE
				lnHours = IIF( lnHours > 22, 00, lnHours + 1 )
			ENDIF
			.Value = lnHours * IIF( .lShowSeconds, 10000, 100 ) + lnRest
		ENDWITH

	ENDPROC


	PROCEDURE incrementminutes
		LPARAMETERS tlDecrement
		LOCAL lcTime, lnMinutes, lcHours, lcSeconds

		WITH This
			IF .lShowSeconds
				lcTime = PADL ( INT( .Value ), 6, '0' )
				lnMinutes = INT ( INT( .Value ) % 10000 / 100 )
				lcSeconds = RIGHT( PADL ( INT( .Value ), 6, '0' ), 2 ) 
			ELSE
				lcTime = PADL ( INT( .Value ), 4, '0' )
				lnMinutes = INT( .Value ) % 100
			ENDIF
			IF tlDecrement
				lnMinutes = IIF( lnMinutes = 00 OR lnMinutes > 59, 59, lnMinutes - 1 ) 
			ELSE
				lnMinutes = IIF( lnMinutes > 58, 00, lnMinutes + 1 )
			ENDIF
			.Value = VAL( LEFT( lcTime, 2 ) + PADL( lnMinutes, 2, '0' ) ;
					+ IIF( .lShowSeconds, RIGHT( lcTime, 2 ), '' ) )
		ENDWITH

	ENDPROC


	PROCEDURE setup
		WITH This
			*** Format the input mask depending on whether or not we are showing seconds
			IF .lShowSeconds
				.InputMask = "99:99:99"
			ELSE
				.InputMask = "99:99"
			ENDIF
			.RefreshSpinner()
		ENDWITH

	ENDPROC


	PROCEDURE sethighlight
		*** Hightlight either the hours, minutes, or seconds portion
		WITH This
			DO CASE
				CASE BETWEEN( .SelStart, 0, 2 )
					.SelStart = 0
				CASE BETWEEN( .SelStart, 3, 5 )
					.SelStart = 3
				OTHERWISE
					.SelStart = IIF( .lShowSeconds, 6, 0 )
			ENDCASE
			.SelLength = 2
			.nSelStart = .SelStart
		ENDWITH
	ENDPROC


	PROCEDURE movehighlight
		LPARAMETERS nKeyCode
		*** nKeyCode = 19 means we have pressed left arrow
		*** otherwise, a right arrow was pressed
		WITH This
			DO CASE
		   		CASE BETWEEN( .SelStart, 0, 2 )
		   			IF .lShowSeconds
						.SelStart = IIF( nKeyCode = 19, 6, 3 )
					ELSE
						.SelStart = 3 
					ENDIF
				CASE BETWEEN( .SelStart, 3, 5 )
					IF .lShowSeconds
						.SelStart = IIF( nKeyCode = 19, 0, 6 )
					ELSE
						.SelStart = 0
					ENDIF
				OTHERWISE
					.SelStart = IIF( nKeyCode = 19, 3, 0 )
			ENDCASE
			.SelLength = 2
			.nSelStart = .SelStart
		ENDWITH
	ENDPROC


	PROCEDURE changetime
		LPARAMETERS tlDecrement
		*** when tlDecrement is true, we are decrementing the time, otherwise we are
		*** incrementing. First, we must select which segment is being adjusted by 
		*** examining the previously saved value of nselstart
		WITH This
			DO CASE
				CASE BETWEEN( .nSelStart, 0, 2 )
					.IncrementHours( tlDecrement )

				CASE BETWEEN( .nSelStart, 3, 5 )
					.IncrementMinutes( tlDecrement )

				OTHERWISE
					IF tlDecrement
						.Value = IIF( INT( .Value % 100 ) = 0 OR INT( .Value % 100 ) > 59, INT( .Value / 100 ) * 100 + 59, .Value - 1 )
					ELSE
						.Value = IIF( INT( .Value % 100 ) > 58, INT( .Value / 100 ) * 100, .Value + 1 )
					ENDIF
		 	ENDCASE
			.lSegmentIsValid = .T.
		ENDWITH
	ENDPROC


	*-- Update the control source if this is a bound control
	PROCEDURE updatecontrolsource
		LOCAL lcTable, lcField, lcValue, lcTemp
		WITH This
			*** Parse out the name of the table and the name of the field in cControlSource
			IF ! EMPTY( .cControlSource ) 
				*** If This is a bound control, set save table and field bound to
				*** Parse out the name of the table if the ControlSource is prefaced by an alias
				IF '.' $ .cControlSource
					lcTable = LEFT( .cControlSource, AT( '.', .cControlSource ) - 1 )
					lcField = SUBSTR( .cControlSource, AT( '.', .cControlSource ) + 1 )
				ELSE
					*** assume the alias is the current selected alias. This is a little dangerous, but if it is
					*** a bad assumption, the program will blow up very quickly in development mode
					*** giving the developer a very clear indication of what is wrong once he checks out
					*** the problem in the debugger
					lcTable = ALIAS()
					lcField = .cControlSource
		   		ENDIF
		   		*** Now convert the numeric value of the spinner to the character value required by the 
		   		*** controlSource (if it is bound) and format it with colons. You must take into account 
		   		*** whether or not we are displaying seconds in the spinner
		   		lcTemp  = IIF( .lShowSeconds, PADL( INT ( .Value ), 6, '0' ), PADL( INT ( .Value ), 4, '0' ) ) 
		   		lcValue = LEFT( lcTemp, 2 ) + ':' + SUBSTR( lcTemp, 3, 2 ) + ;
		   					IIF( .lShowSeconds, ':' + RIGHT( lcTemp, 2 ), '' )
		   		*** Lots of people bind controls to form properties, so let's just check here to see if our
		   		*** alias is ThisForm. If it is, we will assume that we are bound to a form property
		   		IF UPPER( lcTable ) = 'THISFORM'
		   			STORE lcValue TO ( .cControlSource )
		   		ELSE
		   			REPLACE ( lcField ) WITH lcValue IN ( lcTable )
		   		ENDIF
		   	ENDIF
		ENDWITH   
	ENDPROC


	*-- IF this is a bound control, update the value of the spinner from its cControlSource
	PROCEDURE refreshspinner
		*** SInce the spinner must be bound to a numeric value, if it is bound,
		*** use the cControlSource property instead
		*** initialize the control's value
		WITH This
			IF ! EMPTY( .cControlSource )
				.Value = IIF( .lSHowSeconds, VAL( STRTRAN( EVAL( .cControlSource ), ':', '' ) ), ;
							VAL( STRTRAN( LEFT ( EVAL( .cControlSource ), 5 ), ':', '' ) ) )
			ELSE
				.Value = IIF( .lShowSeconds, VAL( STRTRAN( TIME(), ':', '' ) ), ;
							VAL( STRTRAN( LEFT( TIME(), 5), ':', '' ) ) )
			ENDIF
		ENDWITH
	ENDPROC


	*-- Used to validate current segment when the user types a value directly into the control
	PROCEDURE validatesegment
		LOCAL lnHours, lnMinutes, llRetVal

		*** Figure out which segment we are validating
		*** and check for a legal value
		WITH This
			DO CASE
				CASE BETWEEN( .nSelStart, 0, 2 )
					IF .lShowSeconds
						lnHours = VAL( LEFT ( PADL ( INT( .Value ), 6, '0' ) , 2 ) )
					ELSE
						lnHours = VAL( LEFT ( PADL ( INT( .Value ), 4, '0' ) , 2 ) )
					ENDIF
					IF BETWEEN( lnHours, 0, 23 )
						.lSegmentIsValid = .T.
					ELSE
						.lSegmentIsValid = .F.
						MESSAGEBOX( 'Hours must be between 0 and 23', 16, 'Invalid Time' )
					ENDIF
				CASE BETWEEN( .nSelStart, 3, 5 )
					IF .lShowSeconds
						lnMinutes = INT ( INT( .Value ) % 10000 / 100 )
					ELSE
						lnMinutes = INT( .Value ) % 100
					ENDIF
					IF BETWEEN( lnMinutes, 0, 59 )
						.lSegmentIsValid = .T.
					ELSE
						.lSegmentIsValid = .F.
						MESSAGEBOX( 'Minutes must be between 0 and 59', 16, 'Invalid Time' )
					ENDIF
				OTHERWISE
					IF .lShowSeconds
						IF BETWEEN( INT( .Value % 100 ), 0, 59 )
							.lSegmentIsValid = .T.
						ELSE
							.lSegmentIsValid = .F.
							MESSAGEBOX( 'Seconds must be between 0 and 59', 16, 'Invalid Time' )
						ENDIF
					ENDIF

			ENDCASE
		ENDWITH
	ENDPROC


	PROCEDURE GotFocus
		*** Set the highlight whether the user clicks on the control
		*** or tabs into it
		Spinner::GotFocus()
		This.SetHighLight()
		NODEFAULT
	ENDPROC


	PROCEDURE DownClick
		*** Decrement the appropriate portion of the spinner and reset the highligh
		*** Passing .T. tells the changetime method to decrement to selected portion
		*** of the spinner. Passing the changetime method .f. (or no paramters) results
		*** in an increment of the selected portion
		WITH This
			IF .lSegmentIsValid
				.ChangeTime( .T. )
			ENDIF
			.SelStart = .nSelStart
			.SelLength = 2
		ENDWITH
	ENDPROC


	PROCEDURE UpClick
		*** Increment the appropriate portion of the spinner and reset the highlight
		WITH This
			IF .lSegmentIsValid
				.ChangeTime()
			ENDIF
			.SelStart = .nSelStart
			.SelLength = 2
		ENDWITH
	ENDPROC


	PROCEDURE KeyPress
		LPARAMETERS nKeyCode, nShiftAltCtrl
		LOCAL llDecrement
		WITH This
			DO CASE
				CASE nKeyCode = 19 OR nKeyCode = 4	&& Left and right arrow keys
					IF .lSegmentIsValid
						.MoveHighlight( nKeyCode )
					ENDIF
					NODEFAULT

				CASE nKeyCode = 5 OR nKeyCode = 24	&& Up or down arrow
					IF nKeyCode = 24
						llDecrement = .T.
					ENDIF
					.ChangeTime( llDecrement )
					.SelStart = .nSelStart
					.SelLength = 2
					NODEFAULT

				OTHERWISE
					*** So we don't mess up the formatted time
					*** If we start typing numbers and Part of the value is selected,
					*** we lose digits and the remaining ones shift
					.SelLength = 0  
					*** If we are typing a number directly into the control,
					*** make sure it is a valid hours, minutes, or seconds value
					IF BETWEEN( nKeyCode, 48, 57 )
						Spinner::KeyPress( nKeyCode, nShiftAltCtrl )
						.ValidateSegment()
						IF ! .lSegmentIsValid
							.SelStart  = .nSelStart
							.SelLength = 2
						ENDIF
						NODEFAULT
					ENDIF
			ENDCASE
		ENDWITH   
	ENDPROC


	PROCEDURE Init
		IF DODEFAULT()
			This.Setup()
		ENDIF
	ENDPROC


	PROCEDURE Click
		WITH This
			IF .lSegmentIsValid
				Spinner::Click()
				.SetHighLight()
			ELSE
				*** Don't let the user move out of the segement before
				*** he fixes the bad input
				.SelStart = .nSelStart
				.SelLength = 2
			ENDIF
		ENDWITH
		NODEFAULT

	ENDPROC


	PROCEDURE Refresh
		DODEFAULT()
		This.RefreshSpinner()
	ENDPROC


	PROCEDURE Valid
		WITH This
			IF .lSegmentIsValid
				.UpdateControlSource()
			ELSE
				RETURN 0
			ENDIF
		ENDWITH
	ENDPROC


ENDDEFINE
*
*-- EndDefine: spntime
**************************************************
Précédent
Suivant
Répondre
Fil
Voir

Click here to load this message in the networking platform