−トップへ−

時計を作る
その3 針をかき込む

針をかき込む

 今回は文字盤に,短針・長針・秒針を書き込んでみます。
 
 プログラムで実際に短針や長針を動かすことはできないので,一定間隔ごとに何もない文字盤に短針や長針を書き込み,それを表示するという方法をとります。
 そのため,針のない文字盤を保存しておくためにイメージコンポーネントをもう一つ追加しておきます。
 今までimage1コンポーネントに文字盤を作成したので,image1コンポーネントを非表示にして,新たにimage2コンポーネントを追加します。そして一定時間ごとにimage1のイメージをimage2にコピーし,image2に針を書き込むという方法をとります。
 
 次に針をかき込むときの注意点は,短針や長針,秒針の角度を何度にするかということです。例えば短針は分が変わればその角度を微妙に変えていく必要があります。
 具体的には,時をhour,分をmin,秒をsecというword型の変数に設定すると,それぞれの針の角度は下のようになります。
   短針…hour*30+min div 2
   長針…min*6+sec div 10
   秒針…sec*6
 
これを,記述しますが,あらかじめform1にimage2コンポーネントとtimer1コンポーネントを貼り付けて,timer1のイベントハンドラを呼び出しておきます。

 type
  TForm1 = class(TForm)
  Image1: TImage;
  procedure makeban; //←これを記述して,[Shift]+[Ctrl]+[C]を押すと新しいプロシージャが生成されます
  procedure FormCreate(Sender: TObject);
 private
  { Private 宣言 }
  size:integer; //sizeは時計の文字盤の半径の大きさにします
 public
  { Public 宣言 }
 end;
  :
  :
