?? hxcalendar.pas
字號:
{******************************************************************************}
{ @UnitName : hxCalendar }
{ @Project : dclusr }
{ @Copyright : k }
{ @Author : D2000 }
{ @CreateDate : 2004-04-05 19:23:10 }
{ @LastUpdate : 2004-04-23 18:58:59 by D2000 }
{ @Description : }
{ @Comment : }
{ @History : }
{******************************************************************************}
unit hxCalendar;
interface
uses Classes, Controls, Messages, Windows, Forms, Graphics, StdCtrls,
Grids, SysUtils,DateUtils;
type
TDayOfWeek = 0..6;
TDroppedCell = procedure(Sender: TObject; ACol, ARow: LongInt;
var Value: string) of object;
TCellDragOver = procedure(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean) of object;
TCalendarStrings = array[0..6, 0..6] of TStringList;
THzDate = record //農歷日期
Year: integer;
Month: integer;
Day: integer;
isLeap: Boolean; //閏月
end;
TGzDate = record //干支日期
Year: integer;
Month: integer;
Day: integer;
end;
ThxCalendar = class(TCustomGrid)
private
FDate: TDate;
FViewDate: TDate;
//FCalColors: TLssCalColors;
FYear: word;
FMonth: word;
FDay: word;
FCalStrings: TCalendarStrings;
FOnDroppedCell: TDroppedCell;
FOnCellDragOver: TCellDragOver;
FMonthOffset: Integer;
FOnChange: TNotifyEvent;
FReadOnly: Boolean;
FStartOfWeek: TDayOfWeek;
FUpdating: Boolean;
FUseCurrentDate: Boolean;
function GetCellText(ACol, ARow: Integer): string;
function GetDateElement(Index: Integer): Integer;
procedure SetCalendarDate(Value: TDate);
procedure SetDateElement(Index: Integer; Value: Integer);
procedure SetStartOfWeek(Value: TDayOfWeek);
procedure SetUseCurrentDate(Value: Boolean);
function StoreCalendarDate: Boolean;
procedure SetCellString(ACol, ARow, ADay: Integer; Value: string); virtual;
protected
{ Protected declarations }
procedure AcceptDropped(Sender, Source: TObject; X, Y: integer);
procedure CellDragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
procedure Change; dynamic;
procedure ChangeMonth(Delta: Integer);
procedure Click; override;
function DaysPerMonth(AYear, AMonth: Integer): Integer; virtual;
function DaysThisMonth: Integer; virtual;
procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState); override;
function IsLeapYear(AYear: Integer): Boolean; virtual;
function SelectCell(ACol, ARow: Longint): Boolean; override;
procedure WMSize(var Message: TWMSize); message WM_SIZE;
public
constructor Create(AOwner: TComponent); override;
//返回農歷 y年的總天數
function DaysOfLunarYear(y: integer): integer;
//返回農歷 y年閏月的天數
function daysofleapMonth(y: integer): integer;
//返回農歷 y年閏哪個月 1-12 , 沒閏返回 0
function leapMonth(y: integer): integer;
//返回農歷 y年m月的總天數
function Daysofmonth(y, m: integer): integer;
//算出農歷, 傳入公歷日期, 返回農歷日期
function ToLunar(TheDate: TDate): THzDate;
//傳入 offset 返回干支, 0=甲子
function cyclical(num: integer): string;
//算出公歷, 傳入農歷日期控件, 返回公歷
function ToGreg(objDate: THzDate): TDate;
//檢查農歷日期是否合法
function ChkHzDate(objDate: THzDate): Boolean;
//某年的第n個節氣為幾日(從0小寒起算)
function sTerm(y, n: integer): TDateTime;
//求年柱,月柱,日柱(年,月為農歷數字,TheDate為當天的公歷日期)
function GetGZ(y, m: integer; TheDate: TDate): TGzDate;
//取漢字日期
function FormatLunarDay(day:integer): string;
//漢字月份
function FormatLunarMonth(month:integer;isLeap:boolean): string;
//漢字年份
function FormatLunarYear(year:integer): string;
// 取得指定日期的節氣
function GetJQ(TheDate: TDate): string;
// 取得新歷節日
function GetsFtv(TheDate: TDate): string;
// 取得農歷節日
function GetlFtv(TheDate: ThzDate): string;
property CalendarDate: TDate read FDate write SetCalendarDate stored StoreCalendarDate;
procedure MouseToCell(X, Y: Integer; var ACol, ARow: Longint);
property CellText[ACol, ARow: Integer]: string read GetCellText;
procedure NextMonth;
procedure NextYear;
procedure PrevMonth;
procedure PrevYear;
procedure UpdateCalendar; virtual;
published
property Align;
property Anchors;
property BorderStyle;
property Color;
property Constraints;
property Ctl3D;
property Day: Integer index 3 read GetDateElement write SetDateElement stored False;
property DragCursor;
property DragKind;
property DragMode;
property Enabled;
property Font;
property GridLineWidth;
property Month: Integer index 2 read GetDateElement write SetDateElement stored False;
property ParentColor;
property ParentFont;
property ParentShowHint;
property PopupMenu;
property ReadOnly: Boolean read FReadOnly write FReadOnly default False;
property ShowHint;
property StartOfWeek: TDayOfWeek read FStartOfWeek write SetStartOfWeek;
property TabOrder;
property TabStop;
property UseCurrentDate: Boolean read FUseCurrentDate write SetUseCurrentDate default True;
property Visible;
property Year: Integer index 1 read GetDateElement write SetDateElement stored False;
property OnClick;
property OnChange: TNotifyEvent read FOnChange write FOnChange;
property OnDblClick;
property OnDragDrop;
property OnDragOver;
property OnEndDock;
property OnEndDrag;
property OnEnter;
property OnExit;
property OnKeyDown;
property OnKeyPress;
property OnKeyUp;
property OnStartDock;
property OnStartDrag;
property OnMouseDown;
property OnMouseMove;
property OnMouseUp;
end;
const
lunarInfo: array[0..200] of WORD =(
$4bd8,$4ae0,$a570,$54d5,$d260,$d950,$5554,$56af,$9ad0,$55d2,
$4ae0,$a5b6,$a4d0,$d250,$d295,$b54f,$d6a0,$ada2,$95b0,$4977,
$497f,$a4b0,$b4b5,$6a50,$6d40,$ab54,$2b6f,$9570,$52f2,$4970,
$6566,$d4a0,$ea50,$6a95,$5adf,$2b60,$86e3,$92ef,$c8d7,$c95f,
$d4a0,$d8a6,$b55f,$56a0,$a5b4,$25df,$92d0,$d2b2,$a950,$b557,
$6ca0,$b550,$5355,$4daf,$a5b0,$4573,$52bf,$a9a8,$e950,$6aa0,
$aea6,$ab50,$4b60,$aae4,$a570,$5260,$f263,$d950,$5b57,$56a0,
$96d0,$4dd5,$4ad0,$a4d0,$d4d4,$d250,$d558,$b540,$b6a0,$95a6,
$95bf,$49b0,$a974,$a4b0,$b27a,$6a50,$6d40,$af46,$ab60,$9570,
$4af5,$4970,$64b0,$74a3,$ea50,$6b58,$5ac0,$ab60,$96d5,$92e0, //1999
$c960,$d954,$d4a0,$da50,$7552,$56a0,$abb7,$25d0,$92d0,$cab5,
$a950,$b4a0,$baa4,$ad50,$55d9,$4ba0,$a5b0,$5176,$52bf,$a930,
$7954,$6aa0,$ad50,$5b52,$4b60,$a6e6,$a4e0,$d260,$ea65,$d530,
$5aa0,$76a3,$96d0,$4afb,$4ad0,$a4d0,$d0b6,$d25f,$d520,$dd45,
$b5a0,$56d0,$55b2,$49b0,$a577,$a4b0,$aa50,$b255,$6d2f,$ada0,
$4b63,$937f,$49f8,$4970,$64b0,$68a6,$ea5f,$6b20,$a6c4,$aaef,
$92e0,$d2e3,$c960,$d557,$d4a0,$da50,$5d55,$56a0,$a6d0,$55d4,
$52d0,$a9b8,$a950,$b4a0,$b6a6,$ad50,$55a0,$aba4,$a5b0,$52b0,
$b273,$6930,$7337,$6aa0,$ad50,$4b55,$4b6f,$a570,$54e4,$d260,
$e968,$d520,$daa0,$6aa6,$56df,$4ae0,$a9d4,$a4d0,$d150,$f252,
$d520);
Gan: array[0..9] of string[2] =
('甲','乙','丙','丁','戊','己','庚','辛','壬','癸');
Zhi: array[0..11] of string[2] =
('子','丑','寅','卯','辰','巳','午','未','申','酉','戌','亥');
Animals: Array[0..11] of string[2] =
('鼠','牛','虎','兔','龍','蛇','馬','羊','猴','雞','狗','豬');
solarTerm: Array[0..23] of string[4] =
('小寒','大寒','立春','雨水','驚蟄','春分','清明','谷雨'
,'立夏','小滿','芒種','夏至','小暑','大暑','立秋','處暑'
,'白露','秋分','寒露','霜降','立冬','小雪','大雪','冬至');
sTermInfo: Array[0..23] of integer =
(0,21208,42467,63836,85337,107014,128867,150921
,173149,195551,218072,240693,263343,285989,308563,331033
,353350,375494,397447,419210,440795,462224,483532,504758);
nStr1: array[0..10] of string[2] =
('日','一','二','三','四','五','六','七','八','九','十');
nStr2: Array[0..3] of string[2] = ('初','十','廿','卅');
sFtv : Array[0..22] of string =('0101*元旦','0214 情人節','0308 婦女節'
,'0312 植樹節','0315 消費者權益日','0401 愚人節','0501 勞動節','0504 青年節'
,'0512 護士節','0601 兒童節','0701 建黨節 香港回歸紀念'
,'0801 建軍節','0808 父親節','0909 毛澤東逝世紀念','0910 教師節'
,'0928 孔子誕辰','1001*國慶節','1006 老人節','1024 聯合國日','1112 孫中山誕辰紀念'
,'1220 澳門回歸紀念','1225 Christmas Day','1226 毛澤東誕辰紀念');
lFtv:Array[0..9] of string =('0101*春節','0115 元宵節','0505 端午節'
,'0707 七夕情人節','0715 中元節','0815 中秋節','0909 重陽節','1208 臘八節','1224 小年','0100*除夕');
procedure Register;
implementation
//uses ds1,u7;
procedure Register;
begin
RegisterComponents('Samples', [ThxCalendar]);
end;
constructor ThxCalendar.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
{ defaults }
FUseCurrentDate := True;
FixedCols := 0;
FixedRows := 1;
ColCount := 7;
RowCount := 7;
ScrollBars := ssNone;
Options := Options - [goRangeSelect] + [goDrawFocusSelected];
FDate := Date;
UpdateCalendar;
end;
procedure ThxCalendar.Change;
begin
if Assigned(FOnChange) then FOnChange(Self);
end;
procedure ThxCalendar.MouseToCell(X, Y: Integer; var ACol, ARow: Longint);
var
Coord: TGridCoord;
begin
Coord := MouseCoord(X, Y);
ACol := Coord.X;
ARow := Coord.Y;
end;
{ AcceptDropped override }
procedure ThxCalendar.AcceptDropped(Sender, Source: TObject; X, Y: integer);
var
ACol, ARow: LongInt;
Value: string;
begin
{ convert X and Y to Col and Row for convenience }
MouseToCell(X, Y, ACol, ARow);
{ let user respond to event }
if Assigned(FOnDroppedCell) then FOnDroppedCell(Source, ACol, ARow, Value);
{ if user returns a string add it to the cells list }
if Value <> '' then SetCellString(ACol, ARow, 0, Value);
{ set focus to hxCalendar }
SetFocus;
{ force redraw }
Invalidate;
end;
{ CellDragOver override }
procedure ThxCalendar.CellDragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
var
ACol, ARow: LongInt;
begin
{ convert X and Y to Col and Row for convenience }
MouseToCell(X, Y, ACol, ARow);
{ allow user to set Accept the way they want }
if Assigned(FOnCellDragOver) then FOnCellDragOver(Sender, Source, ACol, ARow, State, Accept);
{ if Accept = true then apply further logic else leave Accept = false }
if Accept = true then
if (not FUpdating) and (not FReadOnly) and (CellText[ACol, ARow] <> '') then
Accept := true
else Accept := false;
end;
{ SetCellString - adds a string to the cells stringlist based on Col
or Row or Day of month. }
procedure ThxCalendar.SetCellString(ACol, ARow, ADay: Integer; Value: string);
var
i, j: integer;
TheCellText: string;
begin
if (not FUpdating) and (not FReadOnly) and (CellText[ACol, ARow] <> '') then
begin
{ if ADay is being used calc ACol and ARow. Doesn't matter if
ACol and ARow are <> 0 we just calc them anyway }
if ADay <> 0 then
begin
for i := 0 to 6 do
for j := 1 to 6 do
begin
TheCellText := CellText[i, j];
if (TheCellText <> '') and (ADay = StrToInt(TheCellText)) then
begin
ACol := i;
ARow := j;
end;
end;
end;
{ if no StringList assigned then create one }
if FCalStrings[ACol, ARow] = nil then
FCalStrings[ACol, ARow] := TStringList.Create;
{ add the line of text }
FCalStrings[ACol, ARow].Add(Value);
end;
end;
procedure ThxCalendar.Click;
var
TheCellText: string;
begin
inherited Click;
TheCellText := CellText[Col, Row];
if TheCellText <> '' then Day := StrToInt(TheCellText);
end;
function ThxCalendar.IsLeapYear(AYear: Integer): Boolean;
begin
Result := (AYear mod 4 = 0) and ((AYear mod 100 <> 0) or (AYear mod 400 = 0));
end;
function ThxCalendar.DaysPerMonth(AYear, AMonth: Integer): Integer;
const
DaysInMonth: array[1..12] of Integer = (31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
begin
Result := DaysInMonth[AMonth];
if (AMonth = 2) and IsLeapYear(AYear) then Inc(Result); { leap-year Feb is special }
end;
function ThxCalendar.DaysThisMonth: Integer;
begin
Result := DaysPerMonth(Year, Month);
end;
{procedure ThxCalendar.DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState);
var
TheText: string;
begin
TheText := CellText[ACol, ARow];
with ARect, Canvas do
TextRect(ARect, Left + (Right - Left - TextWidth(TheText)) div 2,
Top + (Bottom - Top - TextHeight(TheText)) div 2, TheText);
end;}
procedure ThxCalendar.DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState);
var
HzDate:THzDate;
TheText,ry,dz,hzdaystr,sf: string;
MyDate:tdate;
TitleLeft,TitleTop,AddSize:integer;
FColor:Tcolor;
begin
AddSize:=2;
FColor:=Font.Color;
TheText := CellText[ACol, ARow];
if (TheText<>'') and (ARow<>0) then
begin
MyDate := EncodeDate(year, month, strtoint(TheText));
HzDate := ToLunar(MyDate);
dz:= GetJQ(MyDate);
if dz = '' Then
if HzDate.Day = 1 then
ry:=FormatLunarMonth(HzDate.Month,HzDate.isLeap)
else
ry := FormatLunarDay(Hzdate.Day);
if GetsFtv(MyDate)<>'' then sf :=GetsFtv(MyDate);
if GetlFtv(hzDate)<>'' then sf :=sf+GetlFtv(hzDate);
end
else MyDate := 0;
with ARect, Canvas do
begin
if dz<>'' then
begin
Font.Color :=FColor; //新歷字體顏色 舊歷有節
Font.Size:=Font.Size+AddSize;
Font.Style:=Font.Style+[fsBold];
TextRect(ARect, Left +10,Top +2, TheText+sf); //舊歷有節時的 新歷顯示
Font.Size:=Font.Size-AddSize;
Font.Style:=Font.Style-[fsBold];
Font.Color :=clRed; //舊歷字體顏色 舊歷有節
TextOut(ARect.Left + Font.Size+10, ARect.Top + (Font.Size+AddSize)*2-3, dz); //舊歷節日名稱 顯示
end
else
begin
if sf<>'' then
begin
Font.Color :=FColor;
Font.Size:=Font.Size+AddSize;
Font.Style:=Font.Style+[fsBold];
TextRect(ARect, Left+2,Top+2, TheText); // +sf
Font.Size:=Font.Size-AddSize;
Font.Style:=Font.Style-[fsBold];
Font.Color :=clMaroon ; //新歷字體顏色 新歷有節氣
TextOut(ARect.Left+(Font.Size+AddSize)*2-3,ARect.Top+4, sf);
end
else
begin
if ARow=0 then
begin
Font.Style:=Font.Style-[fsBold];
Brush.Color :=$00C9C9C9; //星期 標題欄底色
TitleLeft:=(Right-Left-Font.Size*4) div 2;
TitleTop:=((Bottom-Top-Font.Size*2) div 2)+AddSize;
AddSize:=0;
end
else
begin
Font.Style:=Font.Style+[fsBold];
TitleLeft:=10;
TitleTop:=2;
end;
Font.Color :=FColor; // 新歷字體顏色 新歷沒節 星期幾標題字體色
Font.Size:=Font.Size+AddSize;
TextRect(ARect, Left+TitleLeft,Top+TitleTop, TheText+sf);
Font.Size:=Font.Size-AddSize;
Font.Style:=Font.Style-[fsBold];
end;
Font.Color :=clPurple; //舊歷字顏色 舊歷沒節
TextOut(ARect.Left + Font.Size+10, ARect.Top + (Font.Size+AddSize)*2-3, ry);
end;
end;
end;
function ThxCalendar.GetCellText(ACol, ARow: Integer): string;
var
DayNum: Integer;
begin
if ARow = 0 then { day names at tops of columns }
Result := ShortDayNames[(StartOfWeek + ACol) mod 7 + 1]
else
begin
DayNum := FMonthOffset + ACol + (ARow - 1) * 7;
if (DayNum < 1) or (DayNum > DaysThisMonth) then Result := ''
else Result := IntToStr(DayNum);
end;
end;
function ThxCalendar.SelectCell(ACol, ARow: Longint): Boolean;
begin
if ((not FUpdating) and FReadOnly) or (CellText[ACol, ARow] = '') then
Result := False
else Result := inherited SelectCell(ACol, ARow);
end;
procedure ThxCalendar.SetCalendarDate(Value: TDate);
begin
FDate := Value;
UpdateCalendar;
Change;
end;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -