カスタム描画されたドキュメントキャンバスをズームするカスタムコントロールがあります。
AutoScrollを使用してみましたが、満足のいく結果が得られませんでした。AutoScrollPositionとAutoScrollMinSizeを(任意の順序で)連続して設定すると、ズームが変更されるたびにペイントが強制され、ジッターが発生します。これは、両方のプロパティを変更したときに、無効化ではなく更新を呼び出していたためだと思います。
ズームレベルまたはクライアントサイズが変更されるたびに、 AutoScrollをfalseに設定してHorizontalScrollプロパティとVerticalScrollプロパティを手動で設定しています。
int canvasWidth = (int)Math.Ceiling(Image.Width * Zoom) + PageMargins.Horizontal;
int canvasHeight = (int)Math.Ceiling(Image.Height * Zoom) + PageMargins.Vertical;
HorizontalScroll.Maximum = canvasWidth;
HorizontalScroll.LargeChange = ClientSize.Width;
VerticalScroll.Maximum = canvasHeight;
VerticalScroll.LargeChange = ClientSize.Height;
if (canvasWidth > ClientSize.Width)
{
HorizontalScroll.Visible = true;
}
else
{
HorizontalScroll.Visible = false;
HorizontalScroll.Value = 0;
}
if (canvasHeight > ClientSize.Height)
{
VerticalScroll.Visible = true;
}
else
{
VerticalScroll.Visible = false;
VerticalScroll.Value = 0;
}
int focusX = (int)Math.Floor((FocusPoint.X * Zoom) + PageMargins.Left);
int focusY = (int)Math.Floor((FocusPoint.Y * Zoom) + PageMargins.Top);
focusX = focusX - ClientSize.Width / 2;
focusY = focusY - ClientSize.Height / 2;
if (focusX < 0)
focusX = 0;
if (focusX > canvasWidth - ClientSize.Width)
focusX = canvasWidth - ClientSize.Width;
if (focusY < 0)
focusY = 0;
if (focusY > canvasHeight - ClientSize.Height)
focusY = canvasHeight - ClientSize.Height;
if (HorizontalScroll.Visible)
HorizontalScroll.Value = focusX;
if (VerticalScroll.Visible)
VerticalScroll.Value = focusY;
この場合、FocusPointは、ユーザーがフォーカスしているビットマップ内の座標を保持するPointF構造です(たとえば、マウスホイールでズームインすると、その時点での現在のマウスの位置にフォーカスします)。この機能はほとんどの場合機能します。
動作しないのはスクロールバーです。ユーザーがいずれかのスクロールバーをクリックして手動でスクロールしようとすると、両方とも0に戻り続けます。コード内の他の場所には設定していません。OnScroll()メソッドで次のように書いてみました。
if (se.ScrollOrientation == ScrollOrientation.VerticalScroll)
{
VerticalScroll.Value = se.NewValue;
}
else
{
HorizontalScroll.Value = se.NewValue;
}
Invalidate();
ただし、これにより、フリックや範囲外へのスクロールなど、非常に不安定な動作が発生します。
OnScrollのコードをどのように書くべきですか? base.OnScrollを試しましたが、AutoScrollがfalseに設定されている間は何もしませんでした。