ウィンドウコントロールのスクロールバー情報の取得と設定

ウィンドウコントロールのスクロールバーの情報を取得、設定するコードを紹介します。

ウィンドウコントロールのスクロールバーの情報の取得はGetScrollInfo() Windows APIを、スクロールバーの設定はSetScrollInfo() Windows APIを用います。

コード

VisualComponent.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Security.Permissions;
using System.Drawing;
using System.Runtime.InteropServices;

namespace WinformVisualComponent
{
  public partial class VisualComponent : Control
  {
    [StructLayout(LayoutKind.Sequential)]
    struct SCROLLINFO
    {
      public uint cbSize;
      public uint fMask;
      public int nMin;
      public int nMax;
      public uint nPage;
      public int nPos;
      public int nTrackPos;
    }

    private enum ScrollBarDirection
    {
      SB_HORZ = 0,
      SB_VERT = 1,
      SB_CTL = 2,
      SB_BOTH = 3
    }

    private enum ScrollInfoMask
    {
      SIF_RANGE = 0x0001,
      SIF_PAGE = 0x0002,
      SIF_POS = 0x0004,
      SIF_DISABLENOSCROLL = 0x0008,
      SIF_TRACKPOS = 0x0010,
      SIF_ALL = SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS
      //SIF_ALL = SIF_RANGE + SIF_PAGE + SIF_POS + SIF_TRACKPOS
    }

    [DllImport("user32.dll")]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool GetScrollInfo(IntPtr hwnd, int fnBar, ref SCROLLINFO lpsi);

    [DllImport("user32.dll")]
    static extern int SetScrollInfo(IntPtr hwnd, int fnBar, [In] ref SCROLLINFO lpsi,
      bool fRedraw);

    public enum ScrollBarsMode { None, Vertical, Horizontal, Both }

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

    public VisualComponent()
    {
      InitializeComponent();
    }

    public VisualComponent(IContainer container)
    {
      container.Add(this);
      InitializeComponent();
    }

    protected override CreateParams CreateParams
    {
      get
      {
        new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Demand();

        CreateParams cp = base.CreateParams;
        //cp.Style = cp.Style + WS_HSCROLL + WS_VSCROLL;
        
        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 override void OnPaint(PaintEventArgs e)
    {
      base.OnPaint(e);
    }

    public void SetVScrollBar(int Position, uint Page, int nMin, int nMax, out int TrackPosition)
    {
      SCROLLINFO VScrInfo = new SCROLLINFO();
      GetScrollInfo(this.Handle, (int)ScrollBarDirection.SB_VERT, ref VScrInfo);
      VScrInfo.cbSize = (uint)Marshal.SizeOf(VScrInfo);
      VScrInfo.nPos = Position;
      VScrInfo.nPage = Page;
      VScrInfo.nMin = nMin;
      VScrInfo.nMax = nMax;
      TrackPosition = VScrInfo.nTrackPos;

      VScrInfo.fMask = (int)ScrollInfoMask.SIF_POS + (int)ScrollInfoMask.SIF_PAGE 
        + (int)ScrollInfoMask.SIF_RANGE + (int)ScrollInfoMask.SIF_DISABLENOSCROLL;
      SetScrollInfo(this.Handle, (int)ScrollBarDirection.SB_VERT, ref VScrInfo, true);
    }
  }
}

アプリケーション部(UI)

下図のUIを用意します。使用するのは配置したカスタムコンポーネントと"SetVScrollBar"のボタンです。

アプリケーション部(コード)

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

namespace WinformVisualComponent
{
  public partial class SubFormScroll : Form
  {
    public SubFormScroll()
    {
      InitializeComponent();
    }

    private void button_SetVScrollBar_Click(object sender, EventArgs e)
    {
      visualComponent1.ScrollBar = ScrollBarsMode.Vertical;
      int TrackPos;
      visualComponent1.SetVScrollBar(0, 100,0,200, out TrackPos);
    }
  }
}

解説

SetVScrollBarメソッドで縦方向スクロールバーの情報を設定します。SCROLLINFOのnPosはスクロールバーのスクロール(つまみ)位置、nPageはスクロールバーのページスクロール(つまみの上下をクリックした際)でのスクロール量、nMinはスクロールバーの最小値の値、nMaxはスクロールバーの最大値の値になります。
nTrackPosはGetScrollInfo()関数をSIF_TRACKPOSフラグを設定して呼び出した場合、現在のスクロールバーのつまみの位置を返します。

補足

横方向スクロールバーの情報取得、設定をする場合はGetScrollInfo, SetScrollInfoの台に引数にSB_HORZを指定します。
    public void SetHScrollBar(int Position, uint Page, int nMin, int nMax, out int TrackPosition)
    {
      SCROLLINFO VScrInfo = new SCROLLINFO();
      GetScrollInfo(this.Handle, (int)ScrollBarDirection.SB_HORZ, ref VScrInfo);
      VScrInfo.cbSize = (uint)Marshal.SizeOf(VScrInfo);
      VScrInfo.nPos = Position;
      VScrInfo.nPage = Page;
      VScrInfo.nMin = nMin;
      VScrInfo.nMax = nMax;
      TrackPosition = VScrInfo.nTrackPos;

      VScrInfo.fMask = (int)ScrollInfoMask.SIF_POS + (int)ScrollInfoMask.SIF_PAGE 
        + (int)ScrollInfoMask.SIF_RANGE + (int)ScrollInfoMask.SIF_DISABLENOSCROLL;
      SetScrollInfo(this.Handle, (int)ScrollBarDirection.SB_HORZ, ref VScrInfo, true);
    }

実行結果

実行直後で縦方向スクロールバーを表示した状態です。


"SetVScrollBar"ボタンを押しスクロールバーのスクロール範囲を設定後の画面です。スクロール範囲が0~200に対してページ幅が100なのでつまみがスクロールバーの長さの半分になっています。



著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用
掲載日: 2011-11-28
iPentec all rights reserverd.