1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
|
{ $Id: calendarpopup.pas 52144 2016-04-07 13:13:15Z bart $}
{
*****************************************************************************
This file is part of the Lazarus Component Library (LCL)
See the file COPYING.modifiedLGPL.txt, included in this distribution,
for details about the license.
*****************************************************************************
Author: Vincent Snijders
Abstract:
Shows a non-modal calendar popup for a TDateEdit
}
unit CalendarPopup;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, Calendar, LCLProc, LCLType;
type
TReturnDateEvent = procedure (Sender: TObject; const Date: TDateTime) of object;
{ TCalendarPopupForm }
TCalendarPopupForm = class(TForm)
Calendar: TCalendar;
procedure CalendarDblClick(Sender: TObject);
procedure CalendarKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
procedure FormCreate(Sender: TObject);
procedure FormDeactivate(Sender: TObject);
private
FCaller: TControl;
FClosed: boolean;
FOnReturnDate: TReturnDateEvent;
procedure Initialize(ADate: TDateTime;
const DisplaySettings: TDisplaySettings);
procedure KeepInView(const PopupOrigin: TPoint);
procedure ReturnDate;
protected
procedure Paint; override;
end;
procedure ShowCalendarPopup(const APosition: TPoint; ADate: TDateTime;
const CalendarDisplaySettings: TDisplaySettings;
const OnReturnDate: TReturnDateEvent; const OnShowHide: TNotifyEvent = nil;
ACaller: TControl = nil);
implementation
{$R *.lfm}
procedure ShowCalendarPopup(const APosition: TPoint; ADate: TDateTime;
const CalendarDisplaySettings: TDisplaySettings;
const OnReturnDate: TReturnDateEvent; const OnShowHide: TNotifyEvent;
ACaller: TControl);
var
PopupForm: TCalendarPopupForm;
begin
PopupForm := TCalendarPopupForm.Create(nil);
PopupForm.FCaller := ACaller;
PopupForm.Initialize(ADate, CalendarDisplaySettings);
PopupForm.FOnReturnDate := OnReturnDate;
PopupForm.OnShow := OnShowHide;
PopupForm.OnHide := OnShowHide;
PopupForm.Show;
PopupForm.KeepInView(APosition); // must be after Show for PopupForm.AutoSize to be in effect.
end;
{ TCalendarPopupForm }
procedure TCalendarPopupForm.FormCreate(Sender: TObject);
begin
FClosed := false;
Application.AddOnDeactivateHandler(@FormDeactivate);
end;
procedure TCalendarPopupForm.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
//DebugLn(['TCalendarPopupForm.FormClose ']);
FClosed := true;
Application.RemoveOnDeactivateHandler(@FormDeactivate);
CloseAction := caFree;
end;
procedure TCalendarPopupForm.CalendarDblClick(Sender: TObject);
var
P: TPoint;
htRes: TCalendarPart;
begin
P := Calendar.ScreenToClient(Mouse.CursorPos);
htRes := Calendar.HitTest(P);
if {(htRes = cpNoWhere) or }((htRes = cpDate) and (Calendar.GetCalendarView = cvMonth)) then
ReturnDate;
end;
procedure TCalendarPopupForm.CalendarKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
var
Handled: Boolean;
begin
if Shift=[] then
begin
Handled := true;
case Key of
VK_ESCAPE:
Close;
VK_RETURN, VK_SPACE:
if (Calendar.GetCalendarView = cvMonth) then
ReturnDate
else
Handled := False;
else
Handled := false;
end;
if Handled then
Key := 0;
end;
end;
procedure TCalendarPopupForm.FormDeactivate(Sender: TObject);
begin
//DebugLn(['TCalendarPopupForm.FormDeactivate ',DbgSName(GetCaptureControl)]);
//Immediately hide the form, otherwise it stays visible while e.g. user is draging
//another form (Issue #0020647)
Hide;
if (not FClosed) then
Close;
end;
procedure TCalendarPopupForm.Initialize(ADate: TDateTime;
const DisplaySettings: TDisplaySettings);
begin
Calendar.DateTime := ADate;
Calendar.DisplaySettings:=DisplaySettings;
end;
procedure TCalendarPopupForm.KeepInView(const PopupOrigin: TPoint);
var
ABounds: TRect;
P: TPoint;
begin
ABounds := Screen.MonitorFromPoint(PopupOrigin).WorkAreaRect; // take care of taskbar
if PopupOrigin.X + Width > ABounds.Right then
Left := ABounds.Right - Width
else if PopupOrigin.X < ABounds.Left then
Left := ABounds.Left
else
Left := PopupOrigin.X;
if PopupOrigin.Y + Height > ABounds.Bottom then
begin
if Assigned(FCaller) then
Top := PopupOrigin.Y - FCaller.Height - Height
else
Top := ABounds.Bottom - Height;
end else if PopupOrigin.Y < ABounds.Top then
Top := ABounds.Top
else
Top := PopupOrigin.Y;
if Left < ABounds.Left then Left := 0;
if Top < ABounds.Top then Top := 0;
end;
procedure TCalendarPopupForm.ReturnDate;
begin
if Assigned(FOnReturnDate) then
FOnReturnDate(Self, Calendar.DateTime);
if not FClosed then
Close;
end;
procedure TCalendarPopupForm.Paint;
begin
inherited Paint;
Canvas.Pen.Color := clWindowText;
Canvas.Pen.Style := psSolid;
Canvas.Rectangle(0, 0, Width, Height);
end;
end.
|