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

Delphi控件源码

开发平台:

Delphi

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