【winForm】でコントローラーを自作する
あまり僕はwinFormでコントローラーを作成することはない
大体のものがそろっているからだ
ただデータを絞る上でレンジスライダーが必要になったので作成方法を残しておく
最終的な動作
手順と説明
コントローラーフォルダの作成
フォルダにRangeSlider.csファイルを作成する
必要な項目
- スライダーが取り得る最小値と最大値
- スライダーの現在の下限値と上限値
- 値が変更されたときに発生するイベント
- スライダーのハンドルとトラックを描画するためのメソッド
- マウス操作に対応するイベントハンドラ
- イベントハンドラをドラッグしている間にスライダーの値の更新
コード全体
using System;
using System.Drawing;
using System.Windows.Forms;
public class RangeSlider : UserControl
{
// 最小値、最大値、現在の下限値、上限値を保持する変数
private int _minimum = 0;
private int _maximum = 100;
private int _lowerValue = 10;
private int _upperValue = 90;
// ドラッグ操作の状態を追跡するフラグ
private bool isDraggingLower;
private bool isDraggingUpper;
// ドラッグが開始された時のマウスのX座標
private int dragStartX;
// Minimum と Maximum はスライダーの範囲を設定するプロパティ
public int Minimum
{
get => _minimum;
set { _minimum = value; Invalidate(); }
}
public int Maximum
{
get => _maximum;
set { _maximum = value; Invalidate(); }
}
// LowerValue と UpperValue はスライダーの選択範囲を設定するプロパティ
public int LowerValue
{
get => _lowerValue;
set
{
if (_lowerValue != value)
{
_lowerValue = value;
ValueChanged?.Invoke(this, EventArgs.Empty);
Invalidate();
}
}
}
public int UpperValue
{
get => _upperValue;
set
{
if (_upperValue != value)
{
_upperValue = value;
ValueChanged?.Invoke(this, EventArgs.Empty);
Invalidate();
}
}
}
// ValueChanged はプロパティの値が変更されたときに発火するイベント
public event EventHandler ValueChanged;
// OnPaint はコントロールの描画処理を担う
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
Graphics g = e.Graphics;
// スライダーのトラック(線)を描画
g.DrawLine(Pens.Black, 0, Height / 2, Width, Height / 2);
// 下限と上限のハンドルを描画
int lowerX = GetHandlePosition(LowerValue);
g.FillRectangle(Brushes.Blue, lowerX - 5, (Height / 2) - 10, 10, 20);
int upperX = GetHandlePosition(UpperValue);
g.FillRectangle(Brushes.Red, upperX - 5, (Height / 2) - 10, 10, 20);
}
// コンストラクタでマウスイベントを登録
public RangeSlider()
{
this.MouseDown += RangeSlider_MouseDown;
this.MouseMove += RangeSlider_MouseMove;
this.MouseUp += RangeSlider_MouseUp;
}
// マウスが押されたときの処理
private void RangeSlider_MouseDown(object sender, MouseEventArgs e)
{
int lowerHandleX = GetHandlePosition(LowerValue);
int upperHandleX = GetHandlePosition(UpperValue);
if (e.X >= lowerHandleX - 5 && e.X <= lowerHandleX + 5)
{
isDraggingLower = true;
dragStartX = e.X;
}
else if (e.X >= upperHandleX - 5 && e.X <= upperHandleX + 5)
{
isDraggingUpper = true;
dragStartX = e.X;
}
}
// マウスが動いたときの処理
private void RangeSlider_MouseMove(object sender, MouseEventArgs e)
{
if (isDraggingLower)
{
UpdateHandlePosition(ref _lowerValue, e.X);
}
else if (isDraggingUpper)
{
UpdateHandlePosition(ref _upperValue, e.X);
}
}
// マウスボタンが離されたときの処理
private void RangeSlider_MouseUp(object sender, MouseEventArgs e)
{
isDraggingLower = false;
isDraggingUpper = false;
}
// ハンドルの位置を計算するヘルパーメソッド
private int GetHandlePosition(int value)
{
return (int)((value - _minimum) / (double)(_maximum - _minimum) * Width);
}
// ハンドルの位置を更新するメソッド
private void UpdateHandlePosition(ref int value, int mouseX)
{
int newValue = (int)(_minimum + (mouseX / (double)Width) * (_maximum - _minimum));
newValue = Math.Max(_minimum, Math.Min(newValue, _maximum));
if (isDraggingLower)
{
newValue = Math.Min(newValue, _upperValue);
}
else if (isDraggingUpper)
{
newValue = Math.Max(newValue, _lowerValue);
}
value = newValue;
Invalidate(); // コントロールを再描画
ValueChanged?.Invoke(this, EventArgs.Empty); // 値変更イベントを発火
}
}
コードを張り付け保存するとコントローラーとしてアイコンも変わる
この状態でビルドをするとツールボックスにコントローラーが表示される
作成したコントローラーを使用する
ラベルを追加してスライダーを動かしたときの数値の変化を確かめる
using System;
using System.Windows.Forms;
namespace SampleControl
{
public partial class Form1 : Form
{
private RangeSlider rangeSlider;
public Form1()
{
InitializeComponent();
rangeSlider1.ValueChanged += RangeSlider_ValueChanged;
}
private void RangeSlider_ValueChanged(object sender, EventArgs e)
{
label1.Text = rangeSlider1.LowerValue.ToString();
label2.Text = rangeSlider1.UpperValue.ToString();
}
}
}
数値が反映されているのがわかる
さいごに
このレンジスライダーは左右それぞれの領域を侵さない部分の作成が重要だ
コメント