ウィンドウコントロールのスクロールバーのイベントを検出する

ウィンドウコントロールに追加したスクロールバーのイベントを取得する方法を紹介します。

概要

ウィンドウコントロールに追加したスクロールバーのイベントを取得します。イベントの検出はWndProcメソッドをオーバーライドしWindowメッセージを取得することで実現します。
コントロールへのスクロールバーの追加方法はこちらの記事を参照してください。

プログラム

コード

MyConponent.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WindowControlWithScrollBarAndEvent
{
  public partial class MyComponent : Control
  {
    public enum ScrollBarsMode { None, Vertical, Horizontal, Both }

    private ScrollBarsMode scrollBarsMode;
    private TextBox debugTextBox;

    public ScrollBarsMode ScrollBars {
      set
      {
        scrollBarsMode = value;
        this.UpdateStyles();
      }
      get
      {
        return scrollBarsMode;
      }
    }

    public TextBox DebugTextBox {
      set
      {
        debugTextBox = value;
      }

      get
      {
        return debugTextBox;
      }
    }

    public MyComponent()
    {
      InitializeComponent();
    }

    public MyComponent(IContainer container)
    {
      container.Add(this);

      InitializeComponent();
    }

    protected override void WndProc(ref Message message)
    {
      base.WndProc(ref message);

      switch (message.Msg) {
        case WindowsConst.WM_HSCROLL:
          if (debugTextBox != null) {
            debugTextBox.Text += "WM_HSCROLL\r\n";

            short lo = LoWord((long)message.WParam);
            switch (lo) {
              case WindowsConst.SB_ENDSCROLL:
                debugTextBox.Text += "SB_ENDSCROLL\r\n";
                break;
              case WindowsConst.SB_LEFT:
                debugTextBox.Text += "SB_LEFT\r\n";
                break;
              case WindowsConst.SB_RIGHT:
                debugTextBox.Text += "SB_RIGHT\r\n";
                break;
              case WindowsConst.SB_LINELEFT:
                debugTextBox.Text += "SB_LINELEFT\r\n";
                break;
              case WindowsConst.SB_LINERIGHT:
                debugTextBox.Text += "SB_LINERIGHT\r\n";
                break;
              case WindowsConst.SB_PAGELEFT:
                debugTextBox.Text += "SB_PAGELEFT\r\n";
                break;
              case WindowsConst.SB_PAGERIGHT:
                debugTextBox.Text += "SB_PAGERIGHT\r\n";
                break;
              case WindowsConst.SB_THUMBPOSITION:
                debugTextBox.Text += "SB_THUMBPOSITION\r\n";
                break;
              case WindowsConst.SB_THUMBTRACK:
                debugTextBox.Text += "SB_THUMBTRACK\r\n";
                break;
            }
          }
          break;
        case WindowsConst.WM_VSCROLL:
          if (debugTextBox != null) {
            debugTextBox.Text += "WM_VSCROLL\r\n";

            short lo = LoWord((long)message.WParam);
            switch (lo) {
              case WindowsConst.SB_BOTTOM:
                debugTextBox.Text += "SB_BOTTOM\r\n";
                break;
              case WindowsConst.SB_ENDSCROLL:
                debugTextBox.Text += "SB_ENDSCROLL\r\n";
                break;
              case WindowsConst.SB_LINEDOWN:
                debugTextBox.Text += "SB_LINEDOWN\r\n";
                break;
              case WindowsConst.SB_LINEUP:
                debugTextBox.Text += "SB_LINEUP\r\n";
                break;
              case WindowsConst.SB_PAGEDOWN:
                debugTextBox.Text += "SB_PAGEDOWN\r\n";
                break;
              case WindowsConst.SB_PAGEUP:
                debugTextBox.Text += "SB_PAGEUP\r\n";
                break;
              case WindowsConst.SB_THUMBPOSITION:
                debugTextBox.Text += "SB_THUMBPOSITION\r\n";
                break;
              case WindowsConst.SB_THUMBTRACK:
                debugTextBox.Text += "SB_THUMBTRACK\r\n";
                break;
              case WindowsConst.SB_TOP:
                debugTextBox.Text += "SB_TOP\r\n";
                break;
            }
          }
          break;

      }
    }

    protected override CreateParams CreateParams {
      get
      {
        CreateParams cp = base.CreateParams;
        int ScrollBarFlag = 0;

        switch (scrollBarsMode) {
          case ScrollBarsMode.None:
            ScrollBarFlag = 0;
            break;
          case ScrollBarsMode.Horizontal:
            ScrollBarFlag = WindowsConst.WS_HSCROLL;
            break;
          case ScrollBarsMode.Vertical:
            ScrollBarFlag = WindowsConst.WS_VSCROLL;
            break;
          case ScrollBarsMode.Both:
            ScrollBarFlag = WindowsConst.WS_HSCROLL + WindowsConst.WS_VSCROLL;
            break;
        }

        cp.Style |= ScrollBarFlag;
        return cp;
      }
    }

    protected short LoWord(long input)
    {
      return (short)((int)input & 0xFFFF);
    }

    protected short HiWord(long input)
    {
      return (short)((int)input >> 16);
    }

    protected long MakeWParam(short l, short h)
    {
      return MakeLong(l, h);
    }

    protected long MakeLong(short a, short b)
    {
      return a & 0xFFFF | b & 0XFFF << 16;
    }

  }
}

