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

Delphi控件源码

开发平台:

Delphi

  1. {*******************************************************************}
  2. {                                                                   }
  3. {       Almediadev Visual Component Library                         }
  4. {       DynamicSkinForm                                             }
  5. {       Version 5.60                                                }
  6. {                                                                   }
  7. {       Copyright (c) 2000-2003 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.     NumGlyphs := 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.     NumGlyphs := 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.     NumGlyphs := 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.     NumGlyphs := 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. var
  173.   AYear, AMonth, ADay: Word;
  174. begin
  175.   DecodeDate(FDate, AYear, AMonth, ADay);
  176.   if AMonth = 12 then OffsetYear(1);
  177.   OffsetMonth(1);
  178.   Click;
  179. end;
  180. procedure TspSkinMonthCalendar.PriorMButtonClick(Sender: TObject);
  181. var
  182.   AYear, AMonth, ADay: Word;
  183. begin
  184.   DecodeDate(FDate, AYear, AMonth, ADay);
  185.   if AMonth = 1 then OffsetYear(-1);
  186.   OffsetMonth(-1);
  187.   Click;
  188. end;
  189. procedure TspSkinMonthCalendar.NextYButtonClick(Sender: TObject);
  190. begin
  191.   OffsetYear(1);
  192.   Click;
  193. end;
  194. procedure TspSkinMonthCalendar.PriorYButtonClick(Sender: TObject);
  195. begin
  196.   OffsetYear(-1);
  197.   Click;
  198. end;
  199. procedure TspSkinMonthCalendar.OffsetMonth(AOffset: Integer);
  200. var
  201.   AYear, AMonth, ADay: Word;
  202.   TempDate: TDate;
  203. begin
  204.   DecodeDate(FDate, AYear, AMonth, ADay);
  205.   AMonth := AMonth + AOffset;
  206.   if AMonth > 12 then AMonth := 1 else
  207.   if AMonth <= 0 then AMonth := 12;
  208.   if ADay > DaysPerMonth(AYear, AMonth)
  209.   then ADay := DaysPerMonth(AYear, AMonth);
  210.   TempDate := EncodeDate(AYear, AMonth, ADay);
  211.   Date := TempDate;
  212. end;
  213. procedure TspSkinMonthCalendar.OffsetYear(AOffset: Integer);
  214. var
  215.   AYear, AMonth, ADay: Word;
  216.   TempDate: TDate;
  217. begin
  218.   DecodeDate(FDate, AYear, AMonth, ADay);
  219.   AYear := AYear + AOffset;
  220.   if AYear <= 1760 then Exit else
  221.     if AYear > 9999 then Exit;
  222.   if ADay > DaysPerMonth(AYear, AMonth)
  223.   then ADay := DaysPerMonth(AYear, AMonth);  
  224.   TempDate := EncodeDate(AYear, AMonth, ADay);
  225.   Date := TempDate;
  226. end;
  227. procedure TspSkinMonthCalendar.SetFirstDayOfWeek(Value: TspDaysOfWeek);
  228. begin
  229.   FFirstDayOfWeek := Value;
  230.   UpdateCalendar;
  231. end;
  232. procedure TspSkinMonthCalendar.SetSkinData;
  233. var
  234.   i: Integer;
  235. begin
  236.   inherited;
  237.   for i := 0 to 3 do
  238.    if FBtns[i] <> nil then FBtns[i].SkinData := Value;
  239. end;
  240. procedure TspSkinMonthCalendar.ArangeControls;
  241. var
  242.   R: TRect;
  243. begin
  244.   R := Rect(0, 0, Width, Height);
  245.   AdjustClientRect(R);
  246.   if FBtns[0] = nil then Exit;
  247.   with FBtns[2] do SetBounds(R.Left + 1, R.Top + 1, Width, Height);
  248.   with FBtns[0] do SetBounds(FBtns[2].Left + BSize + 1, R.Top + 1, Width, Height);
  249.   with FBtns[3] do SetBounds(R.Right - BSize - 1, R.Top + 1, Width, Height);
  250.   with FBtns[1] do SetBounds(FBtns[3].Left - BSize - 1 , R.Top + 1, Width, Height);
  251. end;
  252. procedure TspSkinMonthCalendar.WMSIZE;
  253. begin
  254.   inherited;
  255.   ArangeControls;
  256. end;
  257. procedure TspSkinMonthCalendar.CreateControlDefaultImage(B: TBitMap);
  258. begin
  259.   inherited;
  260.   DrawCalendar(B.Canvas);
  261. end;
  262. procedure TspSkinMonthCalendar.CreateControlSkinImage(B: TBitMap);
  263. begin
  264.   inherited;
  265.   DrawCalendar(B.Canvas);
  266. end;
  267. procedure TspSkinMonthCalendar.SetDate(Value: TDate);
  268. begin
  269.   FDate := Value;
  270.   UpdateCalendar;
  271.   RePaint;
  272. end;
  273. procedure TspSkinMonthCalendar.UpdateCalendar;
  274. begin
  275.   RePaint;
  276. end;
  277. function TspSkinMonthCalendar.GetMonthOffset: Integer;
  278. var
  279.   AYear, AMonth, ADay: Word;
  280.   FirstDate: TDate;
  281. begin
  282.   DecodeDate(FDate, AYear, AMonth, ADay);
  283.   FirstDate := EncodeDate(AYear, AMonth, 1);
  284.   Result := 2 - ((DayOfWeek(FirstDate) - Ord(FirstDayOfWeek) + 7) mod 7);
  285.   if Result = 2 then Result := -5;
  286. end;
  287. procedure TspSkinMonthCalendar.DrawCalendar(Cnvs: TCanvas);
  288. var
  289.   R: TRect;
  290.   I, J: Integer;
  291.   FMonthOffset, X, Y, X2, Y2: Integer;
  292.   S: String;
  293.   ADay, DayNum: Integer;
  294. begin
  295.   R := Rect(0, 0, Width, Height);
  296.   AdjustClientRect(R);
  297.   with Cnvs do
  298.   begin
  299.     Font := Self.DefaultFont;
  300.     Brush.Style := bsClear;
  301.     // draw caption
  302.     S := FormatDateTime('MMMM, YYYY', FDate);
  303.     Y := R.Top + 2;
  304.     X := (RectWidth(R) - BSize * 4 - 2) div 2 - TextWidth(S) div 2;
  305.     X := X + FBtns[0].Left + BSize + 1;
  306.     if FIndex <> -1
  307.     then
  308.       Font.Color := CalActiveFontColor;
  309.     Font.Style := [fsBold];
  310.     TextOut(X, Y, S);
  311.     CellW := (RectWidth(R) - 2) div 7;
  312.     // draw week days
  313.     X := R.Left + 1;
  314.     Y := R.Top + BSize + 10;
  315.     for I := 0 to 6 do
  316.     begin
  317.       S := ShortDayNames[(Ord(FirstDayOfWeek) + I) mod 7 + 1];
  318.       X2 := X + CellW div 2 - TextWidth(S) div 2;
  319.       TextOut(X2, Y, S);
  320.       X := X + CellW;
  321.     end;
  322.     // draw bevel
  323.     BevelTop := Y + TextHeight('Wq') + 1;
  324.     Pen.Color := Font.Color;
  325.     MoveTo(R.Left + 1, BevelTop);
  326.     LineTo(R.Right - 1, BevelTop);
  327.     Font.Style := [];
  328.     // draw month numbers
  329.     CellH := (R.Bottom - BevelTop - 4) div 6;
  330.     if FIndex <> -1
  331.     then
  332.       Font.Color := CalFontColor;
  333.     FMonthOffset := GetMonthOffset;
  334.     ADay := ExtractDay(FDate);
  335.     Y := BevelTop + 3;
  336.     for J := 0 to 6 do
  337.     begin
  338.       X := R.Left + 1;
  339.       for I := 0 to 6 do
  340.       begin
  341.         DayNum := FMonthOffset + I + (J - 1) * 7;
  342.         if (DayNum < 1) or (DayNum > DaysThisMonth) then S := ''
  343.         else S := IntToStr(DayNum);
  344.         X2 := X + CellW div 2 - TextWidth(S) div 2;
  345.         Y2 := Y - CellH div 2 - TextHeight(S) div 2;
  346.         if S <> '' then TextOut(X2, Y2, S);
  347.         if DayNum = ADay
  348.         then
  349.           begin
  350.             if FIndex <> -1
  351.             then
  352.               Pen.Color := CalActiveFontColor
  353.             else
  354.              Pen.Color := Font.Color;
  355.            Rectangle(X, Y - CellH, X + CellW, Y);
  356.          end;
  357.         X := X + CellW;
  358.       end;
  359.       Y := Y + CellH;
  360.     end;
  361.   end;
  362. end;
  363. function TspSkinMonthCalendar.DaysThisMonth: Integer;
  364. begin
  365.   Result := DaysPerMonth(ExtractYear(FDate), ExtractMonth(FDate));
  366. end;
  367. function TspSkinMonthCalendar.DayNumFromPoint;
  368. var
  369.   R, R1: TRect;
  370.   FMonthOffset, X1, Y1, I, J: Integer;
  371. begin
  372.   Result := 0;
  373.   R := Rect(0, 0, Width, Height);
  374.   AdjustClientRect(R);
  375.   if not PtInRect(R, Point(X, Y)) then Exit;
  376.   FMonthOffset := GetMonthOffset;
  377.   Y1 := BevelTop + 3;
  378.   for J := 0 to 6 do
  379.   begin
  380.     X1 := R.Left + 1;
  381.     for I := 0 to 6 do
  382.     begin
  383.       R1 := Rect(X1, Y1 - CellH, X1 + CellW, Y1);
  384.       if PtInRect(R1, Point(X, Y))
  385.       then
  386.         begin
  387.           Result := FMonthOffset + I + (J - 1) * 7;
  388.           if (Result < 1) or (Result > DaysThisMonth) then Result := 0;
  389.           Break;
  390.         end;
  391.       X1 := X1 + CellW;
  392.     end;
  393.     Y1 := Y1 + CellH;
  394.   end;
  395. end;
  396. procedure TspSkinMonthCalendar.MouseUp;
  397. var
  398.   DayNum, AYear, AMonth, ADay: Word;
  399.   TempDate: TDate;
  400. begin
  401.   inherited;
  402.   if Button <> mbLeft then Exit;
  403.   DayNum := DayNumFromPoint(X, Y);
  404.   if DayNum <> 0
  405.   then
  406.     begin
  407.       DecodeDate(FDate, AYear, AMonth, ADay);
  408.       ADay := DayNum;
  409.       TempDate := EncodeDate(AYear, AMonth, ADay);
  410.       Date := TempDate;
  411.       if Assigned(FOnNumberClick) then FOnNumberClick(Self);
  412.     end;
  413. end;
  414. procedure TspSkinMonthCalendar.Loaded;
  415. begin
  416.   inherited;
  417.   if FTodayDefault then Date := Now;
  418. end;
  419. end.