| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025 |
- {******************************************************************************}
- { CnPack For Delphi/C++Builder }
- { 中国人自己的开放源码第三方开发包 }
- { (C)Copyright 2001-2018 CnPack 开发组 }
- { ------------------------------------ }
- { }
- { 本开发包是开源的自由软件,您可以遵照 CnPack 的发布协议来修 }
- { 改和重新发布这一程序。 }
- { }
- { 发布这一开发包的目的是希望它有用,但没有任何担保。甚至没有 }
- { 适合特定目的而隐含的担保。更详细的情况请参阅 CnPack 发布协议。 }
- { }
- { 您应该已经和开发包一起收到一份 CnPack 发布协议的副本。如果 }
- { 还没有,可访问我们的网站: }
- { }
- { 网站地址:http://www.cnpack.org }
- { 电子邮件:master@cnpack.org }
- { }
- {******************************************************************************}
- unit CnMonthCalendar;
- {* |<PRE>
- ================================================================================
- * 软件名称:CnPack 组件包界面组件库
- * 单元名称:中国月历组件,能显示农历与干支
- * 单元作者:匿名、不夜人
- * 备 注:字体尺寸随组件尺寸变化而变化
- * 开发平台:PWinXP SP2 + Delphi 2006
- * 兼容测试:PWin9X/2000/XP + Delphi 5/6
- * 本 地 化:该单元中的字符串均符合本地化处理方式
- * 单元标识:$Id$
- * 修改记录:2010.11.08 V1.2
- * 修正1582年10月显示不正确的问题
- * 2009.04.26 V1.1
- * 不夜人加入几种颜色以及前进后退年月的按钮,刘啸修改
- * 2008.06.05 V1.0
- * 移植单元
- ================================================================================
- |</PRE>}
- interface
- {$I CnPack.inc}
- uses
- SysUtils, Classes, Controls, Graphics, Windows, Messages,
- StdCtrls, CnCalendar;
-
- type
- TCnLunarDate = record //农历日期
- Year: Integer;
- Month: Integer;
- Day: Integer;
- IsLeap: Boolean; //闰月
- end;
- TCnGanZhiDate = record //干支日期
- Year: Integer;
- Month: Integer;
- Day: Integer;
- end;
- TCnMonthCalendar = class;
- TCnCalStyle = (csBottom, csRight, csNone);
- TCnCalColors = class(TPersistent)
- private
- Owner: TCnMonthCalendar;
- FBackColor: TColor;
- FTextColor: TColor;
- FTitleBackColor: TColor;
- FTitleTextColor: TColor;
- FTrailingTextColor: TColor;
- FSundayColor: TColor;
- FSaturdayColor: TColor;
- FWeekTextColor: TColor; //增加星期的字体颜色属性
- FDaySelectColor: TColor; //增加选择日期颜色属性
- FDaySelectTextColor: TColor; //增加选择日期字体颜色属性
- procedure SetColor(Index: Integer; Value: TColor);
- public
- constructor Create(AOwner: TCnMonthCalendar);
- procedure Assign(Source: TPersistent); override;
- published
- property BackColor: TColor index 0 read FBackColor write SetColor default clWindow;
- property TextColor: TColor index 1 read FTextColor write SetColor default clWindowText;
- property TitleBackColor: TColor index 2 read FTitleBackColor write SetColor default clActiveCaption;
- property TitleTextColor: TColor index 3 read FTitleTextColor write SetColor default clWhite;
- property TrailingTextColor: TColor index 4 read FTrailingTextColor write SetColor default clInactiveCaptionText;
- property SundayColor: TColor index 5 read FSundayColor write SetColor default clRed;
- property SaturdayColor: TColor index 6 read FSaturdayColor write SetColor default clMaroon;
- property WeekTextColor: TColor index 7 read FWeekTextColor write SetColor default clActiveCaption;
- //自己增加星期的字体颜色属性
- property DaySelectColor: TColor index 8 read FDaySelectColor write SetColor default clActiveCaption;
- //自己增加日期选择颜色属性
- property DaySelectTextColor: TColor index 9 read FDaySelectTextColor write SetColor default clWindowText;
- //自己增加日期选择字体颜色属性
- end;
- TCnMonthCalendar = class(TCustomControl)
- private
- FDate: TDate; //月历当前指向的日期
- FViewDate: TDate;
- FCalColors: TCnCalColors;
- FYear: word;
- FMonth: word;
- FDay: word;
- FFirstDate: TDate; //月历第一格日期
- FTitleRect: TRect; //标题区
- FWeekRect: TRect; //星期区
- FDaysRect: TRect; //日期区
- FOldRect: TRect;
- FNeedUpdate: Boolean;
- FCellWidth: Integer;
- FCellHeight: Integer;
- FShowGanZhi: Boolean; //是否使用干支记日
- FCalStyle: TCnCalStyle;
- FTitleTextSize: Integer;
- FWeekTextSize: Integer;
- FDaySize: Integer;
- FLunarDaySize: Integer;
- FOnChange: TNotifyEvent;
- lblPrevMonth: TLabel; //增加的动态建立一个Label
- lblNextMonth: TLabel; //增加的动态建立一个Label
- lblPrevYear: TLabel; //增加的动态建立一个Label
- lblNextYear: TLabel; //增加的动态建立一个Label
- LBTextSize: Integer;
- FShowMonthButton: Boolean;
- FShowYearButton: Boolean; //增加的动态建立一个label字体尺寸
- procedure CalcRect; //计算各区以及字体大小
- function CalcDayRect(ADate: TDate): TRect;
- procedure GetFirstDay;
- function GetMaxTextSize(S: string; W, H: Integer): Integer;
- procedure UpdateHighlight(X, Y: Integer);
- procedure SetDate(Value: TDate);
- procedure SetCalColors(Value: TCnCalColors);
- procedure SetCalStyle(Value: TCnCalStyle);
- procedure SetShowGanZhi(Value: Boolean);
- procedure PrevMonthClick(Sender: TObject); //增加的label单击事件
- procedure NextMonthClick(Sender: TObject);
- procedure PrevYearClick(Sender: TObject); //增加的label单击事件
- procedure NextYearClick(Sender: TObject);
- procedure SetShowMonthButton(const Value: Boolean);
- procedure SetShowYearButton(const Value: Boolean); //增加的label单击事件
- protected
- { Protected declarations }
- procedure CreateWnd; override;
- procedure Paint; override;
- procedure Resize; override;
- procedure KeyDown(var Key: word; Shift: TShiftState); override;
- procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
- procedure MouseMove(Shift: TShiftState; X, Y: Integer); override;
- procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer); override;
- procedure DoEnter; override;
- procedure DoExit; override;
- procedure CMWantSpecialKey(var Message: TCMWantSpecialKey); message CM_WANTSPECIALKEY;
- procedure Changed; dynamic;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
- //算出农历, 传入公历日期, 返回农历日期
- function ToLunar(TheDate: TDate): TCnLunarDate;
- //求年柱,月柱,日柱TheDate为当天的公历日期)
- function GetGanZhi(TheDate: TDate): TCnGanZhiDate;
- //取汉字日期
- function FormatLunarDay(Day: Integer): string;
- //汉字月份
- function FormatLunarMonth(Month: Integer; isLeap: Boolean): string;
- //汉字年份
- function FormatLunarYear(Year: Integer): string;
- // 取得指定日期的节气
- function GetJieQi(TheDate: TDate): string;
- property Year: word read FYear;
- property Month: word read FMonth;
- property Day: word read FDay;
- procedure PriorYear;
- procedure NextYear;
- procedure PriorMonth;
- procedure NextMonth;
- procedure PriorDay;
- procedure NextDay;
- procedure PriorWeek;
- procedure NextWeek;
- procedure FirstDayOfMonth;
- procedure LastDayOfMonth;
- published
- { Published declarations }
- property Align;
- property Anchors;
- property BevelEdges;
- property BevelInner;
- property BevelOuter;
- property BevelKind;
- property BevelWidth;
- property BorderWidth;
- property CalColors: TCnCalColors read FCalColors write SetCalColors;
- property CalStyle: TCnCalStyle read FCalStyle write SetCalStyle default csBottom;
- property ShowGanZhi: Boolean read FShowGanZhi write SetShowGanZhi default False;
- property ShowMonthButton: Boolean read FShowMonthButton write SetShowMonthButton;
- property ShowYearButton: Boolean read FShowYearButton write SetShowYearButton;
- property Cursor;
- property Date: TDate read FDate write SetDate;
- property Enabled;
- property Font;
- property OnChange: TNotifyEvent read FOnChange write FOnChange;
- property PopupMenu;
- property ShowHint;
- property TabOrder;
- property Visible;
- property OnClick;
- property OnContextPopup;
- property OnDblClick;
- property OnKeyDown;
- property OnKeyUp;
- property OnKeyPress;
- property OnMouseDown;
- property OnMouseMove;
- property OnMouseUp;
- end;
- implementation
- const
- LunarStrs: array[0..10] of string =
- ('日', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十');
- constructor TCnMonthCalendar.Create(AOwner: TComponent);
- procedure InitLabel(ALabel: TLabel);
- begin
- ALabel.Parent := Self;
- ALabel.Visible := False;
- ALabel.Left := 10;
- ALabel.Top := 20;
- ALabel.Transparent := True;
- ALabel.Font.Size := 12;
- ALabel.Font.Style := [fsBold];
- end;
- begin
- inherited;
- DoubleBuffered := True;
- ControlStyle := (ControlStyle - [csAcceptsControls, csNoStdEvents, csSetCaption]) + [csReflector];
- FDate := SysUtils.Date;
- FViewDate := FDate;
- FCalColors := TCnCalColors.Create(self);
- GetFirstDay;
- Width := 360;
- Height := 240;
- Font.Name := '宋体';
- Font.Charset := GB2312_CHARSET;
- Font.Size := 9;
- TabStop := True;
- Color := FCalColors.BackColor;
- FShowGanZhi := False;
- //DoubleBuffered := False;
- lblPrevMonth := TLabel.Create(Self);
- InitLabel(lblPrevMonth);
- lblPrevMonth.Caption := '<';
- lblPrevMonth.OnClick := PrevMonthClick;
- lblNextMonth := TLabel.Create(Self);
- InitLabel(lblNextMonth);
- lblNextMonth.Caption := '>';
- lblNextMonth.OnClick := NextMonthClick;
- lblPrevYear := TLabel.Create(Self);
- InitLabel(lblPrevYear);
- lblPrevYear.Caption := '<<';
- lblPrevYear.OnClick := PrevYearClick;
- lblNextYear := TLabel.Create(Self);
- InitLabel(lblNextYear);
- lblNextYear.Caption := '>>';
- lblNextYear.OnClick := NextYearClick;
- end;
- procedure TCnMonthCalendar.PrevMonthClick(Sender: TObject);
- begin
- PriorMonth;
- end;
- procedure TCnMonthCalendar.NextMonthClick(Sender: TObject);
- begin
- NextMonth;
- end;
- destructor TCnMonthCalendar.Destroy;
- begin
- FCalColors.Free;
- lblPrevMonth.Free; //增加的释放动态建立的label
- lblNextMonth.Free; //增加的释放动态建立的label
- lblPrevYear.Free;
- lblNextYear.Free;
- inherited Destroy;
- end;
- procedure TCnMonthCalendar.CreateWnd;
- begin
- inherited;
- CalcRect;
- Color := FCalColors.BackColor;
- end;
- procedure TCnMonthCalendar.Paint;
- var
- OutputStr: string;
- Col, I, Skip: Integer;
- TempDate: TDate;
- R, DR: TRect;
- Y, M, D: word;
- GzDate: TCnGanZhiDate;
- procedure DrawString(const S: string; Bounds: TRect; Flag: Cardinal);
- var
- TextSize: TSize;
- StartPos: TPoint;
- begin
- TextSize := Canvas.TextExtent(S);
- StartPos := Bounds.TopLeft;
- with StartPos, Bounds, TextSize do
- begin
- if (DT_CENTER and Flag) = DT_CENTER then X := X + (Right - Left - cx) div 2
- else if (DT_RIGHT and Flag) = DT_RIGHT then X := X + (Right - Left - cx);
- if (DT_VCENTER and Flag) = DT_VCENTER then Y := Y + (Bottom - Top - cy) div 2
- else if (DT_BOTTOM and Flag) = DT_BOTTOM then Y := Y + (Bottom - Top - cy);
- Canvas.TextOut(X, Y, S);
- end;
- end;
- procedure DrawLunarDay(R: TRect; TheDate: TDate);
- var
- S, S1: string;
- LunarDate: TCnLunarDate;
- H, yy: Integer;
- begin
- S := GetJieQi(TheDate);
- if S = '' then
- if FShowGanZhi then
- begin
- GzDate := GetGanZhi(TheDate);
- S := GetGanZhiFromNumber(GzDate.Day);
- end
- else
- begin
- LunarDate := ToLunar(TheDate);
- if LunarDate.Day = 0 then Exit;
- if LunarDate.Day = 1 then
- S := FormatLunarMonth(LunarDate.Month, LunarDate.isLeap)
- else
- S := FormatLunarDay(LunarDate.Day);
- end;
- Canvas.Font.Size := FLunarDaySize;
- if FCalStyle = csRight then
- begin
- H := Canvas.TextHeight(S);
- yy := R.Top + (FCellHeight div 2) - H;
- S1 := Copy(S, 1, 2);
- Canvas.TextOut(R.Left + 2, yy, S1);
- yy := yy + H;
- S1 := Copy(S, 3, 2);
- Canvas.TextOut(R.Left + 2, yy, S1);
- end
- else
- DrawString(S, R, DT_TOP or DT_CENTER);
- end;
- begin
- inherited;
- Canvas.Font.Assign(Font);
- with Canvas, FCalColors do
- begin
- // 画年月
- if ShowYearButton then
- begin
- lblPrevYear.Font.Size := LBTextSize;
- lblPrevYear.Font.Color := TitleTextColor;
- lblNextYear.Font.Size := LBTextSize;
- lblNextYear.Font.Color := TitleTextColor;
- end;
- if ShowMonthButton then
- begin
- lblPrevMonth.Font.Size := LBTextSize;
- lblPrevMonth.Font.Color := TitleTextColor;
- lblNextMonth.Font.Size := LBTextSize;
- lblNextMonth.Font.Color := TitleTextColor;
- end;
- if RectVisible(Canvas.Handle, FTitleRect) then
- begin
- Brush.Color := TitleBackColor;
- Brush.Style := bsSolid;
- FillRect(FTitleRect);
- Brush.Style := bsClear;
- Font.Color := TitleTextColor;
- Font.Size := FTitleTextSize;
- Font.Style := [fsBold];
- if FShowGanZhi then
- begin
- GzDate := GetGanZhi(FDate);
- OutputStr := GetGanZhiFromNumber(GzDate.Year) + '(' + GetShengXiaoFromNumber(GzDate.Year mod 12) +
- ')年' + GetGanZhiFromNumber(GzDate.Month) + '月';
- end
- else
- OutputStr := FormatDateTime('yyyy', FDate) + '年' + FormatDateTime('m', FDate) + '月';
- DrawString(OutputStr, FTitleRect, DT_CENTER or DT_VCENTER);
- Font.Style := [];
- end;
- //画星期
- R := Bounds(FWeekRect.Left, FWeekRect.Top, FCellWidth, FCellHeight);
- if RectVisible(Canvas.Handle, FWeekRect) then
- begin
- Font.Size := FWeekTextSize;
- Font.Color := WeekTextColor; //增加上的,改变星期头字体颜色
- for I := 0 to 6 do
- begin
- OutputStr := GetWeekFromNumber(GetWeek(FFirstDate + I));
- DrawString(OutputStr, R, DT_CENTER or DT_VCENTER);
- OffsetRect(R, FCellWidth, 0);
- end;
- Pen.Color := TitleBackColor;
- Pen.Width := 1;
- Pen.Mode := pmCopy;
- PenPos := Point(2, FWeekRect.Bottom - 2);
- LineTo(FWeekRect.Right - 2, FWeekRect.Bottom - 2);
- end;
- //画日期
- R := Bounds(FDaysRect.Left, FDaysRect.Top, FCellWidth, FCellHeight);
- Skip := 0;
- for I := 0 to 41 do
- begin
- Col := (I - Skip) mod 7;
- //if RectVisible(Canvas.Handle, R) then // NOTE: NEVER!
- TempDate := FFirstDate + I;
- DecodeDate(TempDate, Y, M, D);
- if (Y = 1582) and (M = 10) and (D in [5..14]) then
- begin
- Inc(Skip);
- Continue;
- end;
- if M = FMonth then
- if Col = 0 then
- Font.Color := SundayColor
- else if Col = 6 then
- Font.Color := SaturdayColor
- else
- Font.Color := TextColor
- else
- Font.Color := TrailingTextColor;
- if Trunc(TempDate) = Trunc(FViewDate) then //高亮显示月历日期
- begin
- Brush.Color := DaySelectColor; // 增加的颜色设置
- Font.Color := DaySelectTextColor; // 增加的颜色设置
- FillRect(R);
- FOldRect := R;
- DR := R;
- InflateRect(DR, -2, -2);
- if Focused then
- Windows.DrawFocusRect(Handle, DR);
- end
- else
- begin
- Brush.Color := Color;
- Brush.Style := bsSolid;
- FillRect(R);
- end;
- Brush.Style := bsClear;
- if TempDate = SysUtils.Date then //在当前日期画一红色框
- begin
- Pen.Color := clRed;
- Pen.Width := 1;
- Rectangle(R.Left, R.Top, R.Right, R.Bottom);
- end;
- OutputStr := IntToStr(D);
- Font.Size := FDaySize;
- if FCalStyle = csNone then
- DrawString(OutputStr, R, DT_VCENTER or DT_CENTER)
- else
- begin
- if FCalStyle = csRight then
- begin
- DR := Bounds(R.Left, R.Top, FCellWidth div 3 * 2, FCellHeight);
- DrawString(OutputStr, DR, DT_VCENTER or DT_RIGHT);
- OffsetRect(DR, FCellWidth div 3 * 2, 0);
- end
- else
- begin
- DR := Bounds(R.Left, R.Top, FCellWidth, FCellHeight div 5 * 3);
- DrawString(OutputStr, DR, DT_BOTTOM or DT_CENTER);
- DR := Bounds(DR.Left, DR.Bottom, FCellWidth, FCellHeight div 5 * 2);
- end;
- DrawLunarDay(DR, TempDate);
- end;
- if Col = 6 then
- OffsetRect(R, FDaysRect.Left - R.Left, FCellHeight)
- else
- OffsetRect(R, FCellWidth, 0);
- end; {end for}
- end; {end with}
- end;
- procedure TCnMonthCalendar.Resize;
- begin
- inherited;
- CalcRect;
- end;
- procedure TCnMonthCalendar.CalcRect;
- begin
- Canvas.Font.Assign(Font);
- FCellWidth := ClientRect.Right div 7;
- FCellHeight := ClientRect.Bottom div 8;
- FTitleRect := ClientRect;
- FTitleRect.Bottom := FCellHeight;
- FTitleTextSize := GetMaxTextSize(FormatDateTime('yyyy年mm月', FDate), FTitleRect.Right, Round((FTitleRect.Bottom - FTitleRect.Top) * 0.8));
- LBTextSize := Round(FTitleTextSize * 0.8); //增加的label字体尺寸
- FWeekTextSize := GetMaxTextSize(FormatDateTime('ddd', FDate), Round(FCellWidth * 1.2), FCellHeight); //这是修改后的字体(加大了!)
- if FCalStyle = csNone then
- FDaySize := GetMaxTextSize(FormatDateTime('dd', FDate), FCellWidth, FCellHeight)
- else begin
- if FCalStyle = csRight then
- begin
- FDaySize := GetMaxTextSize(FormatDateTime('dd', FDate), FCellWidth div 3 * 2, FCellHeight);
- FLunarDaySize := GetMaxTextSize('九', FCellWidth div 3, FCellHeight div 2);
- end
- else begin
- FDaySize := GetMaxTextSize(FormatDateTime('dd', FDate), FCellWidth, FCellHeight div 5 * 3);
- FLunarDaySize := GetMaxTextSize('九九', FCellWidth, FCellHeight div 5 * 2);
- end;
- end;
- FWeekRect := Bounds(0, FTitleRect.Bottom, FCellWidth * 7, FCellHeight);
- FDaysRect := Bounds(0, FWeekRect.Bottom, FCellWidth * 7, FCellHeight * 6);
- lblPrevMonth.Font.Size := LBTextSize;
- lblPrevMonth.Font.Color := FCalColors.TitleTextColor;
- lblPrevMonth.Left := 40;
- lblPrevMonth.Top := Round((FTitleRect.Bottom - lblPrevMonth.Height) / 2);
- lblNextMonth.Font.Size := LBTextSize;
- lblNextMonth.Font.Color := FCalColors.TitleTextColor;
- lblNextMonth.Left := FTitleRect.Right - 30 - Round(LBTextSize * 1.2);
- lblNextMonth.Top := lblPrevMonth.Top;
- lblPrevYear.Font.Size := LBTextSize;
- lblPrevYear.Font.Color := FCalColors.TitleTextColor;
- lblPrevYear.Left := 10;
- lblPrevYear.Top := Round((FTitleRect.Bottom - lblPrevYear.Height) / 2);
- lblNextYear.Font.Size := LBTextSize;
- lblNextYear.Font.Color := FCalColors.TitleTextColor;
- lblNextYear.Left := FTitleRect.Right - 10 - Round(LBTextSize * 1.2);
- lblNextYear.Top := lblPrevYear.Top;
- end;
- function TCnMonthCalendar.CalcDayRect(ADate: TDate): TRect;
- var
- DateOffset: Integer;
- col, Row: Integer;
- begin
- DateOffset := Trunc(Abs(ADate - FFirstDate));
- Row := DateOffset div 7;
- col := DateOffset mod 7;
- Result.Left := FDaysRect.Left + FCellWidth * col;
- Result.Top := FDaysRect.Top + FCellHeight * Row;
- Result.Right := Result.Left + FCellWidth;
- Result.Bottom := Result.Top + FCellHeight;
- end;
- function TCnMonthCalendar.GetMaxTextSize(S: string; W, H: Integer): Integer;
- var
- n: Integer;
- TextSize: TSize;
- begin
- for n := 5 to 72 do
- begin
- Canvas.Font.Size := n;
- TextSize := Canvas.TextExtent(S);
- if (TextSize.cx > W) or (TextSize.cy > H) then Break;
- end;
- Result := n - 1;
- end;
- procedure TCnMonthCalendar.GetFirstDay;
- var
- DayOffSet: Integer;
- begin
- DecodeDate(FDate, FYear, FMonth, FDay);
- FFirstDate := EncodeDate(FYear, FMonth, 1);
- DayOffSet := GetWeek(FFirstDate) + 1;
- if DayOffSet = 1 then DayOffSet := 8; //保证前面包含上月数据
- FFirstDate := FFirstDate + 1 - DayOffSet;
- end;
- procedure TCnMonthCalendar.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
- begin
- inherited;
- if not (csDesigning in ComponentState) then SetFocus;
- if Button = mbLeft then
- begin
- UpdateHighlight(X, Y);
- end;
- end;
- procedure TCnMonthCalendar.MouseMove(Shift: TShiftState; X, Y: Integer);
- begin
- inherited;
- if ssLeft in Shift then
- UpdateHighlight(X, Y);
- end;
- procedure TCnMonthCalendar.MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
- begin
- inherited;
- if Button = mbLeft then
- begin
- FNeedUpdate := False;
- SetDate(FViewDate);
- end;
- end;
- procedure TCnMonthCalendar.CMWantSpecialKey(var Message: TCMWantSpecialKey);
- begin
- inherited;
- if Message.CharCode in [vk_Left..vk_Down] then Message.Result := 1;
- end;
- procedure TCnMonthCalendar.KeyDown(var Key: word; Shift: TShiftState);
- var
- D, m, Y: word;
- begin
- inherited;
- if Shift = [] then
- begin
- FNeedUpdate := True;
- case Key of
- vk_Up: SetDate(FDate - 7);
- vk_Down: SetDate(FDate + 7);
- vk_Left: SetDate(FDate - 1);
- vk_Right: SetDate(FDate + 1);
- vk_Home: begin
- DecodeDate(FDate, Y, m, D);
- SetDate(EncodeDate(Y, m, 1));
- end;
- vk_End: begin
- DecodeDate(IncMonth(FDate, 1), Y, m, D);
- SetDate(EncodeDate(Y, m, 1) - 1);
- end;
- vk_Prior: SetDate(IncMonth(FDate, -1));
- vk_Next: SetDate(IncMonth(FDate, 1));
- end;
- if Key = vk_Return then
- inherited Click;
- end;
- end; {= TCnMonthCalendar.KeyDown =}
- procedure TCnMonthCalendar.UpdateHighlight(X, Y: Integer);
- var
- Col, Row: Integer;
- TempDate: TDate;
- R: TRect;
- Ye, M, D: Word;
- begin
- if PtInRect(FDaysRect, Point(X, Y)) then
- begin
- Col := X div FCellWidth;
- Row := (Y - FDaysRect.Top) div FCellHeight;
- TempDate := FFirstDate + Col + Row * 7;
- DecodeDate(TempDate, Ye, M, D);
- if (Ye = 1582) and (M = 10) and (D in [5..31]) then
- begin
- DecodeDate(FViewDate, Ye, M, D);
- if M = 10 then
- TempDate := TempDate + 10;
- end;
- if TempDate <> FViewDate then
- begin
- R := Bounds(FDaysRect.Left + FCellWidth * Col + 1,
- FDaysRect.Top + FCellHeight * Row + 1, FCellWidth - 2, FCellHeight - 2);
- FViewDate := TempDate;
- InvalidateRect(Handle, @FOldRect, False);
- InvalidateRect(Handle, @R, False);
- end;
- end;
- end;
- procedure TCnMonthCalendar.DoEnter;
- begin
- inherited;
- with Canvas, FCalColors do
- begin
- Brush.Style := bsSolid;
- Brush.Color := TitleBackColor;
- Font.Color := TitleTextColor;
- Windows.DrawFocusRect(Handle, FOldRect);
- end;
- end;
- procedure TCnMonthCalendar.DoExit;
- begin
- inherited;
- with Canvas, FCalColors do
- begin
- Brush.Style := bsSolid;
- Brush.Color := TitleBackColor;
- Font.Color := TitleTextColor;
- Windows.DrawFocusRect(Handle, FOldRect);
- end;
- end;
- procedure TCnMonthCalendar.SetCalColors(Value: TCnCalColors);
- begin
- if FCalColors <> Value then FCalColors.Assign(Value);
- end;
- procedure TCnMonthCalendar.SetCalStyle(Value: TCnCalStyle);
- begin
- if FCalStyle <> Value then
- begin
- FCalStyle := Value;
- CalcRect;
- Invalidate;
- end;
- end;
- procedure TCnMonthCalendar.SetDate(Value: TDate);
- var
- oldFirstDate: TDate;
- R: TRect;
- begin
- if (FDate <> Trunc(Value)) then
- begin
- FDate := Value;
- FViewDate := FDate;
- oldFirstDate := FFirstDate;
- GetFirstDay;
- Changed;
- FNeedUpdate := True;
- if oldFirstDate <> FFirstDate then
- begin
- InvalidateRect(Handle, @FTitleRect, False);
- InvalidateRect(Handle, @FDaysRect, False);
- end
- else if FNeedUpdate then
- begin
- InvalidateRect(Handle, @FOldRect, False);
- R := CalcDayRect(FViewDate);
- InvalidateRect(Handle, @R, False);
- end
- else if FShowGanZhi then
- begin
- InvalidateRect(Handle, @FTitleRect, False);
- end;
- end;
- end; {= TCnMonthCalendar.SetDate =}
- procedure TCnMonthCalendar.Changed;
- begin
- if Assigned(FOnChange) then
- FOnChange(self);
- end;
- //算出农历, 传入公历日期, 返回农历日期
- function TCnMonthCalendar.ToLunar(TheDate: TDate): TCnLunarDate;
- var
- Y, M, D: Word;
- begin
- DecodeDate(TheDate, Y, M, D);
- GetLunarFromDay(Y, M, D, Result.Year, Result.Month, Result.Day, Result.IsLeap);
- Result.Year := Y;
- end;
- // 求年柱,月柱,日柱, TheDate 为公历日期
- function TCnMonthCalendar.GetGanZhi(TheDate: TDate): TCnGanZhiDate;
- var
- Y, M, D: Word;
- begin
- DecodeDate(TheDate, Y, M, D);
- Result.Year := GetGanZhiFromYear(Y, M, D);
- Result.Month := GetGanZhiFromMonth(Y, M, D);
- Result.Day := GetGanZhiFromDay(Y, M, D);
- end;
- function TCnMonthCalendar.FormatLunarDay(Day: Integer): string;
- begin
- case Day of
- 1..10: Result := SCnLunarNumber2Array[0] + LunarStrs[Day];
- 11..19: Result := SCnLunarNumber2Array[1] + LunarStrs[Day - 10];
- 20: Result := LunarStrs[2] + LunarStrs[10];
- 21..29: Result := SCnLunarNumber2Array[2] + LunarStrs[Day - 20];
- 30: Result := LunarStrs[3] + LunarStrs[10];
- else Result := '';
- end;
- end;
- function TCnMonthCalendar.FormatLunarMonth(Month: Integer; isLeap: Boolean): string;
- begin
- case Month of
- 1..10: Result := LunarStrs[Month];
- 11..12: Result := LunarStrs[10] + LunarStrs[Month - 10];
- else Result := '';
- end;
- if isLeap then Result := '闰' + Result;
- Result := Result + '月';
- end;
- function TCnMonthCalendar.FormatLunarYear(Year: Integer): string;
- var
- temp: Integer;
- zero: string;
- begin
- zero := '零';
- temp := Year div 1000;
- Result := LunarStrs[temp];
- Year := Year - temp * 1000;
- if Year >= 100 then
- begin
- temp := Year div 100;
- Result := Result + LunarStrs[temp];
- Year := Year - temp * 100;
- end
- else
- Result := Result + zero;
- if Year >= 10 then
- begin
- temp := Year div 10;
- Result := Result + LunarStrs[temp];
- Year := Year - temp * 10;
- end
- else
- Result := Result + zero;
- if Year = 0 then Result := Result + zero else
- Result := Result + LunarStrs[Year];
- Result := Result + '年';
- end;
- // 取得指定日期的节气
- function TCnMonthCalendar.GetJieQi(TheDate: TDate): string;
- var
- Y, M, D: Word;
- J: Integer;
- begin
- Result := '';
- DecodeDate(TheDate, Y, M, D);
- J := GetJieQiFromDay(Y, M, D);
- if J <> -1 then
- Result := SCnJieQiArray[J];
- end;
- { TCnCalColors }
- constructor TCnCalColors.Create(AOwner: TCnMonthCalendar);
- begin
- Owner := AOwner;
- FBackColor := clWindow;
- FTextColor := clWindowText;
- FTitleBackColor := clActiveCaption;
- FTitleTextColor := clWhite;
- FTrailingTextColor := clInactiveCaptionText;
- FSundayColor := clRed;
- FSaturdayColor := clMaroon;
- FWeekTextColor := clActiveCaption; // 增加星期字头颜色
- FDaySelectColor := clActiveCaption; // 增加选择日期的填充颜色颜色
- FDaySelectTextColor := clWhite; // 增加选择日期字体的填充颜色颜色
- end;
- procedure TCnCalColors.SetColor(Index: Integer; Value: TColor);
- begin
- case Index of
- 0: FBackColor := Value;
- 1: FTextColor := Value;
- 2: FTitleBackColor := Value;
- 3: FTitleTextColor := Value;
- 4: FTrailingTextColor := Value;
- 5: FSundayColor := Value;
- 6: FSaturdayColor := Value;
- 7: FWeekTextColor := Value; // 增加星期字头字头颜色
- 8: FDaySelectColor := Value; // 增加选择日期的填充颜色颜色
- 9: FDaySelectTextColor := Value; // 增加选择日期字体的填充颜色颜色
- end;
- if Owner.HandleAllocated then
- begin
- Owner.Color := FBackColor;
- Owner.Invalidate;
- end;
- end;
- procedure TCnCalColors.Assign(Source: TPersistent);
- begin
- if (Source = nil) or not (Source is TCnCalColors) then Exit;
- FBackColor := TCnCalColors(Source).BackColor;
- FTextColor := TCnCalColors(Source).TextColor;
- FTitleBackColor := TCnCalColors(Source).TitleBackColor;
- FTitleTextColor := TCnCalColors(Source).TitleTextColor;
- FTrailingTextColor := TCnCalColors(Source).TrailingTextColor;
- FSundayColor := TCnCalColors(Source).SundayColor;
- FSaturdayColor := TCnCalColors(Source).SaturdayColor;
- FWeekTextColor := TCnCalColors(Source).WeekTextColor; // 增加星期字头字头颜色
- FDaySelectColor := TCnCalColors(Source).DaySelectColor;
- FDaySelectTextColor := TCnCalColors(Source).DaySelectTextColor;
- end;
- procedure TCnMonthCalendar.SetShowGanZhi(Value: Boolean);
- begin
- if Value <> FShowGanZhi then
- begin
- FShowGanZhi := Value;
- Invalidate;
- end;
- end;
- procedure TCnMonthCalendar.FirstDayOfMonth;
- var
- D, m, Y: word;
- begin
- FNeedUpdate := True;
- DecodeDate(FDate, Y, m, D);
- SetDate(EncodeDate(Y, m, 1));
- end;
- procedure TCnMonthCalendar.LastDayOfMonth;
- var
- D, m, Y: word;
- begin
- FNeedUpdate := True;
- DecodeDate(IncMonth(FDate, 1), Y, m, D);
- SetDate(EncodeDate(Y, m, 1) - 1);
- end;
- procedure TCnMonthCalendar.NextDay;
- begin
- FNeedUpdate := True;
- SetDate(FDate + 1);
- end;
- procedure TCnMonthCalendar.NextMonth;
- begin
- FNeedUpdate := True;
- SetDate(IncMonth(FDate, 1));
- end;
- procedure TCnMonthCalendar.NextYear;
- begin
- FNeedUpdate := True;
- SetDate(IncMonth(FDate, 12));
- end;
- procedure TCnMonthCalendar.PriorDay;
- begin
- FNeedUpdate := True;
- SetDate(FDate - 1);
- end;
- procedure TCnMonthCalendar.PriorYear;
- begin
- FNeedUpdate := True;
- SetDate(IncMonth(FDate, -12));
- end;
- procedure TCnMonthCalendar.PriorMonth;
- begin
- FNeedUpdate := True;
- SetDate(IncMonth(FDate, -1));
- end;
- procedure TCnMonthCalendar.NextWeek;
- begin
- FNeedUpdate := True;
- SetDate(FDate + 7);
- end;
- procedure TCnMonthCalendar.PriorWeek;
- begin
- FNeedUpdate := True;
- SetDate(FDate - 7);
- end;
- procedure TCnMonthCalendar.SetShowMonthButton(const Value: Boolean);
- begin
- FShowMonthButton := Value;
- lblPrevMonth.Visible := Value;
- lblNextMonth.Visible := Value;
- end;
- procedure TCnMonthCalendar.SetShowYearButton(const Value: Boolean);
- begin
- FShowYearButton := Value;
- lblNextYear.Visible := Value;
- lblPrevYear.Visible := Value;
- end;
- procedure TCnMonthCalendar.NextYearClick(Sender: TObject);
- begin
- NextYear;
- end;
- procedure TCnMonthCalendar.PrevYearClick(Sender: TObject);
- begin
- PriorYear;
- end;
- end.
|