−トップへ−

カレンダーを作る
その1 数字を並べる

はじめに

 今回は,カレンダーを作ってみます。今まではformを1つだけ使ったものでしたが,今回はfomr1でカレンダーを表示して,form2でカレンダーの設定をするようにしてみます。

基本的な考え方

 まず,カレンダーの設定をしてみます。数字はimageコンポーネントに書き込んでいきますが,ここでややこしいのが,日付によって表示する場所を変えていくことです。例えば,ある月の朔日(ついたち)が水曜日の場合,カレンダーは下のようになります。

 



1011
12131415









 このときの朔日の座標を(4,1)とした場合,4日の座標は(7,1)になり,その次が(1,2)にしなければなりません。

 これを考えていくために必要な日付関数を探してみると,「Dayofweek」というのがあります。これは特定の日付の曜日を数字で返すものです。
例えば特定の日付が日曜なら1を返し,月曜なら2,土曜日なら8を返します。

 このDayofweek関数で求めた朔日の整数値をweek,日付をdayとして,上の座標を求める式を考えてみます。

 上のカレンダーではweekが4になるので,朔日の座標は(week+day−1,1)になり,4日まではこの式で大丈夫です。しかし5日になるとx座標を1にして,y座標を1つ増やさなければなりません。これを満たす式を考えていくと下のような式になります。

 X座標…(week+day-2) mod 7+1
 Y座標…(week+day-2) div 7+1

 座標が決まれば,これを元に数字を表記する具体的な場所を求めることができます。
 例えばformの幅を400にした場合,
   X座標が1のとき…400÷8×1=50
   X座標が2のとき…400÷8×2=100
      :
   X座標が7のとき…400÷8×7=350
となります。
 
 また,縦方向については,1ヶ月の行数は最大で6行になります。また数字の上に曜日を書き込んだり,西暦や月を書き込む余白を確保するために,全体を10等分してその4段目から書き込むことにします。例えば,formの高さを400にした場合,
   Y座標が1のとき…400÷10×(1+3)=160
   Y座標が2のとき…400÷10×(2+3)=200
      :
   Y座標が6のとき…400÷10×(6+3)=360
となります。

 これを元に,今月のカレンダーを表示するプログラムを記述してみます。
 
 なお,下のプログラムでは,フォームの大きさや数字の大きさなどを,すべて1つの変数「size」によって表しています。そうすることで「size」の値を変更するだけで全体の大きさを変えることができます。
 
 まず,formにimegeコンポーネントを貼り付け,FormCreateを呼び出し,次に「makec」プロシージャを作成します。

 type
  TForm1 = class(TForm)
  Image1: TImage;
  procedure makec; //←これを記述して[Shift]+[Ctrl]+[C]をおすと,新しいprocedureが作成されます
  procedure FormCreate(Sender: TObject);
 private
  { Private 宣言 }
  ye,mo:string; //yeとmoは当日の西暦と月を表示するため
  size:integer; //sizeは全体の大きさを管理するため
 public
  { Public 宣言 }
 end;
  :
  :
  :
 procedure TForm1.FormCreate(Sender: TObject);
 begin
  ye:=formatdatetime('yyyy',date); //“今日”の西暦を求めます。
  mo:=formatdatetime('m',date); //“今日”の月を求めます。
  size:=400; //“size”をとりあえず400にしてみます。
  makec;
 end;
 
 procedure TForm1.makec;
  var
   i,week:integer;
 begin
  form1.ClientWidth:=size; //フォームの内側の幅を,変数“size”にする
  form1.ClientHeight:=size; //フォームの内側の高さを,変数“size”にする

  image1.Left:=0; //以下の4行でイメージコンポーネントをフォーム全体に広げる
  image1.Top:=0;
  image1.Width:=size;
  image1.Height:=size;
 
  week:=dayofweek(strtodate(ye+'/'+mo+'/1')); //“今月”の始まりの曜日を求める
  with image1.Canvas do begin
   brush.Color:=clwhite; //塗りつぶしの色を白にする
   fillrect(image1.ClientRect); //image1全体を塗りつぶす
   brush.Style:=bsclear; //塗りつぶしのスタイルを文字だけの塗りつぶしにする
     //これをbssolidにすると文字の周りをbrush.colorで指定した色で塗りつぶします。
   font.Size:=size div 20; //フォントのサイズをsizeの20分の1にする
                    //この大きさはいろいろ試して見てください。
   for i:=1 to 31 do begin //1日から31日まで繰り返します
    font.Color:=clblack; //フォントの色を黒にする
    textout(size*((week+i-2) mod 7+1) div 8 -textwidth(inttostr(i)) div 2,
        size*((week+i-2) div 7+4) div 10-textheight(inttostr(i)) div 2,
        inttostr(i)); //日付を書き込む
   end;
  end;
 end;
 
 end.

 以上のプログラムを実行すると,下図の様なフォームが現れます。
 (デスクトップは「クラシック表示」にしてあります。)
 ここでsizeの大きさを400からいろいろな数字に変えると全体の大きさが変わることがわかると思います。
 
 これで基本的な形は出来上がりました。しかしまだ「大の月」や「小の月」さらに2月の日付には対応していません。

 次回は,
  ・ 「大の月」や「小の月」,閏年などに対応させる
  ・ 「日」〜「土」の表示や月の表示,西暦や年号の表示をする
 ことなどをしていきます。

−トップへ−