spcalendar.pas
上传用户:hylc_2004
上传日期:2014-01-23
资源大小:46800k
文件大小:12k
源码类别:

Delphi控件源码

开发平台:

Delphi

  1. {*******************************************************************}
  2. {                                                                   }
  3. {       Almediadev Visual Component Library                         }
  4. {       DynamicSkinForm                                             }
  5. {       Version 4.98                                                }
  6. {                                                                   }
  7. {       Copyright (c) 2000-2002 Almediadev                          }
  8. {       ALL RIGHTS RESERVED                                         }
  9. {                                                                   }
  10. {       Home:  http://www.almdev.com                                }
  11. {       Support: support@almdev.com                                 }
  12. {                                                                   }
  13. {*******************************************************************}
  14. unit spcalendar;
  15. interface
  16. uses Windows, SysUtils, Messages, Classes, Graphics, Controls, Forms,
  17.      Buttons, SkinCtrls, SkinData, ExtCtrls;
  18. type
  19.   TspDaysOfWeek = (Sun, Mon, Tue, Wed, Thu, Fri, Sat);
  20.   TspSkinMonthCalendar = class(TspSkinPanel)
  21.   protected
  22.     FTodayDefault: Boolean;
  23.     BevelTop, CellW, CellH: Integer;
  24.     FBtns: array[0..3] of TspSkinSpeedButton;
  25.     MonthYearLabel: TspSkinStdLabel;
  26.     FDate: TDate;
  27.     FFirstDayOfWeek: TspDaysOfWeek;
  28.     CalFontColor: TColor;
  29.     CalActiveFontColor: TColor;
  30.     FOnNumberClick: TNotifyEvent;
  31.     procedure Loaded; override;
  32.     procedure SetTodayDefault(Value: Boolean);
  33.     procedure OffsetMonth(AOffset: Integer);
  34.     procedure OffsetYear(AOffset: Integer);
  35.     procedure SetFirstDayOfWeek(Value: TspDaysOfWeek);
  36.     procedure UpdateCalendar;
  37.     procedure ArangeControls;
  38.     procedure WMSIZE(var Message: TWMSIZE); message WM_SIZE;
  39.     procedure SetSkinData(Value: TspSkinData); override;
  40.     procedure CreateControlDefaultImage(B: TBitMap); override;
  41.     procedure CreateControlSkinImage(B: TBitMap); override;
  42.     procedure SetDate(Value: TDate);
  43.     procedure DrawCalendar(Cnvs: TCanvas);
  44.     function DaysThisMonth: Integer;
  45.     function GetMonthOffset: Integer;
  46.     procedure MouseUp(Button: TMouseButton; Shift: TShiftState;
  47.       X, Y: Integer); override;
  48.     function DayNumFromPoint(X, Y: Integer): Word;
  49.     procedure NextMButtonClick(Sender: TObject);
  50.     procedure PriorMButtonClick(Sender: TObject);
  51.     procedure NextYButtonClick(Sender: TObject);
  52.     procedure PriorYButtonClick(Sender: TObject);
  53.     procedure SetCaptionMode(Value: Boolean); override;
  54.     procedure SetDefaultCaptionHeight(Value: Integer); override;
  55.   public
  56.     constructor Create(AOwner: TComponent); override;
  57.     procedure ChangeSkinData; override;
  58.   published
  59.     property Date: TDate read FDate write SetDate;
  60.     property TodayDefault: Boolean read FTodayDefault write SetTodayDefault; 
  61.     property FirstDayOfWeek: TspDaysOfWeek read FFirstDayOfWeek write SetFirstDayOfWeek;
  62.     property OnNumberClick: TNotifyEvent
  63.       read FOnNumberClick write FOnNumberClick;
  64.   end;
  65. implementation
  66.       Uses spUtils;
  67. {$R *.res}
  68. const
  69.   BSize = 20;
  70.   RepeatInt = 250;
  71. constructor TspSkinMonthCalendar.Create;
  72. begin
  73.   inherited;
  74.   BorderStyle := bvFrame;
  75.   FBtns[0] := TspSkinSpeedButton.Create(Self);
  76.   with FBtns[0] do
  77.   begin
  78.     RepeatMode := True;
  79.     RepeatInterval := RepeatInt;
  80.     SkinDataName := 'resizebutton';
  81.     Width := BSize;
  82.     Height := BSize;
  83.     NumGlyhps := 1;
  84.     Glyph.Handle := LoadBitmap(hInstance, 'SP_PRIORMONTH');
  85.     OnClick := PriorMButtonClick;
  86.     Parent := Self;
  87.   end;
  88.   FBtns[1] := TspSkinSpeedButton.Create(Self);
  89.   with FBtns[1] do
  90.   begin
  91.     RepeatMode := True;
  92.     RepeatInterval := RepeatInt;
  93.     SkinDataName := 'resizebutton';
  94.     Width := BSize;
  95.     Height := BSize;
  96.     NumGlyhps := 1;
  97.     Glyph.Handle := LoadBitmap(hInstance, 'SP_NEXTMONTH');
  98.     OnClick := NextMButtonClick;
  99.     Parent := Self;
  100.   end;
  101.   FBtns[2] := TspSkinSpeedButton.Create(Self);
  102.   with FBtns[2] do
  103.   begin
  104.     RepeatMode := True;
  105.     RepeatInterval := RepeatInt - 150;
  106.     SkinDataName := 'resizebutton';
  107.     Width := BSize;
  108.     Height := BSize;
  109.     NumGlyhps := 1;
  110.     Glyph.Handle := LoadBitmap(hInstance, 'SP_PRIORYEAR');
  111.     OnClick := PriorYButtonClick;
  112.     Parent := Self;
  113.   end;
  114.   FBtns[3] := TspSkinSpeedButton.Create(Self);
  115.   with FBtns[3] do
  116.   begin
  117.     RepeatMode := True;
  118.     RepeatInterval := RepeatInt - 150;
  119.     SkinDataName := 'resizebutton';
  120.     Width := BSize;
  121.     Height := BSize;
  122.     NumGlyhps := 1;
  123.     Glyph.Handle := LoadBitmap(hInstance, 'SP_NEXTYEAR');
  124.     OnClick := NextYButtonClick;
  125.     Parent := Self;
  126.   end;
  127.   Width := 200;
  128.   Height := 150;
  129.   Date := Now;
  130.   FTodayDefault := False;
  131. end;
  132. procedure TspSkinMonthCalendar.SetTodayDefault;
  133. begin
  134.   FTodayDefault := Value;
  135.   if FTodayDefault then Date := Now;
  136. end;
  137. procedure TspSkinMonthCalendar.SetCaptionMode;
  138. begin
  139.   inherited;
  140.   ArangeControls;
  141.   UpdateCalendar;
  142. end;
  143. procedure TspSkinMonthCalendar.SetDefaultCaptionHeight;
  144. begin
  145.   inherited;
  146.   ArangeControls;
  147.   UpdateCalendar;
  148. end;
  149. procedure TspSkinMonthCalendar.ChangeSkinData;
  150. var
  151.   I: Integer;
  152. begin
  153.   I := FSD.GetControlIndex('stdlabel');
  154.   if I <> -1
  155.   then
  156.     if TspDataSkinControl(FSD.CtrlList.Items[I]) is TspDataSkinStdLabelControl
  157.     then
  158.       with TspDataSkinStdLabelControl(FSD.CtrlList.Items[I]) do
  159.       begin
  160.         CalFontColor := FontColor;
  161.         CalActiveFontColor := ActiveFontColor;
  162.       end
  163.     else
  164.       begin
  165.         CalFontColor := Font.Color;
  166.         CalActiveFontColor := Font.Color;
  167.       end;
  168.   inherited;
  169.   ArangeControls;
  170. end;
  171. procedure TspSkinMonthCalendar.NextMButtonClick(Sender: TObject);
  172. begin
  173.   OffsetMonth(1);
  174.   Click;
  175. end;
  176. procedure TspSkinMonthCalendar.PriorMButtonClick(Sender: TObject);
  177. begin
  178.   OffsetMonth(-1);
  179.   Click;
  180. end;
  181. procedure TspSkinMonthCalendar.NextYButtonClick(Sender: TObject);
  182. begin
  183.   OffsetYear(1);
  184.   Click;
  185. end;
  186. procedure TspSkinMonthCalendar.PriorYButtonClick(Sender: TObject);
  187. begin
  188.   OffsetYear(-1);
  189.   Click;
  190. end;
  191. procedure TspSkinMonthCalendar.OffsetMonth(AOffset: Integer);
  192. var
  193.   AYear, AMonth, ADay: Word;
  194.   TempDate: TDate;
  195. begin
  196.   DecodeDate(FDate, AYear, AMonth, ADay);
  197.   AMonth := AMonth + AOffset;
  198.   if AMonth > 12 then AMonth := 1 else
  199.   if AMonth <= 0 then AMonth := 12;
  200.   if ADay > DaysPerMonth(AYear, AMonth)
  201.   then ADay := DaysPerMonth(AYear, AMonth);
  202.   TempDate := EncodeDate(AYear, AMonth, ADay);
  203.   Date := TempDate;
  204. end;
  205. procedure TspSkinMonthCalendar.OffsetYear(AOffset: Integer);
  206. var
  207.   AYear, AMonth, ADay: Word;
  208.   TempDate: TDate;
  209. begin
  210.   DecodeDate(FDate, AYear, AMonth, ADay);
  211.   AYear := AYear + AOffset;
  212.   if AYear <= 1760 then Exit else
  213.     if AYear > 9999 then Exit;
  214.   TempDate := EncodeDate(AYear, AMonth, ADay);
  215.   Date := TempDate;
  216. end;
  217. procedure TspSkinMonthCalendar.SetFirstDayOfWeek(Value: TspDaysOfWeek);
  218. begin
  219.   FFirstDayOfWeek := Value;
  220.   UpdateCalendar;
  221. end;
  222. procedure TspSkinMonthCalendar.SetSkinData;
  223. var
  224.   i: Integer;
  225. begin
  226.   inherited;
  227.   for i := 0 to 3 do
  228.    if FBtns[i] <> nil then FBtns[i].SkinData := Value;
  229. end;
  230. procedure TspSkinMonthCalendar.ArangeControls;
  231. var
  232.   R: TRect;
  233. begin
  234.   R := Rect(0, 0, Width, Height);
  235.   AdjustClientRect(R);
  236.   if FBtns[0] = nil then Exit;
  237.   with FBtns[2] do SetBounds(R.Left + 1, R.Top + 1, Width, Height);
  238.   with FBtns[0] do SetBounds(FBtns[2].Left + BSize + 1, R.Top + 1, Width, Height);
  239.   with FBtns[3] do SetBounds(R.Right - BSize - 1, R.Top + 1, Width, Height);
  240.   with FBtns[1] do SetBounds(FBtns[3].Left - BSize - 1 , R.Top + 1, Width, Height);
  241. end;
  242. procedure TspSkinMonthCalendar.WMSIZE;
  243. begin
  244.   inherited;
  245.   ArangeControls;
  246. end;
  247. procedure TspSkinMonthCalendar.CreateControlDefaultImage(B: TBitMap);
  248. begin
  249.   inherited;
  250.   DrawCalendar(B.Canvas);
  251. end;
  252. procedure TspSkinMonthCalendar.CreateControlSkinImage(B: TBitMap);
  253. begin
  254.   inherited;
  255.   DrawCalendar(B.Canvas);
  256. end;
  257. procedure TspSkinMonthCalendar.SetDate(Value: TDate);
  258. begin
  259.   FDate := Value;
  260.   UpdateCalendar;
  261.   RePaint;
  262. end;
  263. procedure TspSkinMonthCalendar.UpdateCalendar;
  264. begin
  265.   RePaint;
  266. end;
  267. function TspSkinMonthCalendar.GetMonthOffset: Integer;
  268. var
  269.   AYear, AMonth, ADay: Word;
  270.   FirstDate: TDate;
  271. begin
  272.   DecodeDate(FDate, AYear, AMonth, ADay);
  273.   FirstDate := EncodeDate(AYear, AMonth, 1);
  274.   Result := 2 - ((DayOfWeek(FirstDate) - Ord(FirstDayOfWeek) + 7) mod 7);
  275.   if Result = 2 then Result := -5;
  276. end;
  277. procedure TspSkinMonthCalendar.DrawCalendar(Cnvs: TCanvas);
  278. var
  279.   R: TRect;
  280.   I, J: Integer;
  281.   FMonthOffset, X, Y, X2, Y2: Integer;
  282.   S: String;
  283.   ADay, DayNum: Word;
  284. begin
  285.   R := Rect(0, 0, Width, Height);
  286.   AdjustClientRect(R);
  287.   with Cnvs do
  288.   begin
  289.     Font := Self.DefaultFont;
  290.     Brush.Style := bsClear;
  291.     // draw caption
  292.     S := FormatDateTime('MMMM, YYYY', FDate);
  293.     Y := R.Top + 2;
  294.     X := (RectWidth(R) - BSize * 4 - 2) div 2 - TextWidth(S) div 2;
  295.     X := X + FBtns[0].Left + BSize + 1;
  296.     if FIndex <> -1
  297.     then
  298.       Font.Color := CalActiveFontColor;
  299.     Font.Style := [fsBold];
  300.     TextOut(X, Y, S);
  301.     CellW := (RectWidth(R) - 2) div 7;
  302.     // draw week days
  303.     X := R.Left + 1;
  304.     Y := R.Top + BSize + 10;
  305.     for I := 0 to 6 do
  306.     begin
  307.       S := ShortDayNames[(Ord(FirstDayOfWeek) + I) mod 7 + 1];
  308.       X2 := X + CellW div 2 - TextWidth(S) div 2;
  309.       TextOut(X2, Y, S);
  310.       X := X + CellW;
  311.     end;
  312.     // draw bevel
  313.     BevelTop := Y + TextHeight('Wq') + 1;
  314.     Pen.Color := Font.Color;
  315.     MoveTo(R.Left + 1, BevelTop);
  316.     LineTo(R.Right - 1, BevelTop);
  317.     Font.Style := [];
  318.     // draw month numbers
  319.     CellH := (R.Bottom - BevelTop - 4) div 6;
  320.     if FIndex <> -1
  321.     then
  322.       Font.Color := CalFontColor;
  323.     FMonthOffset := GetMonthOffset;
  324.     ADay := ExtractDay(FDate);
  325.     Y := BevelTop + 3;
  326.     for J := 0 to 6 do
  327.     begin
  328.       X := R.Left + 1;
  329.       for I := 0 to 6 do
  330.       begin
  331.         DayNum := FMonthOffset + I + (J - 1) * 7;
  332.         if (DayNum < 1) or (DayNum > DaysThisMonth) then S := ''
  333.         else S := IntToStr(DayNum);
  334.         X2 := X + CellW div 2 - TextWidth(S) div 2;
  335.         Y2 := Y - CellH div 2 - TextHeight(S) div 2;
  336.         if S <> '' then TextOut(X2, Y2, S);
  337.         if DayNum = ADay
  338.         then
  339.           begin
  340.             if FIndex <> -1
  341.             then
  342.               Pen.Color := CalActiveFontColor
  343.             else
  344.              Pen.Color := Font.Color;
  345.            Rectangle(X, Y - CellH, X + CellW, Y);
  346.          end;
  347.         X := X + CellW;
  348.       end;
  349.       Y := Y + CellH;
  350.     end;
  351.   end;
  352. end;
  353. function TspSkinMonthCalendar.DaysThisMonth: Integer;
  354. begin
  355.   Result := DaysPerMonth(ExtractYear(FDate), ExtractMonth(FDate));
  356. end;
  357. function TspSkinMonthCalendar.DayNumFromPoint;
  358. var
  359.   R, R1: TRect;
  360.   FMonthOffset, X1, Y1, I, J: Integer;
  361. begin
  362.   Result := 0;
  363.   R := Rect(0, 0, Width, Height);
  364.   AdjustClientRect(R);
  365.   if not PtInRect(R, Point(X, Y)) then Exit;
  366.   FMonthOffset := GetMonthOffset;
  367.   Y1 := BevelTop + 3;
  368.   for J := 0 to 6 do
  369.   begin
  370.     X1 := R.Left + 1;
  371.     for I := 0 to 6 do
  372.     begin
  373.       R1 := Rect(X1, Y1 - CellH, X1 + CellW, Y1);
  374.       if PtInRect(R1, Point(X, Y))
  375.       then
  376.         begin
  377.           Result := FMonthOffset + I + (J - 1) * 7;
  378.           if (Result < 1) or (Result > DaysThisMonth) then Result := 0;
  379.           Break;
  380.         end;
  381.       X1 := X1 + CellW;
  382.     end;
  383.     Y1 := Y1 + CellH;
  384.   end;
  385. end;
  386. procedure TspSkinMonthCalendar.MouseUp;
  387. var
  388.   DayNum, AYear, AMonth, ADay: Word;
  389.   TempDate: TDate;
  390. begin
  391.   inherited;
  392.   if Button <> mbLeft then Exit;
  393.   DayNum := DayNumFromPoint(X, Y);
  394.   if DayNum <> 0
  395.   then
  396.     begin
  397.       DecodeDate(FDate, AYear, AMonth, ADay);
  398.       ADay := DayNum;
  399.       TempDate := EncodeDate(AYear, AMonth, ADay);
  400.       Date := TempDate;
  401.       if Assigned(FOnNumberClick) then FOnNumberClick(Self);
  402.     end;
  403. end;
  404. procedure TspSkinMonthCalendar.Loaded;
  405. begin
  406.   inherited;
  407.   if FTodayDefault then Date := Now;
  408. end;
  409. end.