Create a new component

I wanne create a component that has the same functionality as TMonthCalendar class using TPanel and probably Tlabel. Would you tell me how can I write some code for it? Please let me know if you have any other suggestion to create such component?
rastkarAsked:
Who is Participating?
 
mullet_attackConnect With a Mentor Commented:
Here's the bulk of an unfinished calendar I once wrote. It should compile (except the bitmaps are missing, but you should be able to recreate them easily) It duplicates most of the functionality of TMonthCalendar, plus some.

unit TopCalendar;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  ExtCtrls, buttons;

type
  TTopCalendar = class(TCustomControl)
  private
    CalWidth : integer;
    CalHeight : integer;
    fCalColor: TColor;
    fBackColor: TColor;
    fTitleBackColor: TColor;
    fTitleTextColor: TColor;
    fDate: TDate;
    TitleHeight: integer;
    rBtnRect, lBtnRect : TRect;
    CalRect, TitleRect, DaysRect : TRect;
    TitleText : string;
    FontHeight : integer;
    RightBtnDown, LeftBtnDown : boolean;
    bmpToday, bmpTodayMask : TBitmap;
    bmpNo, bmpNoMask : TBitmap;
    procedure SetCalColor(const Value: TColor);
    procedure SetBackColor(const Value: TColor);
    procedure SetTitleBackColor(const Value: TColor);
    procedure SetTitleTextColor(const Value: TColor);
    procedure SetDate(const Value: TDate);
    function DayConv(dow : integer) : integer;
  protected
    procedure Resize;Override;
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);override;
    procedure MouseUp(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);override;
    procedure CalcSizes;
    procedure DrawButtons;
    procedure DrawDates;
    { Protected declarations }
  public
    Constructor Create(AOwner : TComponent);override;
    procedure Paint;override;
    { Public declarations }
  published
    property CalColor : TColor read fCalColor write SetCalColor default clWindow;
    property BackColor : TColor read fBackColor write SetBackColor default clBtnFace;
    property TitleBackColor : TColor read fTitleBackColor write fTitleBackColor default clActiveCaption;
    property TitleTextColor : TColor read fTitleTextColor write fTitleTextColor default clWhite;
    property Date : TDate read fDate write SetDate;
    { Published declarations }
  end;

{$R topcal.res}

const
  Days : array[0..6] of string = ('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun') ;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Samples', [TTopCalendar]);
end;

{ TTopCalendar }

constructor TTopCalendar.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
  bmpToday := TBitmap.create;
  bmpToday.LoadFromResourceName(HInstance,'TODAY');
  bmpTodayMask := TBitmap.create;
  bmpTodayMask.LoadFromResourceName(HInstance,'TODAYMASK');
  bmpNo := TBitmap.create;
  bmpNo.LoadFromResourceName(HInstance,'NO');
  bmpNoMask := TBitmap.create;
  bmpNoMask.LoadFromResourceName(HInstance,'NOMASK');
  Caption := '';
  color := fCalColor;
  CalWidth := 190;
  CalHeight := 154;
  Width := CalWidth;
  Height := CalHeight;
  TitleHeight := 32;
  fCalColor := clWhite;
  fBackColor := clBtnFace;
  fTitleBackColor := clActiveCaption;
  fTitleTextColor := clWhite;
  RightBtnDown := false;
  LeftBtnDown := false;
  Date := now;
  CalcSizes;
end;

procedure TTopCalendar.Resize;
begin
  inherited;
  if Width < CalWidth then Width := CalWidth;
  if Height < CalHeight then Height := CalHeight;
  CalcSizes;
  invalidate;
end;

procedure TTopCalendar.Paint;
var
  t : integer;
begin
  inherited;
  with canvas do
    begin
      FontHeight := TextHeight(Days[0]);
      brush.Color := fBackColor;
      Fillrect(ClientRect);

      brush.color := fCalColor;
      FillRect(CalRect);

      brush.color := fTitleBackColor;
      FillRect(TitleRect);

      font.color := fTitleTextColor;
      font.style := font.style + [fsBold];
      TextOut(calRect.left + (calWidth - TextWidth(TitleText)) div 2,Calrect.Top + (TitleHeight - TextHeight(TitleText)) div 2 ,TitleText);

      brush.color := fCalColor;
      font.color := fTitleBackColor;
      font.style := font.style - [fsBold];
      for t := 0 to 6 do
        TextOut(CalRect.left + 4 + (((CalWidth  - 4) div 7) * t), TitleRect.bottom + 1, days[t]);

      pen.Color := clBlack;
      MoveTo(Calrect.left + 4,TitleRect.bottom + 1 + FontHeight);
      LineTo(Calrect.right - 4,TitleRect.bottom + 1 + FontHeight);
    end;
   DrawButtons;
   DrawDates;
