移動の追跡
この例での OnMouseMove イベントハンドラとしての問題点は,最初の位置からではなく,直前のマウス位置から現在のマウス位置への描画を行うという点にあります。この問題は,描画位置を原点に戻してから現在の位置まで線を描くという方法で修正できます。
procedure TForm1.FormMouseMove(Sender: TObject;Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Drawing then
begin
Canvas.MoveTo(Origin.X, Origin.Y);{ ペンを始点に移動 }
Canvas.LineTo(X, Y);
end;
end;
void __fastcall TForm1::FormMouseMove(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
{
if (Drawing)
{
Canvas->MoveTo(Origin.x, Origin.y); // ペンを始点に移動
Canvas->LineTo(X, Y);
}
}
上記のコードは,現在のマウス位置を追跡しますが,中間的な線は消去しないため,どれが最終的な線なのかが判断できなくなります。したがって,直前の点がどこであったのかを保存しておいて,次の線を描く前に直前の線を消去する必要があります。この処理を行うために,MovePt フィールドを使用します。
MovePt と Origin を使って直前の線を消去できるように,MovePt に中間的な各線の終点を設定する必要があります。
procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
Drawing := True;
Canvas.MoveTo(X, Y);
Origin := Point(X, Y);
MovePt := Point(X, Y);{ この移動の開始位置を記録 }
end;
procedure TForm1.FormMouseMove(Sender: TObject;Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Drawing then
begin
Canvas.Pen.Mode := pmNotXor;{ XOR モードで描画,消去 }
Canvas.MoveTo(Origin.X, Origin.Y);{ ペンを始点に戻す }
Canvas.LineTo(MovePt.X, MovePt.Y);{ 前の線を消去 }
Canvas.MoveTo(Origin.X, Origin.Y);{ ペンを始点に戻す }
Canvas.LineTo(X, Y);{ 新しい線を描画 }
end;
MovePt := Point(X, Y);{ 次の移動のためにポイントを記録 }
Canvas.Pen.Mode := pmCopy;
end;
void __fastcall TForm1::FormMouseDown(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
{
Drawing = true; // 描画フラグをセット
Canvas->MoveTo(X, Y); // ペン位置を設定
Origin = Point(X, Y); // 線の開始位置を記録
MovePt = Point(X, Y); // 最後の終了位置を記録
}
void __fastcall TForm1::FormMouseMove(TObject *Sender, TMouseButton Button,
TShiftState Shift, int X, int Y)
{
if (Drawing)
{
Canvas->Pen->Mode = pmNotXor; // XOR モードで描画,消去
Canvas->MoveTo(Origin.x, Origin.y); // ペンを始点に移動
Canvas->LineTo(MovePt.x, MovePt.y); // 前の線を消去
Canvas->MoveTo(Origin.x, Origin.y); // ペンを始点に再移動
Canvas->LineTo(X, Y); // 新しい線を描画
}
MovePt = Point(X, Y); // 新しい終了位置を記録
Canvas->Pen->Mode = pmCopy;
}
これで,描画時の「ラバーバンド」効果が実現できました。ペンのモードを pmNotXor にすると,ペン色と背景色を排他演算した結果(つまりペンとも背景とも一致しない色)をさらに反転した色で描画します。このペンモードの特性は,一度めの描画は背景ともペンとも一致しないユニークな色で描画し,同じ部分をもう一度描画すると,元々の背景色に戻ることです。この例では,この特性を利用してマウス移動中の線を描画し,そして消去しています。線を描画した後でペンモードを pmCopy(デフォルト値)に戻すと,マウスボタンを放したときに最終的な線を描画できる状態が保証されます。