手のひらツールの実装

画像などが画面に入りきらずスクロールバーが表示されている場合に,マウスのドラッグでスクロールさせる機能(所謂,Adobe Reader などの「手のひらツール」)を実装する必要があったので調べてみました.

スクロールバーの表示

手のひらツールの実装の前に,スクロールバーの表示のさせ方.画像などを表示させる場合には PictureBox クラス (System.Windows.Forms) を使う事になりますが,単にこれを使っただけではスクロールバーは表示されず,Panel クラス (System.Windows.Forms) と併用する必要があるようです.

必要な手順は,以下の通り.

  1. Panel を配置し,AutoScroll を True に設定する.
  2. Panel の内部に PictureBox を配置し,SizeMode を AutoSize に設定する.

MouseMove イベントで手のひらツールを実装する

本題です.手のひらツールを実装するためには,MouseMove イベントが発生するたびに座標を計算して Panel の AutoScrollPosition を更新していきます.ただし,MouseMove イベントは,マウスを押しながら動かした場合 (Drag) でも押さずに動かした場合 (ただの Move) でも発生してしまうため,マウスが押下されているかどうかの状態を内部で保持しておきます.

具体的なコードは,以下のような形になります.

private bool is_mouse_down_ = false;
private Point origin_;

private void pictureBox_MouseDown(object sender, MouseEventArgs e) {
    origin_ = pictureBox1.Parent.PointToScreen(e.Location);
    Cursor.Current = Cursors.Cross; // マウスカーソルの見た目を変更
    is_mouse_down_ = true;
}

private void pictureBox_MouseUp(object sender, MouseEventArgs e) {
    is_mouse_down_ = false;
    Cursor.Current = Cursors.Default;
}

private void pictureBox_MouseMove(object sender, MouseEventArgs e) {
    if (is_mouse_down_) {
        var current = pictureBox1.PointToScreen(e.Location);
        int x = current.X - origin_.X;
        int y = current.Y - origin_.Y;
        panel1.AutoScrollPosition = new Point(-x, -y);
    }
}

渡された座標をそのまま使用すると,AutoScrollPosition の座標を変更した時点でマウスの(相対)座標も変わってしまうため,おかしな挙動になってしまうようです.そのため,PointToScreen() を利用します(参考:ドラッグでスクロール: DOBON.NETプログラミング掲示板過去ログ).

この際,開始時の座標の計算は Panel.PointToScreen() を利用した方が楽なようです.座標を計算する場合には,既にスクロールされている分の座標も考慮して新たな座標を計算しなければなりませんが,Panel.PointToScree() はスクロール分も合わせた(?)座標を返してくれるようです.

この機能を実装した適当なサンプルプログラムは,http://cielquis.net/download/DragScroll_20100716.zip からダウンロードできます.

このエントリをつぶやく このWebページのtweets