【C#】【Form】HScrollBar / VScrollBar ~ 独自スクロールバーの実装 ~

  ■ はじめに

 * HScrollBar / VScrollBar について、学ぶ
  => 大変...

  補足:ScrollableControlについて

 * 独自スクロールバーは、とても大変なので、
   ScrollableControlを継承させたクラスを作ることも検討した方がいいかも...
http://wisdom.sakura.ne.jp/system/msnet/msnet_win23.html
https://www.cyotek.com/blog/creating-a-scrollable-and-zoomable-image-viewer-in-csharp-part-4#files

 

  ■ HScrollBar / VScrollBar

  HScrollBar

 * 水平(Horizontal)方向のスクロールバー
  => つまり、横スクロールバー
https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.forms.hscrollbar?view=netframework-4.7.2

  VScrollBar

 * 垂直(Vertical)方向のスクロールバー
  => つまり、縦スクロールバー
https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.forms.vscrollbar?view=netframework-4.7.2

 

  ■ 主なプロパティ

  【1】Value

 * スクロール バーのスクロール ボックスの位置に対応する値(規定は、0)

  【2】Minimum / Maximum

 * Valueプロパティ の 最小値/最大値
  => ただ、実際は、「ScrollBar.Minimum ≦ Value ≦ 1 + ScrollBar.Maximum - ScrollBar.LargeChange」
  => 詳細は、以下の「使用上の注意」を参照。

  【3】LargeChange / SmallChange

LargeChange
 * バーと左右端の矢印の間をクリックした場合の移動量
 * 設定する際は、「表示領域の幅」にすると、うまくいく
  => 以下のサイトの図付きの説明が分かりやすい
https://www.hesperus.net/csharp/scrollbar.aspx
SmallChange
 * 左右端/上下端の矢印をクリックした場合の移動量

  【4】Size

 * スクロールバーの大きさ

  【5】Location

 * スクロールバーの位置

  使用上の注意

 * Valueプロパティの取る最大値はMaximumではない
公式サイト
https://docs.microsoft.com/ja-jp/dotnet/api/system.windows.forms.scrollbar.maximum?view=netframework-4.7.2
より抜粋
~~~~~~~~~~~~
最大値は、プログラムによってのみアクセスできます。
スクロール バーの値は、実行時にユーザーとの対話が最大値に到達できません。 
ユーザーの操作によって到達可能な最大値が 1 だけでなく、Maximumプロパティの値を引いた、LargeChangeプロパティの値。
~~~~~~~~~~~~
 => ユーザ操作によって到達可能な最大値は「1 + ScrollBar.Maximum - ScrollBar.LargeChange」
 => 以下のサイトの図付きの説明が分かりやすい
https://www.hesperus.net/csharp/scrollbar.aspx

 

  ■ 主なイベント

  【1】ValueChanged

 * Value プロパティが変更されると発生

  【2】Scroll

 * スクロールした際に発生
  => 以下の公式サイトにサンプルコードあり。
https://docs.microsoft.com/en-us/dotnet/api/system.windows.forms.scrollbar.scroll?redirectedfrom=MSDN&view=netframework-4.7.2

 

  ■ サンプル

http://www.java2s.com/Tutorial/CSharp/0460__GUI-Windows-Forms/ScrollBarValuechangedeventhandler.htm
を参考にした。
問題はあるが、とりあえず、これで、、、

  コントロール構成

 + Panel (Anchor:Top, Bottom, Left, Right)
    + VScrollBar
    + HScrollBar
    + PictureBox

  コード

using System.Drawing;
using System.Windows.Forms;

namespace SampleForm
{
  public partial class Form1 : Form
  {
    private Image image;

    public Form1()
    {
      InitializeComponent();
    }

