トップへ(mam-mam.net/)

TGridPanelでカレンダー表示 ~Delphiソースコード集

TGridPanelでカレンダー表示 ~Delphiソースコード集

TGridPanelを使うとコンポーネントをグリッド上に並べて配置することが出来ます。
これを利用してカレンダー表示を行ってみます。

TGridPanel.RowCollection.BeginUpdate(); ~ TGridPanel.RowCollection.EndUpdate();
TGridPanel.ColumnCollection.BeginUpdate(); ~ TGridPanel.ColumnCollection.EndUpdate();
が非常に重要となります。

プロジェクトの作成と画面設計

Delphiを起動し、メニューから「ファイル」⇒「新規作成」⇒ 「Windows VCLアプリケーション -Delphi(W)」をクリックしてプロジェクトを作成します。

「TPanel」と「TGridPanel」をフォームにドラッグ&ドロップします。
Panel1の上に「TComboBox」を2個ドラッグ&ドロップします。

ソースコードの記述

「コード」モードに切り替えて(F12を押す)、以下ソースコードをドラッグ&ドロップして貼り付けます。

「デザイン」モードに切り替えて(F12を押す)、左下ペインの「オブジェクト インスペクタ」を「イベント」タブに切り替えて以下の設定を行います。

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
  Vcl.ExtCtrls, Vcl.StdCtrls, DateUtils, Vcl.Buttons;

type
  TForm1 = class(TForm)
    GridPanel1: TGridPanel;
    Panel1: TPanel;
    ComboBox1: TComboBox;
    ComboBox2: TComboBox;
    procedure FormCreate(Sender: TObject);
    procedure ComboBox1Change(Sender: TObject);
  private
    { Private 宣言 }
    procedure CreateCalendar(GPanel:TGridPanel; y,m:Integer);
    procedure SpeedButtonClick(Sender:TObject);
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;
const Weeks:array[0..6] of String=
  ('日','月','火','水','木','金','土');

implementation

{$R *.dfm}

procedure TForm1.SpeedButtonClick(Sender: TObject);
var d:TDateTime;
begin
  if Sender is TSpeedButton then
  begin
    d:=TDateTime(TSpeedButton(Sender).Tag);
    ShowMessage(FormatDateTime('yyyy/mm/dd',d));
  end;
end;

procedure TForm1.ComboBox1Change(Sender: TObject);
begin
  CreateCalendar(
    GridPanel1,
    StrToInt(ComboBox1.Items[ComboBox1.ItemIndex]),
    StrToInt(ComboBox2.Items[ComboBox2.ItemIndex])
  );
end;

procedure TForm1.CreateCalendar(GPanel:TGridPanel; y,m:Integer);
var StartDate, EndDate, PreviousDate, NextDate, GPDate:TDateTime;
    SButton:TSpeedButton;
    Lbl:TLabel;
    ColumnItem:TColumnItem;
    RowItem:TRowItem;
    DayCount, RowCount, Row,Col:Integer;