//関数=====================================================
function GetPoint(Center: TPoint; deg: Integer; len: Integer): TPoint;
begin
Result.x := Center.x + Round(deg * sin(len * pi /180));
Result.y := Center.y - Round(deg * cos(len * pi /180));
end;
//=========================================================
 
 この関数では,中心の座標をポイント型の変数(center),角度を整数型の変数(deg)
  中心からの長さを整数型の変数(len)として代入します。結果はポイント型で返します。
 

 procedure TForm1.FormCreate(Sender: TObject);
 begin
  size:=100; //sizeをとりあえず100にします
  form1.ClientWidth:=size*2; //フォームの内側の幅をsizeの2倍にします
  form1.ClientHeight:=size*2; //フォームの内側の高さをsizeの2倍にします
  form1.TransparentColor:=true; //フォームを透明にします
  form1.TransparentColorValue:=clred; //フォームの透明色を赤にします
  form1.Color:=clred; //フォームの色を赤にします
  image1.left:=0; //image1のX座標を0にします
  image1.Top:=0; //image1のY座標を0にします
  image1.Width:=form1.ClientWidth; //image1の幅をform1の内側の幅と同じにします
  image1.Height:=form1.ClientHeight; //image1の高さをform1の内側の高さと同じにします
  image1.Visible:=false; //image1を非表示にします
  image2.left:=0; //image2をimage1と同じ大きさにします
  image2.Top:=0; //以下同様
  image2.Width:=form1.ClientWidth;
  image2.Height:=form1.ClientHeight;
  makeban; //←これを記述
 end;

 procedure TForm1.makeban; //これが新しく生成されたプロシージャです
 var
  w,i:integer; //変数wを整数宣言します(文字盤の枠の太さを表すために使用します)
         //変数iを整数宣言します
  center:TPoint; //centerをポイント型の変数として宣言します
 begin
  w:=size div 30; //wの大きさをsizeの30分の1にしてみます
  with image1.Canvas do begin
   brush.Color:=clred; //ブラシの色を赤にして
   fillrect(image1.ClientRect); //image1のcanvasを赤で塗りつぶします(これで透明になります)
   brush.Color:=$fafafa; //次にブラシの色を灰色っぽい白にして
   brush.Style:=bssolid; //ブラシの塗りつぶしのスタイルを「bssolid」にします
   pen.color:=$cccccc; //ペンの色を灰色にします(これが枠の色になります)
   pen.width:=w * 2; //ペンの太さを変数「w」の2倍にします
   Ellipse(w,w,image1.Width-w,image1.Height-w); //円を描きます

    //目盛を刻む
   w:=size *86 div 100; //目盛を書き込む場所をsizeの長さの86%にしてみます
   cent.X:=size; //中心のX座標をsizeにする
   cent.Y:=size; //中心のY座標をsizeにする
   pen.Width:=1; //目盛を書き込む太さを1にする
   pen.Color:=clblack; //目盛の色を黒にする
   for i:=1 to 60 do begin
    moveto(getpoint(cent,w,i*6).X,getpoint(cent,w,i*6).Y);
    lineto(getpoint(cent,w+3,i*6).x,getpoint(cent,w+3,i*6).y);
   end;
   w:=size *84 div 100; //目盛を書き込む場所をsizeの長さの84%にしてみます
   pen.Width:=3; //目盛の太さを3にする
   for i:=0 to 11 do begin
    moveto(getpoint(cent,w,i*30).X,getpoint(cent,w,i*30).Y);
    lineto(getpoint(cent,w+4,i*30).x,getpoint(cent,w+4,i*30).y);
   end;
  end;
 end;

 procedure TForm1.Timer1Timer(Sender: TObject); //timer1のイベントハンドラを呼び出します
 var
  hour,min,sec,msec:word; //hour,min,sec,msecをword型の変数にします
  cent:tpoint; //centをポイント型の変数にします
  w1,w2:integer; //w1とw2を整数型の変数にします
 begin
  image2.Canvas.CopyRect(image1.Canvas.ClipRect,image1.Canvas,image2.Canvas.ClipRect); //image1の文字盤をimage2にコピーする
  DecodeTime(Now, Hour, Min, Sec,msec); //現在時刻を時間,分,秒,ミリ秒に分解する
  with image2.Canvas do begin //image1のcanvasにいろいろかき込みます
   cent.x:=size; //ポイント型の変数centに座標を入力します
   cent.y:=size; //
    //短針を書き込む
   w1:=size div 10; //短針の反対側の長さを文字盤の10%にします(ここは0でもよいのですが少し長くしたほうが本物らしく見えます)
   w2:=size div 2; //短針の長さを文字盤の50%にします
   pen.Width:=5; //ペンの太さを5ポイントにします
   moveto(getpoint(cent,w1,hour*30+min div 2+180).x,getpoint(cent,w1,hour*30+min div 2+180).y); //線を引く始点を指定します
   lineto(getpoint(cent,w2,hour*30+min div 2).x,getpoint(cent,w2,hour*30+min div 2).y); //線を引く終点を指定して線を引きます
    //長針を書き込む
   w1:=size div 10; //長針の反対側の長さを文字盤の10%にします
   w2:=size*7 div 10; //長針の長さを文字盤の70%にします
   pen.Width:=3; //ペンの太さを3ポイントにします
   moveto(getpoint(cent,w1,min*6+sec div 10+180).x,getpoint(cent,w1,min*6+sec div 10+180).y); //線を引く始点を指定します
   lineto(getpoint(cent,w2,min*6+sec div 10).x,getpoint(cent,w2,min*6+sec div 10).y); //線を引く終点を指定して線を引きます
    //秒針を書き込む
   w1:=size div 10; //秒針の反対側の長さを文字盤の10%にします
   w2:=size*8 div 10; //秒針の長さを文字盤の80%にします
   pen.Width:=1; //ペンの太さを1ポイントにします
   moveto(getpoint(cent,w1,sec*6+180).x,getpoint(cent,w1,sec*6+180).y); //線を引く始点を指定します
   lineto(getpoint(cent,w2,sec*6).x,getpoint(cent,w2,sec*6).y); //線を引く終点を指定して線を引きます
  end;
 end;

 end.

 これを実行すると,下のようになります。



 次回は,周りの枠を消して,時計をマウスで移動できるようにします。

−トップへ−