    private void Form1_Load(object sender, System.EventArgs e)
    {
      this.image = Image.FromFile(@"C:\helloworld.gif");

      this.pictureBox1.Size = new Size(image.Size.Width, image.Size.Height);
      this.pictureBox1.Image = this.image;

      // スクロールバーの位置
      this.hScrollBar1.Location = new Point(0, this.panel1.Height - this.hScrollBar1.Height);
      // スクロールバーの大きさ
      this.hScrollBar1.Width = this.panel1.Width - this.vScrollBar1.Width;

      this.hScrollBar1.Minimum = 0;
      this.hScrollBar1.Maximum = this.image.Width;
      this.hScrollBar1.LargeChange = this.panel1.ClientSize.Width;
      this.hScrollBar1.SmallChange = this.hScrollBar1.LargeChange / 20;
      this.hScrollBar1.Value = 0;

      // スクロールバーの位置
      this.vScrollBar1.Location = new Point(this.panel1.Width - this.vScrollBar1.Width, 0);
      // スクロールバーの大きさ
      this.vScrollBar1.Height = this.panel1.Height - this.hScrollBar1.Height;

      this.vScrollBar1.Minimum = 0;
      this.vScrollBar1.Maximum = this.image.Height;
      this.vScrollBar1.LargeChange = this.panel1.ClientSize.Height;
      this.vScrollBar1.SmallChange = this.vScrollBar1.LargeChange / 20;
      this.vScrollBar1.Value = 0;

      // pictureBoxの大きさを調整
      if (this.hScrollBar1.Visible)
      {
        this.pictureBox1.Height = this.panel1.Height - this.hScrollBar1.Height;
      }
      else
      {
        this.pictureBox1.Height = this.panel1.Height;
      }
      if (this.vScrollBar1.Visible)
      {
        this.pictureBox1.Width = this.panel1.Width - this.vScrollBar1.Width;
      }
      else
      {
        this.pictureBox1.Width = this.panel1.Width;
      }
    }

    private void Form1_Resize(object sender, System.EventArgs e)
    {
      // スクロールバーの位置
      this.hScrollBar1.Location = new Point(0, this.panel1.Height - this.hScrollBar1.Height);
      // スクロールバーの大きさ
      this.hScrollBar1.Width = this.panel1.Width - this.vScrollBar1.Width;

      // スクロールバーの位置
      this.vScrollBar1.Location = new Point(this.panel1.Width - this.vScrollBar1.Width, 0);
      // スクロールバーの大きさ
      this.vScrollBar1.Height = this.panel1.Height - this.hScrollBar1.Height;

      // pictureBoxの大きさを調整
      if (this.hScrollBar1.Visible)
      {
        this.pictureBox1.Height = this.panel1.Height - this.hScrollBar1.Height;
      }
      else
      {
        this.pictureBox1.Height = this.panel1.Height;
      }
      if (this.vScrollBar1.Visible)
      {
        this.pictureBox1.Width = this.panel1.Width - this.vScrollBar1.Width;
      }
      else
      {
        this.pictureBox1.Width = this.panel1.Width;
      }

      this.pictureBox1.Refresh();
    }

    private void vScrollBar1_ValueChanged(object sender, System.EventArgs e)
    {
      this.pictureBox1.Top = (this.panel1.Size.Height - image.Size.Height) * this.vScrollBar1.Value / (this.vScrollBar1.Maximum - this.vScrollBar1.LargeChange + 1);
    }

    private void hScrollBar1_ValueChanged(object sender, System.EventArgs e)
    {
      this.pictureBox1.Left = (this.panel1.Size.Width - image.Size.Width) * (this.hScrollBar1.Value) / (this.hScrollBar1.Maximum - this.hScrollBar1.LargeChange + 1);
    }

    private void vScrollBar1_Scroll(object sender, ScrollEventArgs e)
    {
      var vScrollBar = sender as VScrollBar;
      this.Text = "VScrollBar Value" + vScrollBar.Value + ", OldValue : " + e.OldValue + ", NewValue : " + e.NewValue;
    }

    private void hScrollBar1_Scroll(object sender, ScrollEventArgs e)
    {
      var hScrollBar = sender as HScrollBar;
      this.Text = "HScrollBar Value" + hScrollBar.Value + ", OldValue : " + e.OldValue + ", NewValue : " + e.NewValue;

    }
  }
}

 

 

  関連記事

  Windows Form ~ 目次 ~

https://blogs.yahoo.co.jp/dk521123/8054245.html

  スクロール に関するあれこれ

https://blogs.yahoo.co.jp/dk521123/37838702.html\

   HScrollBar / VScrollBar でArgumentOutOfRangeExceptionが発生する