begin
  //グリッドパネル上のコントロールを破棄
  while GPanel.ControlCount>0 do GPanel.Controls[0].Free;

  //年月の最初の日
  StartDate:=EncodeDate(y,m,1);
  //年月の最後の日
  EndDate:=EndOfAMonth(y,m);
  //カレンダーには日曜日から表示するので前月日付
  PreviousDate:=StartDate-(DayOfTheWeek(StartDate) Mod 7);
  //カレンダーには土曜日まで表示するので次月日付
  NextDate:=EndOfAMonth(y,m)+(6-(DayOfTheWeek(EndDate) mod 7));
  //グリッドパネル上に表示する総日数
  DayCount:=trunc(NextDate-PreviousDate+1);
  //行数(上部に曜日を表示するので+1する)
  RowCount:=DayCount div 7 + 1;

  //グリッドパネルのグリッドをクリア
  GPanel.ColumnCollection.Clear;
  GPanel.RowCollection.Clear;

  //グリッドパネルに行を追加
  GPanel.RowCollection.BeginUpdate();
  for Row := 0 to RowCount-1 do
  begin
    RowItem:=GPanel.RowCollection.Add();
    RowItem.SizeStyle:=TSizeStyle.ssPercent;
    RowItem.Value:=100/RowCount;
  end;
  GPanel.RowCollection.EndUpdate();

  //グリッドパネルに列を追加
  GPanel.ColumnCollection.BeginUpdate();
  for Col := 0 to 6 do
  begin
    ColumnItem:=GPanel.ColumnCollection.Add();
    ColumnItem.SizeStyle:=TSizeStyle.ssPercent;
    ColumnItem.Value:=100/7;
  end;
  GPanel.ColumnCollection.EndUpdate();

  //TLabelで曜日をグリッドに配置
  for Col := 0 to 6 do
  begin
    Lbl:=TLabel.Create(GPanel);
    Lbl.Parent:=GPanel;
    Lbl.Align:=alClient;
    Lbl.Layout:=tlCenter;
    Lbl.Caption:=Weeks[Col];
    Lbl.Alignment:=taCenter;
    Lbl.Font.Size:=12;
    if Col=0 then Lbl.Font.Color:=clRed;
    if Col=6 then Lbl.Font.Color:=clBlue;
    GPanel.ControlCollection.AddControl(Lbl, Col, 0);
  end;

  //TButtonで日付のボタンを配置
  GPDate:=PreviousDate;
  for Row:=1 to RowCount-1 do
  begin
    for Col := 0 to 6 do
    begin
      SButton:=TSpeedButton.Create(GPanel);
      SButton.Parent:=GPanel;
      SButton.Align:=alClient;
      SButton.Caption:=FormatDateTime('d', GPDate);
      SButton.Tag:=Trunc(GPDate);//年月日を入れておく
      SButton.StyleElements:=[seBorder];
      SButton.Font.Size:=12;
      SButton.OnClick:=SpeedButtonClick;
      SButton.Font.Color:=clBlack;
      if MonthOf(GPDate)<>m then
        SButton.Font.Color:=clGray;
      if GPDate=Date() then
      begin
        SButton.Font.Color:=clRed;
        SButton.Font.Style:=[TFontStyle.fsBold];
      end;
      GPanel.ControlCollection.AddControl(SButton, Col, Row);
      GPDate:=GPDate+1;
    end;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var y, m, i:Integer;
begin
  Panel1.Align:=alTop;
  Panel1.Caption:='';
  GridPanel1.Align:=alCLient;
  GridPanel1.Caption:='';


  //現在の年月を取得
  y:=YearOf(Date());
  m:=MonthOf(Date());

  //前後10年分の値を設定
  ComboBox1.Clear;
  ComboBox1.Style:=csDropDownList;
  for i := y-10 to y+10 do
  begin
    ComboBox1.Items.Add(IntToStr(i));
    if i=y then
      ComboBox1.ItemIndex:=ComboBox1.Items.Count-1;
  end;

  //月の設定
  ComboBox2.Clear;
  ComboBox2.Style:=csDropDownList;
  for i := 1 to 12 do
  begin
    ComboBox2.Items.Add(IntToStr(i));
    if i=m then
      ComboBox2.ItemIndex:=ComboBox2.Items.Count-1;
  end;

  //カレンダーを表示する
  CreateCalendar(
    GridPanel1,
    StrToInt(ComboBox1.Items[ComboBox1.ItemIndex]),
    StrToInt(ComboBox2.Items[ComboBox2.ItemIndex])
  );
end;

end.

実行する

メニューから「実行」⇒「実行」をクリックするとコンパイルと実行が行われ、カレンダーが表示されます。
ComboBox1の年やComboBox2の月を変更すると、カレンダーが切り替わります。
日付のボタンを押すと年月日がモーダルウィンドウで表示されます。