WindowsConst.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace WindowControlWithScrollBarAndEvent
{
  internal class WindowsConst
  {
    // window style constants for scrollbars
    public const int WS_VSCROLL = 0x00200000;
    public const int WS_HSCROLL = 0x00100000;
    public const int WM_LBUTTONDOWN = 0x00000201;
    public const int WM_RBUTTONDOWN = 0x00000204;

    public const int WM_HSCROLL = 0x00000114;
    public const int WM_VSCROLL = 0x00000115;

    /*
     * Scroll Bar Commands
     */
    public const int SB_LINEUP = 0;
    public const int SB_LINELEFT = 0;
    public const int SB_LINEDOWN = 1;
    public const int SB_LINERIGHT = 1;
    public const int SB_PAGEUP = 2;
    public const int SB_PAGELEFT = 2;
    public const int SB_PAGEDOWN = 3;
    public const int SB_PAGERIGHT = 3;
    public const int SB_THUMBPOSITION = 4;
    public const int SB_THUMBTRACK = 5;
    public const int SB_TOP = 6;
    public const int SB_LEFT = 6;
    public const int SB_BOTTOM = 7;
    public const int SB_RIGHT = 7;
    public const int SB_ENDSCROLL = 8;
  }
}

解説

コントロールへスクロールバーを表示する部分のコードはこちらの記事を参照してください。
WndProcメソッドをオーバーライドしWindowメッセージを取得します。 コントロールのスクロールバーがクリックされると、縦方向スクロールバーの場合はWM_VSCROLLが、横方向スクロールバーの場合はWM_VSCROLLメッセージがコントロールに送られます。 WndoProcメソッドでそれらのイベントを受け取り、デバッグ用のテキストボックスにその値を表示します。

縦方向スクロールバーでの上下ボタン判別、横方向スクロールバーでの左右ボタンの判別は、WindowメッセージのWParamの値で判別します。 WParamの値を判定することで、ボタンがクリックされたか、ページスクロールか、Thumbがドラッグされたかを調べることができます。

メインフォーム

コンポーネントを配置するアプリケーション部は以下のUIとコードを用意します。

UI

下図のフォームを作成します。作成したウィンドウコントロールのコンポーネントとボタンを配置します。 MyComponentのScrollBarsプロパティをBothに設定します。

ウィンドウコントロールのスクロールバーのイベントを検出する:画像1

コード

以下のコードを記述します。ButtonコントロールのClickイベントを実装します。

namespace WindowControlWithScrollBarAndEvent
{
  public partial class FormMain : Form
  {
    public FormMain()
    {
      InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
      FormLogView f = new FormLogView();
      myComponent1.DebugTextBox = f.textBox1;
      f.Show();
    }
  }
}

解説

Button1をクリックするとコンポーネントのDebugTextBoxにログビューのテキストボックスを設定し、ログビューのフォームを表示します。

ログビュー

UI

下図のフォームを作成します。MutilineプロパティをTrueに設定したテキストボックスを配置します。

ウィンドウコントロールのスクロールバーのイベントを検出する:画像2

注意
TextBoxのModifiersプロパティを"Public"に設定する必要があります。

コード

ログビューのコードは以下です。追加するコードはありません。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace WindowControlWithScrollBarAndEvent
{
  public partial class FormLogView : Form
  {
    public FormLogView()
    {
      InitializeComponent();
    }
  }
}

実行結果

プロジェクトを実行します。下図のウィンドウが表示されます。
ウィンドウコントロールのスクロールバーのイベントを検出する:画像3

Button1をクリックします。ログビューのウィンドウが表示され、下図の状態になります。
ウィンドウコントロールのスクロールバーのイベントを検出する:画像4

コントロールのスクロールバーをクリックするとデバッグウィンドウにメッセージが表示されます。
ウィンドウコントロールのスクロールバーのイベントを検出する:画像5
ウィンドウコントロールのスクロールバーのイベントを検出する:画像6
ウィンドウコントロールのスクロールバーのイベントを検出する:画像7
ウィンドウコントロールのスクロールバーのイベントを検出する:画像8

AuthorPortraitAlt
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
作成日: 2011-11-19
Copyright © 1995–2025 iPentec all rights reserverd.