end;

procedure TTopCalendar.SetBackColor(const Value: TColor);
begin
  fBackColor := Value;
  invalidate;
end;

procedure TTopCalendar.SetCalColor(const Value: TColor);
begin
  fCalColor := Value;
  invalidate;
end;

procedure TTopCalendar.SetTitleBackColor(const Value: TColor);
begin
  fTitleBackColor := Value;
  invalidate;
end;

procedure TTopCalendar.SetTitleTextColor(const Value: TColor);
begin
  fTitleBackColor := Value;
  invalidate;
end;
procedure TTopCalendar.SetDate(const Value: TDate);
begin
  fDate := Value;
  TitleText := FormatDateTime('mmmm yyyy',fDate);
  invalidate;
end;

procedure TTopCalendar.CalcSizes;
begin
  CalRect.left := (Width - CalWidth) div 2;
  CalRect.top := (Height - CalHeight) div 2;
  Calrect.Right := CalRect.Left + CalWidth;
  Calrect.Bottom := CalRect.Top + CalHeight;

  TitleRect.left := CalRect.left + 1;
  TitleRect.top := CalRect.top + 1;
  TitleRect.Right := CalRect.Left + CalWidth - 2;
  TitleRect.Bottom := CalRect.Top + TitleHeight;
  With lBtnRect do
    begin
      left := TitleRect.left + 6;
      top := TitleRect.Top + 6;
      right := left + 20;
      bottom := top + 16;
    end;
  With rBtnRect do
    begin
      right := TitleRect.right - 6;
      left := right - 20;
      top := TitleRect.Top + 6;
      bottom := top + 16;
    end;
end;

procedure TTopCalendar.DrawButtons;
var
  t,l : integer;
begin
  DrawButtonFace(Canvas, lBtnRect, 1, bsNew, false, LeftBtnDown, false);
  DrawButtonFace(Canvas, rBtnRect, 1, bsNew, false, RightBtnDown, false);
  canvas.Pen.color := clBlack;
  l := 4;
  for t := 0 to 4 do with canvas do
    begin
      MoveTo(rBtnRect.left + t + 7, rBtnRect.top + t + 3);
      LineTo(rbtnRect.left + t + 7, rBtnRect.top  + 3 + t + (l * 2));
      dec(l);
    end;
  l := 4;
  for t := 0 to 4 do with canvas do
    begin
      MoveTo(lBtnRect.left + l + 5, lBtnRect.top + 3 + t);
      LineTo(lbtnRect.left + l + 5, lBtnRect.top + 3 + t + (l * 2));
      dec(l);
    end;
end;

procedure TTopCalendar.MouseDown(Button: TMouseButton; Shift: TShiftState;
  X, Y: Integer);
var
  year, month, day : word;
begin
  inherited;
  if Button = mbLeft then
    begin
      if PtInRect(lBtnRect,point(x,y)) then
        begin
          LeftBtnDown := true;
          DecodeDate(fDate,Year, month, day);
          Dec(month);
          if month = 0 then
            begin
              dec(year);
              month := 12;
            end;
          Date := EncodeDate(year, month, day);
        end;
      if PtInRect(rBtnRect,point(x,y)) then
        begin
          RightBtnDown := true;
          DecodeDate(fDate,Year, month, day);
          inc(month);
          if month = 13 then
            begin
              inc(year);
              Month := 1;
            end;
          Date := EncodeDate(year, month, day);
        end;
      DrawButtons;
    end;

end;

procedure TTopCalendar.MouseUp(Button: TMouseButton; Shift: TShiftState; X,
  Y: Integer);
begin
  inherited;
  LeftBtnDown := false;
  RightBtnDown := false;
  DrawButtons;
end;

procedure TTopCalendar.DrawDates;
var
  StartDate : TDate;
  ThisMonth, Day ,Month ,Year : word;
  x,y : integer;
  p,z : integer;
  FHeight : integer;
  boxwidth, boxheight : integer;
