lazarus-ccr/components/orpheus/ovcedcal.pas

1129 lines
33 KiB
ObjectPascal

{*********************************************************}
{* OVCEDCAL.PAS 4.06 *}
{*********************************************************}
{* ***** BEGIN LICENSE BLOCK ***** *}
{* Version: MPL 1.1 *}
{* *}
{* The contents of this file are subject to the Mozilla Public License *}
{* Version 1.1 (the "License"); you may not use this file except in *}
{* compliance with the License. You may obtain a copy of the License at *}
{* http://www.mozilla.org/MPL/ *}
{* *}
{* Software distributed under the License is distributed on an "AS IS" basis, *}
{* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License *}
{* for the specific language governing rights and limitations under the *}
{* License. *}
{* *}
{* The Original Code is TurboPower Orpheus *}
{* *}
{* The Initial Developer of the Original Code is TurboPower Software *}
{* *}
{* Portions created by TurboPower Software Inc. are Copyright (C)1995-2002 *}
{* TurboPower Software Inc. All Rights Reserved. *}
{* *}
{* Contributor(s): *}
{* *}
{* ***** END LICENSE BLOCK ***** *}
{$I OVC.INC}
{$B-} {Complete Boolean Evaluation}
{$I+} {Input/Output-Checking}
{$P+} {Open Parameters}
{$T-} {Typed @ Operator}
{.W-} {Windows Stack Frame}
{$X+} {Extended Syntax}
unit ovcedcal;
{-date edit field with popup calendar}
interface
uses
{$IFNDEF LCL} Windows, Messages, {$ELSE} LclIntf, LMessages, LclType, MyMisc, {$ENDIF}
Buttons, Classes, Controls, Forms, Graphics, Menus,
StdCtrls, SysUtils, {$IFNDEF LCL} {$IFDEF VERSION4} MultiMon, {$ENDIF} {$ENDIF} OvcBase, OvcCal,
OvcConst, OvcData, OvcEdPop, OvcExcpt, OvcIntl, OvcMisc, OvcEditF, OvcDate;
type
TOvcDateOrder = (doMDY, doDMY, doYMD);
TOvcRequiredDateField = (rfYear, rfMonth, rfDay);
TOvcRequiredDateFields = set of TOvcRequiredDateField;
{Events}
TOvcGetDateEvent = procedure(Sender : TObject; var Value : string) of object;
TOvcPreParseDateEvent = procedure(Sender : TObject; var Value : string)
of object;
TOvcGetDateMaskEvent = procedure(Sender : TObject; var Mask : string)
of object;
TOvcCustomDateEdit = class(TOvcEdPopup)
protected {private}
{property variables}
FAllowIncDec : Boolean;
FCalendar : TOvcCalendar;
FDate : TDateTime;
FEpoch : Integer;
FForceCentury : Boolean;
FRequiredFields : TOvcRequiredDateFields;
FTodayString : string;
{event variables}
FOnGetDate : TOvcGetDateEvent;
FOnGetDateMask : TOvcGetDateMaskEvent;
FOnPreParseDate : TOvcPreParseDateEvent;
FOnSetDate : TNotifyEvent;
{internal variables}
DateOrder : TOvcDateOrder;
HoldCursor : TCursor;
PopupClosing : Boolean;
WasAutoScroll : Boolean;
{property methods}
function GetDate : TDateTime;
function GetEpoch : Integer;
function GetPopupColors : TOvcCalColors;
function GetPopupFont : TFont;
function GetPopupHeight : Integer;
function GetPopupDateFormat : TOvcDateFormat;
function GetPopupDayNameWidth : TOvcDayNameWidth;
function GetPopupOptions : TOvcCalDisplayOptions;
function GetPopupWeekStarts : TOvcDayType;
function GetPopupWidth : Integer;
function GetReadOnly : Boolean;
procedure SetEpoch(Value : Integer);
procedure SetForceCentury(Value : Boolean);
procedure SetPopupColors(Value : TOvcCalColors);
procedure SetPopupFont(Value : TFont);
procedure SetPopupHeight(Value : Integer);
procedure SetPopupWidth(Value : Integer);
procedure SetPopupDateFormat(Value : TOvcDateFormat);
procedure SetPopupDayNameWidth(Value : TOvcDayNameWidth);
procedure SetPopupOptions(Value : TOvcCalDisplayOptions);
procedure SetPopupWeekStarts(Value : TOvcDayType);
procedure SetReadOnly(Value : Boolean);
{internal methods}
function ParseDate(const Value : string) : string;
procedure PopupDateChange(Sender : TObject; Date : TDateTime);
procedure PopupKeyDown(Sender : TObject; var Key : Word;
Shift : TShiftState);
procedure PopupKeyPress(Sender : TObject; var Key : Char);
procedure PopupMouseDown(Sender : TObject; Button : TMouseButton;
Shift : TShiftState; X, Y : Integer);
protected
procedure DoExit; override;
procedure GlyphChanged; override;
procedure KeyDown(var Key : Word; Shift : TShiftState); override;
procedure KeyPress(var Key : Char); override;
procedure SetDate(Value : TDateTime);
{protected properties}
property AllowIncDec : Boolean read FAllowIncDec write FAllowIncDec;
property Epoch : Integer read GetEpoch write SetEpoch;
property ForceCentury : Boolean read FForceCentury write SetForceCentury;
property PopupColors : TOvcCalColors read GetPopupColors
write SetPopupColors;
property PopupFont : TFont read GetPopupFont write SetPopupFont;
property PopupHeight : Integer read GetPopupHeight write SetPopupHeight;
property PopupWidth : Integer read GetPopupWidth write SetPopupWidth;
property PopupDateFormat : TOvcDateFormat read GetPopupDateFormat
write SetPopupDateFormat;
property PopupDayNameWidth : TOvcDayNameWidth read GetPopupDayNameWidth
write SetPopupDayNameWidth;
property PopupOptions : TOvcCalDisplayOptions read GetPopupOptions
write SetPopupOptions;
property PopupWeekStarts : TOvcDayType read GetPopupWeekStarts
write SetPopupWeekStarts;
property ReadOnly : Boolean read GetReadOnly write SetReadOnly;
property RequiredFields : TOvcRequiredDateFields read FRequiredFields
write FRequiredFields;
property TodayString : string read FTodayString write FTodayString;
{protected events}
property OnGetDate : TOvcGetDateEvent read FOnGetDate write FOnGetDate;
property OnGetDateMask : TOvcGetDateMaskEvent read FOnGetDateMask
write FOnGetDateMask;
property OnPreParseDate : TOvcPreParseDateEvent read FOnPreParseDate
write FOnPreParseDate;
property OnSetDate : TNotifyEvent read FOnSetDate write FOnSetDate;
public
constructor Create(AOwner : TComponent); override;
function DateString(const Mask : string) : string;
function FormatDate(Value : TDateTime) : string; dynamic;
procedure PopupClose(Sender : TObject); override;
procedure PopupOpen; override;
procedure SetDateText(Value : string); dynamic;
{public properties}
property Calendar : TOvcCalendar read FCalendar;
property Date: TDateTime read GetDate write SetDate;
end;
TOvcDateEdit = class(TOvcCustomDateEdit)
published
{properties}
{$IFDEF VERSION4}
property Anchors;
property Constraints;
property DragKind;
{$ENDIF}
property About;
property AllowIncDec;
{$IFNDEF LCL}
property AutoSelect;
{$ENDIF}
property AutoSize;
property BorderStyle;
property ButtonGlyph;
property CharCase;
property Color;
property Controller;
property Ctl3D;
property Cursor;
property DragCursor;
property DragMode;
property Enabled;
property Epoch;
property Font;
property ForceCentury;
{$IFNDEF LCL}
property HideSelection;
{$ENDIF}
property LabelInfo;
property ParentColor;
{$IFNDEF LCL}
property ParentCtl3D;
{$ENDIF}
property ParentFont;
property ParentShowHint;
property PopupAnchor;
property PopupColors;
property PopupDateFormat;
property PopupDayNameWidth;
property PopupFont;
property PopupHeight;
property PopupMenu;
property PopupOptions;
property PopupWidth;
property PopupWeekStarts;
property ReadOnly;
property RequiredFields;
property ShowButton;
property ShowHint;
property TabOrder;
property TabStop;
property TodayString;
property Visible;
{inherited events}
property OnChange;
property OnClick;
property OnDblClick;
property OnDragDrop;
property OnDragOver;
property OnEndDrag;
property OnEnter;
property OnExit;
property OnGetDate;
property OnGetDateMask;
property OnKeyDown;
property OnKeyPress;
property OnKeyUp;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
property OnPopupClose;
property OnPopupOpen;
property OnPreParseDate;
property OnSetDate;
property OnStartDrag;
end;
implementation
{*** TOvcCustomDateEdit ***}
constructor TOvcCustomDateEdit.Create(AOwner : TComponent);
var
C : array[0..1] of Char;
begin
inherited Create(AOwner);
ControlStyle := ControlStyle - [csSetCaption];
FAllowIncDec := True;
FForceCentury := False;
FRequiredFields := [rfMonth, rfDay];
FTodayString := DateSeparator;
{get the date order from windows}
C[0] := '0'; {default}
GetProfileString('intl', 'iDate', '0', C, 2);
DateOrder := TOvcDateOrder(Ord(C[0])-Ord('0'));
{load button glyph}
{$IFNDEF LCL}
FButtonGlyph.Handle := LoadBaseBitmap('ORBTNCAL');
{$ELSE}
FButtonGlyph.LoadFromLazarusResource('ORBTNCAL');
{$ENDIF}
FButton.Glyph.Assign(FButtonGlyph);
FCalendar := TOvcCalendar.CreateEx(Self, True);
FCalendar.OnChange := PopupDateChange;
FCalendar.OnExit := PopupClose;
FCalendar.OnKeyDown := PopupKeyDown;
FCalendar.OnKeyPress := PopupKeyPress;
FCalendar.OnMouseDown := PopupMouseDown;
FCalendar.Visible := False; {to avoid flash at 0,0}
FCalendar.BorderStyle := bsSingle;
FCalendar.ParentFont := False;
FCalendar.Parent := GetImmediateParentForm(Self);
end;
procedure TOvcCustomDateEdit.DoExit;
begin
try
SetDateText(Text);
except
SetFocus;
raise;
end;
if not PopupActive then
inherited DoExit;
end;
function TOvcCustomDateEdit.DateString(const Mask : string) : string;
begin
Result := OvcIntlSup.DateToDateString(Mask, DateTimeToSTDate(Date), False);
end;
function TOvcCustomDateEdit.FormatDate(Value : TDateTime) : string;
var
DateMask : string;
Mask : string;
begin
DateMask := OvcIntlSup.InternationalDate(FForceCentury);
if Assigned(FOnGetDateMask) then begin
FOnGetDateMask(Self, DateMask);
{see if the date order needs to be changed}
Mask := AnsiUpperCase(DateMask);
if (Pos('M', Mask) > Pos('Y', Mask)) or
(Pos('N', Mask) > Pos('Y', Mask)) then
DateOrder := doYMD
else if (Pos('M', Mask) > Pos('D', Mask)) or
(Pos('N', Mask) > Pos('D', Mask)) then
DateOrder := doDMY
else
DateOrder := doMDY;
end;
Result := OvcIntlSup.DateToDateString(DateMask, DateTimeToSTDate(Value), False);
end;
function TOvcCustomDateEdit.GetDate : TDateTime;
begin
SetDateText(Text);
Result := FDate;
end;
function TOvcCustomDateEdit.GetEpoch : Integer;
begin
Result := FEpoch;
if (csWriting in ComponentState) then
Exit;
if (Result = 0) and ControllerAssigned then
Result := Controller.Epoch;
end;
function TOvcCustomDateEdit.GetPopupColors : TOvcCalColors;
begin
Result := FCalendar.Colors;
end;
function TOvcCustomDateEdit.GetPopupDateFormat : TOvcDateFormat;
begin
Result := FCalendar.DateFormat;
end;
function TOvcCustomDateEdit.GetPopupDayNameWidth : TOvcDayNameWidth;
begin
Result := FCalendar.DayNameWidth;
end;
function TOvcCustomDateEdit.GetPopupFont : TFont;
begin
Result := FCalendar.Font;
end;
function TOvcCustomDateEdit.GetPopupHeight : Integer;
begin
Result := FCalendar.Height;
end;
function TOvcCustomDateEdit.GetPopupOptions: TOvcCalDisplayOptions;
begin
Result := FCalendar.Options;
end;
function TOvcCustomDateEdit.GetPopupWeekStarts: TOvcDayType;
begin
Result := FCalendar.WeekStarts;
end;
function TOvcCustomDateEdit.GetPopupWidth : Integer;
begin
Result := FCalendar.Width;
end;
function TOvcCustomDateEdit.GetReadOnly : Boolean;
begin
Result := inherited ReadOnly;
end;
procedure TOvcCustomDateEdit.GlyphChanged;
begin
inherited GlyphChanged;
if FButtonGlyph.Empty then
{$IFNDEF LCL}
FButtonGlyph.Handle := LoadBaseBitmap('ORBTNCAL');
{$ELSE}
FButtonGlyph.LoadFromLazarusResource('ORBTNCAL');
{$ENDIF}
end;
procedure TOvcCustomDateEdit.KeyDown(var Key : Word; Shift : TShiftState);
begin
inherited KeyDown(Key, Shift);
if ShowButton and (Key = VK_DOWN) and (ssAlt in Shift) then
PopupOpen;
end;
procedure TOvcCustomDateEdit.KeyPress(var Key : Char);
var
D : Word;
M : Word;
Y : Word;
begin
inherited KeyPress(Key);
if (ReadOnly) then Exit;
if FAllowIncDec and (Key in ['+', '-']) then begin
{accept current date}
DoExit;
if FDate = 0 then
DecodeDate(SysUtils.Date, Y, M, D)
else
DecodeDate(FDate, Y, M, D);
if Key = '+' then begin
Inc(D);
if D > DaysInMonth(M, Y, Epoch) then begin
D := 1;
Inc(M);
if M > 12 then begin
Inc(Y);
M := 1;
end;
end;
end else begin
{Key = '-'}
Dec(D);
if D < 1 then begin
Dec(M);
if M < 1 then begin
M := 12;
Dec(Y);
end;
D := DaysInMonth(M, Y, Epoch);
end;
end;
SetDate(STDateToDateTime(DMYToSTDate(D, M, Y, Epoch)));
{clear}
Key := #0;
end;
end;
function TOvcCustomDateEdit.ParseDate(const Value : string) : string;
var
S : string;
ThisYear : Word;
ThisMonth : Word;
ThisDay : Word;
DefaultDate : TStDate;
Increment : Integer;
Occurrence : Integer;
StartDate : TStDate;
procedure DoSetDate;
var
I : integer;
D : TStDate;
DOW : TStDayType;
begin
D := StartDate;
DOW := DayofWeek(DateTimeToStDate(SysUtils.Date));
if Pos(AnsiUppercase(Copy(LongDayNames[1],1,3)), S) > 0 then begin
DOW := Sunday;
end else if Pos(AnsiUppercase(Copy(LongDayNames[2],1,3)), S) > 0 then begin
DOW := Monday;
end else if Pos(AnsiUppercase(Copy(LongDayNames[3],1,3)), S) > 0 then begin
DOW := Tuesday;
end else if Pos(AnsiUppercase(Copy(LongDayNames[4],1,3)), S) > 0 then begin
DOW := Wednesday;
end else if Pos(AnsiUppercase(Copy(LongDayNames[5],1,3)), S) > 0 then begin
DOW := Thursday;
end else if Pos(AnsiUppercase(Copy(LongDayNames[6],1,3)), S) > 0 then begin
DOW := Friday;
end else if Pos(AnsiUppercase(Copy(LongDayNames[7],1,3)), S) > 0 then begin
DOW := Saturday;
end else begin
if DefaultDate > 0 then begin
D := DefaultDate;
Occurrence := 0;
end else if DefaultDate < 0 then begin
Result := S;
exit;
end;
end;
I := 0;
while I < Occurrence do begin
D := D + Increment;
if DayOfWeek(D) = DOW then begin
inc(I);
end;
end;
Result := FormatDate(StDateToDateTime(D));
end;
begin
{The following code provides the user the ability to enter dates
using text descriptions. All descriptions assume the current
date as a reference date. The following descriptions are currently
supported:
<day of week> Next is assumed; may be abbreviated -- 1st 3 chars
Next <day of week>
Last current day of week is assumed
Last <day of week>
First | 1st current day of week is assumed
First | 1st <day of week>
Second | 2nd current day of week is assumed
Second | 2nd <day of week>
Third | 3rd current day of week is assumed
Third | 3rd <day of week>
Fourth | 4th current day of week is assumed
Fourth | 4th <day of week>
Final | lst current day of week is assumed
Final | lst <day of week>
BOM | Begin returns first day of current month
EOM | End returns last day of current month
Yesterday returns yesterday's date
Today returns today's date
Tomorrow returns tomorrow's date}
S := AnsiUppercase(Value);
if Pos(GetOrphStr(SCCalYesterday), S) > 0 then begin
Result := FormatDate(StDateToDateTime(DateTimeToStDate(SysUtils.Date) - 1));
end else if Pos(GetOrphStr(SCCalToday), S) > 0 then begin
Result := FormatDate(StDateToDateTime(DateTimeToStDate(SysUtils.Date)));
end else if Pos(GetOrphStr(SCCalTomorrow), S) > 0 then begin
Result := FormatDate(StDateToDateTime(DateTimeToStDate(SysUtils.Date) + 1));
end else if Pos(GetOrphStr(SCCalNext), S) > 0 then begin
Increment := 1;
Occurrence := 1;
StartDate := DateTimeToStDate(SysUtils.Date);
DefaultDate := StartDate + 7;
DoSetDate;
end else if Pos(GetOrphStr(SCCalLast), S) > 0 then begin
Increment := -1;
Occurrence := 1;
StartDate := DateTimeToStDate(SysUtils.Date);
DefaultDate := StartDate - 7;
DoSetDate;
end else if Pos(GetOrphStr(SCCalPrev), S) > 0 then begin
Increment := -1;
Occurrence := 1;
StartDate := DateTimeToStDate(SysUtils.Date);
DefaultDate := StartDate - 7;
DoSetDate;
end else if (Pos(GetOrphStr(SCCalFirst), S) > 0)
or (Pos(GetOrphStr(SCCal1st), S) > 0) then begin
Increment := 1;
Occurrence := 1;
DecodeDate(SysUtils.Date, ThisYear, ThisMonth, ThisDay);
StartDate := DMYToStDate(1, ThisMonth, ThisYear, Epoch) - 1;
DefaultDate := 0;
DoSetDate;
end else if (Pos(GetOrphStr(SCCalSecond), S) > 0)
or (Pos(GetOrphStr(SCCal2nd), S) > 0) then begin
Increment := 1;
Occurrence := 2;
DecodeDate(SysUtils.Date, ThisYear, ThisMonth, ThisDay);
StartDate := DMYToStDate(1, ThisMonth, ThisYear, Epoch) - 1;
DefaultDate := 0;
DoSetDate;
end else if (Pos(GetOrphStr(SCCalThird), S) > 0)
or (Pos(GetOrphStr(SCCal3rd), S) > 0) then begin
Increment := 1;
Occurrence := 3;
DecodeDate(SysUtils.Date, ThisYear, ThisMonth, ThisDay);
StartDate := DMYToStDate(1, ThisMonth, ThisYear, Epoch) - 1;
DefaultDate := 0;
DoSetDate;
end else if (Pos(GetOrphStr(SCCalFourth), S) > 0)
or (Pos(GetOrphStr(SCCal4th), S) > 0) then begin
Increment := 1;
Occurrence := 4;
DecodeDate(SysUtils.Date, ThisYear, ThisMonth, ThisDay);
StartDate := DMYToStDate(1, ThisMonth, ThisYear, Epoch) - 1;
DefaultDate := 0;
DoSetDate;
end else if Pos(GetOrphStr(SCCalFinal), S) > 0 then begin
Increment := -1;
Occurrence := 1;
DecodeDate(SysUtils.Date, ThisYear, ThisMonth, ThisDay);
StartDate := DMYToStDate(DaysInMonth(ThisMonth,
ThisYear, Epoch),
ThisMonth, ThisYear, Epoch) + 1;
DefaultDate := 0;
DoSetDate;
end else if (Pos(GetOrphStr(SCCalBOM), S) > 0)
or (Pos(GetOrphStr(SCCalBegin), S) > 0) then begin
Increment := 0;
Occurrence := 0;
DecodeDate(SysUtils.Date, ThisYear, ThisMonth, ThisDay);
StartDate := DMYToStDate(1, ThisMonth, ThisYear, Epoch);
DefaultDate := StartDate;
DoSetDate;
end else if (Pos(GetOrphStr(SCCalEOM), S) > 0)
or (Pos(GetOrphStr(SCCalEnd), S) > 0) then begin
Increment := 0;
Occurrence := 0;
DecodeDate(SysUtils.Date, ThisYear, ThisMonth, ThisDay);
StartDate := DMYToStDate(DaysInMonth(ThisMonth,
ThisYear, Epoch),
ThisMonth, ThisYear, Epoch);
DefaultDate := StartDate;
DoSetDate;
end else begin
Increment := 1;
Occurrence := 1;
StartDate := DateTimeToStDate(SysUtils.Date);
DefaultDate := -1;
DoSetDate;
end;
end;
procedure TOvcCustomDateEdit.PopupClose(Sender : TObject);
begin
if not FCalendar.Visible then
{already closed, exit}
Exit;
if PopupClosing then
Exit;
{avoid recursion}
PopupClosing := True;
try
inherited PopupClose(Sender);
if GetCapture = FCalendar.Handle then
ReleaseCapture;
SetFocus;
{hide the Calendar}
FCalendar.Hide;
if FCalendar.Parent is TForm then
TForm(FCalendar.Parent).AutoScroll := WasAutoScroll;
Cursor := HoldCursor;
{change parentage so that we control the window handle destruction}
FCalendar.Parent := Self;
finally
PopupClosing := False;
end;
end;
procedure TOvcCustomDateEdit.PopupKeyDown(Sender : TObject; var Key : Word; Shift : TShiftState);
var
X : Integer;
begin
case Key of
VK_TAB :
begin
if Shift = [ssShift] then begin
PopupClose(Sender);
PostMessage(Handle, WM_KeyDown, VK_TAB, Integer(ssShift));
end else if Shift = [] then begin
PopupClose(Sender);
PostMessage(Handle, WM_KeyDown, VK_TAB, 0);
end;
end;
VK_UP :
begin
if Shift = [ssAlt] then begin
PopupClose(Sender);
X := SelStart;
SetFocus;
SelStart := X;
SelLength := 0;
end;
end;
end;
end;
procedure TOvcCustomDateEdit.PopupKeyPress(Sender : TObject; var Key : Char);
var
X : Integer;
begin
case Key of
#13,
#32,
#27 :
begin
PopupClose(Sender);
X := SelStart;
SetFocus;
SelStart := X;
SelLength := 0;
end;
end;
end;
procedure TOvcCustomDateEdit.PopupMouseDown(Sender : TObject; Button : TMouseButton; Shift : TShiftState; X, Y : Integer);
var
P : TPoint;
I : Integer;
begin
P := Point(X,Y);
if not PtInRect(FCalendar.ClientRect, P) then
PopUpClose(Sender);
{convert to our coordinate system}
P := ScreenToClient(FCalendar.ClientToScreen(P));
if PtInRect(ClientRect, P) then begin
I := SelStart;
SetFocus;
SelStart := I;
SelLength := 0;
end;
end;
procedure TOvcCustomDateEdit.PopupOpen;
var
P : TPoint;
R : TRect;
{$IFDEF VERSION4}
{$IFNDEF LCL}
F : TCustomForm;
MonInfo : TMonitorInfo;
{$ENDIF}
{$ENDIF}
begin
if FCalendar.Visible then
{already popped up, exit}
Exit;
inherited PopupOpen;
{force update of date}
DoExit;
FCalendar.Parent := GetParentForm(Self);
if FCalendar.Parent is TForm then begin
WasAutoScroll := TForm(FCalendar.Parent).AutoScroll;
TForm(FCalendar.Parent).AutoScroll := False;
end;
{set 3d to be the same as our own}
{$IFNDEF LCL}
FCalendar.ParentCtl3D := False;
{$ENDIF}
FCalendar.Ctl3D := False;
{determine the proper position}
SystemParametersInfo(SPI_GETWORKAREA, 0, @R, 0);
{$IFDEF VERSION4}
{$IFNDEF LCL}
F := GetParentForm(Self);
if Assigned(F) then begin
FillChar(MonInfo, SizeOf(MonInfo), #0);
MonInfo.cbSize := SizeOf(MonInfo);
GetMonitorInfo(F.Monitor.Handle, @MonInfo);
R := MonInfo.rcWork;
end;
{$ENDIF}
{$ENDIF}
if FPopupAnchor = paLeft then
P := ClientToScreen(Point(-3, Height-4))
else {paRight}
P := ClientToScreen(Point(Width-FCalendar.Width-1, Height-2));
if not Ctl3D then begin
Inc(P.X, 3);
Inc(P.Y, 3);
end;
if P.Y + FCalendar.Height >= R.Bottom then
P.Y := P.Y - FCalendar.Height - Height;
if P.X + FCalendar.Width >= R.Right then
P.X := R.Right - FCalendar.Width - 1;
if P.X <= R.Left then
P.X := R.Left + 1;
MoveWindow(FCalendar.Handle, P.X, P.Y, FCalendar.Width, FCalendar.Height, False);
if Text = '' then
FCalendar.Date := SysUtils.Date
else
FCalendar.Date := FDate;
HoldCursor := Cursor;
Cursor := crArrow;
FCalendar.Show;
FCalendar.SetFocus;
SetCapture(FCalendar.Handle);
end;
procedure TOvcCustomDateEdit.PopupDateChange(Sender : TObject; Date : TDateTime);
begin
{get the current value}
SetDate(FCalendar.Date);
Modified := True;
if FCalendar.Browsing then
Exit;
{hide the Calendar}
PopupClose(Sender);
SetFocus;
SelStart := Length(Text);
SelLength := 0;
end;
procedure TOvcCustomDateEdit.SetDate(Value : TDateTime);
begin
FDate := Value;
Modified := True;
if FDate = 0 then
Text := ''
else
Text := FormatDate(FDate);
if Assigned(FOnSetDate) then
FOnSetDate(Self);
end;
procedure TOvcCustomDateEdit.SetDateText(Value : string);
var
Field : Integer;
I1 : Integer;
I2 : Integer;
Error : Integer;
ThisYear : Word;
ThisMonth : Word;
ThisDay : Word;
Year : Word;
Month : Word;
Day : Word;
EpochYear : Integer;
EpochCent : Integer;
StringList : TStringList;
FieldOrder : string[3];
S : string;
begin
if Assigned(FOnPreParseDate) then
FOnPreParseDate(Self, Value);
Value := ParseDate(Value);
if Assigned(FOnGetDate) then
FOnGetDate(Self, Value);
if (Value = '') and (FRequiredFields <> []) then begin
FDate := 0;
Text := '';
Exit;
end;
if AnsiCompareText(Value, TodayString) = 0 then begin
SetDate(SysUtils.Date);
Text := FormatDate(FDate);
end else begin
DecodeDate(SysUtils.Date, ThisYear, ThisMonth, ThisDay);
Value := AnsiUpperCase(Value);
StringList := TStringList.Create;
try
{parse the string into subfields using a string list to hold the parts}
I1 := 1;
while (I1 <= Length(Value)) and not (Value[I1] in ['0'..'9', 'A'..'Z']) do
Inc(I1);
while I1 <= Length(Value) do begin
I2 := I1;
while (I2 <= Length(Value)) and (Value[I2] in ['0'..'9', 'A'..'Z']) do
Inc(I2);
StringList.Add(Copy(Value, I1, I2-I1));
while (I2 <= Length(Value)) and not (Value[I2] in ['0'..'9', 'A'..'Z']) do
Inc(I2);
I1 := I2;
end;
case DateOrder of
doMDY : FieldOrder := 'MDY';
doDMY : FieldOrder := 'DMY';
doYMD : FieldOrder := 'YMD';
end;
Year := 0;
Month := 0;
Day := 0;
Error := 0;
for Field := 1 to Length(FieldOrder) do begin
if StringList.Count > 0 then
S := StringList[0]
else
S := '';
case FieldOrder[Field] of
'M' :
begin
if (S = '') or (S[1] in ['0'..'9']) then begin
{numeric month}
try
if S = '' then
Month := 0
else
Month := StrToInt(S);
except
Month := 0;
{error converting month number}
Error := SCMonthConvertError;
end;
if not (Month in [1..12]) then
Month := 0;
end else begin
{one or more letters in month}
Month := 0;
I1 := 1;
S := Copy(S, 1, 3);
{error converting month name}
Error := SCMonthNameConvertError;
repeat
if S = AnsiUpperCase(Copy(ShortMonthNames[I1], 1, Length(S))) then begin
Month := I1;
I1 := 13;
Error := 0;
end else
Inc(I1);
until I1 = 13;
end;
if Month = 0 then begin
if rfMonth in FRequiredFields then
{month required}
Error := SCMonthRequired
else
Month := ThisMonth;
end else if StringList.Count > 0 then
StringList.Delete(0);
if Error > 0 then
Break;
end;
'Y' :
begin
try
if S = '' then
Year := 0
else
Year := StrToInt(S);
except
Year := 0;
{error converting year}
Error := SCYearConvertError;
end;
if (Epoch = 0) and (Year < 100) and (S <> '') then
{default to current century if Epoch is zero}
Year := Year + (ThisYear div 100 * 100)
else if (Epoch > 0) and (Year < 100) and (S <> '') then begin
{use epoch}
EpochYear := Epoch mod 100;
EpochCent := (Epoch div 100) * 100;
if (Year < EpochYear) then
Inc(Year,EpochCent+100)
else
Inc(Year,EpochCent);
end;
if Year = 0 then begin
if rfYear in FRequiredFields then
{year is required}
Error := SCYearRequired
else
Year := ThisYear;
end else if StringList.Count > 0 then
StringList.Delete(0);
if Error > 0 then
Break;
end;
'D' :
begin
try
if S = '' then
Day := 0
else
Day := StrToInt(S);
except
Day := 0;
{error converting day}
Error := SCDayConvertError;
end;
if not (Day in [1..31]) then
Day := 0;
if Day = 0 then begin
if rfDay in FRequiredFields then
{day is required}
Error := SCDayRequired
else
Day := ThisDay;
end
else if StringList.Count > 0 then
StringList.Delete(0);
if Error > 0 then
Break;
end;
end;
end;
case Error of
SCDayConvertError :
if S = '' then
raise EOvcException.Create(
GetOrphStr(SCInvalidDay) + ' "' + Value + '"')
else
raise EOvcException.Create(
GetOrphStr(SCInvalidDay) + ' "' + S + '"');
SCMonthConvertError :
if S = '' then
raise EOvcException.Create(
GetOrphStr(SCInvalidMonth) + ' "' + Value + '"')
else
raise EOvcException.Create(
GetOrphStr(SCInvalidMonth) + ' "' + S + '"');
SCMonthNameConvertError :
if S = '' then
raise EOvcException.Create(
GetOrphStr(SCInvalidMonthName) + ' "' + Value + '"')
else
raise EOvcException.Create(
GetOrphStr(SCInvalidMonthName) + ' "' + S + '"');
SCYearConvertError :
if S = '' then
raise EOvcException.Create(
GetOrphStr(SCInvalidYear) + ' "' + Value + '"')
else
raise EOvcException.Create(
GetOrphStr(SCInvalidYear) + ' "' + S + '"');
SCDayRequired :
raise EOvcException.Create(
GetOrphStr(SCDayRequired));
SCMonthRequired :
raise EOvcException.Create(
GetOrphStr(SCMonthRequired));
SCYearRequired :
raise EOvcException.Create(
GetOrphStr(SCYearRequired));
end;
try
SetDate(STDatetoDateTime(DMYToStDate(Day, Month, Year, Epoch)));
Text := FormatDate(FDate);
except
raise EOvcException.Create(
GetOrphStr(SCInvalidDate) + ' "' + Value + '"');
end;
finally
StringList.Free;
end;
end;
end;
procedure TOvcCustomDateEdit.SetEpoch(Value : Integer);
begin
if Value <> FEpoch then
if (Value = 0) or ((Value >= MinYear) and (Value <= MaxYear)) then
FEpoch := Value;
end;
procedure TOvcCustomDateEdit.SetForceCentury(Value : Boolean);
begin
if Value <> FForceCentury then begin
FForceCentury := Value;
SetDate(FCalendar.Date);
end;
end;
procedure TOvcCustomDateEdit.SetPopupColors(Value : TOvcCalColors);
begin
FCalendar.Colors := Value;
end;
procedure TOvcCustomDateEdit.SetPopupDateFormat(Value : TOvcDateFormat);
begin
FCalendar.DateFormat := Value;
end;
procedure TOvcCustomDateEdit.SetPopupFont(Value : TFont);
begin
if Assigned(Value) then
FCalendar.Font.Assign(Value);
end;
procedure TOvcCustomDateEdit.SetPopupHeight(Value : Integer);
begin
FCalendar.Height := Value;
end;
procedure TOvcCustomDateEdit.SetPopupDayNameWidth(Value : TOvcDayNameWidth);
begin
FCalendar.DayNameWidth := Value;
end;
procedure TOvcCustomDateEdit.SetPopupOptions(Value : TOvcCalDisplayOptions);
begin
FCalendar.Options := Value;
end;
procedure TOvcCustomDateEdit.SetPopupWidth(Value : Integer);
begin
FCalendar.Width := Value;
end;
procedure TOvcCustomDateEdit.SetPopupWeekStarts(Value : TOvcDayType);
begin
FCalendar.WeekStarts := Value;
end;
procedure TOvcCustomDateEdit.SetReadOnly(Value : Boolean);
begin
inherited ReadOnly := Value;
FButton.Enabled := not ReadOnly;
end;
end.