begin
  FHeight := canvas.TextHeight(Days[1]);
   With DaysRect do
    begin
      left := CalRect.left + 4;
      right := left + CalWidth - 4;
      top := CalRect.top + TitleHeight + 2 + FHeight;
      bottom := top + (CalRect.bottom - CalRect.top) - (FHeight * 2) - TitleHeight - 2;
    end;
  DecodeDate(fDate, Year, Month, Day);
  ThisMonth := Month;
  z := DayOfWeek(EncodeDate(Year, Month, 1));
  p := DayConv(z);
  StartDate := EncodeDate(Year, Month, 1) - p + 1;
  DecodeDate(StartDate, Year, Month, Day);
  if day = 1 then StartDate := StartDate - 7;
  canvas.Brush.Color := fCalColor;
//  BoxWidth := DaysRect.left + ((DaysRect.right - DaysRect.left) div 7);
//  BoxHeight := DaysRect.top + ((DaysRect.Bottom - DaysRect.top) div 6);
  BoxWidth := (DaysRect.right - DaysRect.left) div 7;
  BoxHeight := (DaysRect.Bottom - DaysRect.top) div 6;
  for y := 0 to 5 do
    for x := 0 to 6 do
      begin
        DecodeDate(StartDate, Year, Month, Day);
        If Month = ThisMonth then
          canvas.brush.color := clyellow
        else
          canvas.brush.color := clwhite;
        If ((DayOfWeek(StartDate) = 1) or (DayOfWeek(StartDate) = 7)) then
          canvas.font.color := clRed
        else
          canvas.font.color := clGreen;

        canvas.fillrect(rect
                            (DaysRect.left + (BoxWidth * x)-2,
                             DaysRect.top + (BoxHeight * y),
                             DaysRect.left +  (BoxWidth  * (x + 1))-2,
                             DaysRect.top + (BoxHeight * (y +1))));
        canvas.textout(DaysRect.left + (BoxWidth * x) + 5,
                       DaysRect.top + (BoxHeight * y),
                       Format('%2d',[day]));
        if (StartDate = trunc(Now)) then
          begin
            canvas.CopyMode := cmSrcAnd;
            canvas.CopyRect(rect
                            (DaysRect.left + (BoxWidth * x)-2,
                             DaysRect.top + (BoxHeight * y),
                             DaysRect.left +  (BoxWidth  * (x + 1))-2,
                             DaysRect.top + (BoxHeight * (y +1))),
                             bmpTodayMask.canvas,
                            rect(
                             0,
                             0,
                             bmpTodayMask.width,
                             bmpTodayMask.height));
            canvas.CopyMode := cmSrcPaint;
            canvas.CopyRect(rect(
                             DaysRect.left + (BoxWidth * x-2),
                             DaysRect.top + (BoxHeight * y),
                             DaysRect.left + (BoxWidth * (x + 1))-2,
                             DaysRect.top + (BoxHeight * (y + 1))),
                             bmpToday.canvas,
                            rect(
                             0,
                             0,
                             bmpTodayMask.width,
                             bmpTodayMask.height));

          end;
        if true = false then
          begin
            canvas.CopyMode := cmSrcAnd;
            canvas.CopyRect(rect
                            (DaysRect.left + (BoxWidth * x)-2,
                             DaysRect.top + (BoxHeight * y),
                             DaysRect.left +  (BoxWidth  * (x + 1))-2,
                             DaysRect.top + (BoxHeight * (y +1))),
                             bmpNoMask.canvas,
                            rect(
                             0,
                             0,
                             bmpNoMask.width,
                             bmpNoMask.height));
            canvas.CopyMode := cmSrcPaint;
            canvas.CopyRect(rect(
                             DaysRect.left + (BoxWidth * x-2),
                             DaysRect.top + (BoxHeight * y),
                             DaysRect.left + (BoxWidth * (x + 1))-2,
                             DaysRect.top + (BoxHeight * (y + 1))),
                             bmpNo.canvas,
                            rect(
                             0,
                             0,
                             bmpNoMask.width,
                             bmpNoMask.height));

          end;
        StartDate := StartDate + 1;
      end;
end;

function TTopCalendar.DayConv(dow: integer): integer;
begin
  if dow = 1 then
   result := 7
 else
   result := dow - 1;  
end;

end.
0
 
rastkarAuthor Commented:
I like to have a Piece of code to start...
0
 
ITugayCommented:
Use TStringGrid or TDrawGrid instead TPanel. It more easy.

---
Igor.
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.