はじめに
アプリケーション開発で悩むのが入力コントロール。よりグラフィカルなアプリケーションに仕上げたい時などは、入力方法だけでなくコントロールのデザインにも手を入れたくなります。しかし、あらためてコントロールをデザインするとなるとセンスと手間が必要になります。
ComponentOne Studioのゲージコントロール(C1Gauge)は、データをゲージで視覚化するコントロールですが、マウスイベントと組み合わせると入力コントロールとしても使用できるようになります。線形ゲージも円形ゲージも入力コントロールとして使えるので、ユーザーにとっては入力値がどの位置にあるのかを確認しながらデータ入力が行えるようになります。
そこで今回は、入力コントロールのサンプルとして円形ゲージを入力コントロールとして使用し、RGB値を生成してテキストの文字色を変化させるアプリケーションを作成してみました。


対象読者
Visual Basic 2010/2012/2013、またはVisual C# 2010/2012/2013を使ってプログラムを作ったことがある人。
必要な環境
Visual Basic 2010/2012/2013、Visual C# 2010/2012/2013、Visual Studio 2010/2012/2013でプログラムが作れる環境。
なお、本プログラムは次の環境で開発・動作確認を行っています。
- OS:Windows 7
- 開発Tool:Visual Studio 2010、.NET Framework 4
プログラム実行時の注意事項
本稿の実行ファイル(バイナリファイル)を動かすには、zipファイルに同梱してある以下のファイルが必要になります。.NET Framework 4でのみご使用いただけます。
ファイル名 | 説明 |
---|---|
C1.Win.C1Gauge.4.dll | 本体アセンブリ |
これらのファイルを、実行プログラムと同じフォルダに格納します。
コントロールのインストール
トライアル版は、グレープシティのWebページから申し込みできます。
トライアル申込フォームが表示されますので、必要情報を入力して申し込むとトライアル版のダウンロード手順を記載したE-Mailが送られてきます。その手順にそってダウンロードを行ってください。また、ダウンロードファイルは圧縮ファイルになっていますので、解凍してインストーラを起動します。
制限事項などの詳細については、インストーラに同梱されているリリースノートを参照ください。
コントロールと参照の追加
ComponentOne Studioをインストールしたら、プロジェクトにコントロールを追加します。ツールボックスに専用のタブを作成し、使用するコンポーネントを追加します。追加するコントロールは、アセンブリ名が「C1.Win.C1Gauge.4」の「C1Gauge」コントロールです。
このコントロールを追加すると、プロジェクトに以下のランタイムライブラリへの参照が追加されます。
ファイル | 内容 |
---|---|
C1.Win.C1Gauge.4 | 本体アセンブリ |
C1Gaugeコントロールの概要
C1Gaugeコントロールは、ゲージと形状のコンテナコントロールです。直線型ゲージと円形ゲージをサポートしており、ゲージはデータを表示し、ポインタとデコレータ(ラベル、目盛りマーク、範囲など)を使用してカスタマイズできます。
円形ゲージは、円形、半円形、貝殻形、らせん形、または円弧形にすることができます。直線型ゲージは、横、縦、斜め、または自由形状にすることができます。

C1Gaugeコントロールは形状もサポートします。形状は、静的な形状、キャプション、または画像で構成されます。形状には、楕円、長方形、円弧、扇形などの幾何学的形状があり、それぞれに多数のカスタマイズ可能な設定が含まれます。他の形状、デコレータ、ポインタなどの他の要素のためのクリッピング領域を形状に指定することもできます。
ポインタは、現在値を示すビジュアル要素です。デコレータは、ポインタに結合できます。例えば、1つのラベルをポインタに結合して、ラベルに現在値を表示することができます。この強力なテクニックは、「デコレータ」セクションで詳細に説明します。
カスタムビットマップを除き、Gauges for WinForms内のすべてのグラフィックはベクタベースです。C1Gaugeコンテナコントロールとそのゲージは、サイズを任意に変更できます。個々のゲージの絶対位置または相対位置と、アスペクト比を指定できます。
あらかじめ組み込まれたテンプレートを持っており、ここからゲージの形状を選ぶことで、すぐにゲージをアプリケーションに実装することができます。

C1Gaugeコントロールの特徴
Gauges for WinFormsは、以下の主要機能を備えています。
機能 | 説明 |
---|---|
円形ゲージと直線型ゲージ | C1Gaugeコントロールの設定時に、放射状または線形形状を選択します。円形ゲージは円、らせん、円弧曲線、クラムシェル、または半円をとり、直線型ゲージは水平、垂直、傾斜、または自由形状をとることができます。 |
ベクトルベースのグラフィックス | ピクセルベースのサイズを指定しない限り、C1Gaugeコントロールのグラフィックスはすべてベクトルベースです。従って、ゲージはどのようなサイズでも完全にペイントされ、内部のすべての要素が比例してサイズ変更されます。 |
ゲージのデータバインド | 標準.NETデータバインディング技術を使って、デザイン時にC1Gaugeコントロールをデータソースにバインドします。個々のポインタを異なるデータソースにバインドできます(1つのゲージで最大5個のポインタまでになります)。 |
複数のポインタとスケール | 1つのゲージが保持できるポインタとスケールの数は無制限です。複数の関連するスケールまたは関連のないスケールを1つのゲージに追加したり、複数のゲージを重ね合わせて追加のレイアウトオプションを使用したりできます。スケールを均一にする必要はありません。線形または対数を使用できます。動的なスケールを作成できます。スケールの開始点と終了点をポインタにバインドすることもできます。 |
範囲のバインド | Gauges for WinFormsを使用して、非線形または線形の形状をした範囲を作成できます。希望する外観に最も合うように、範囲の厳密な位置とサイズをカスタマイズします。色を値のしきい値にマップして、オプションで色が徐々に融合する多色の範囲を表示します。範囲をポインタにバインドして、より動的な表示を行うこともできます。範囲(目盛やラベルも同様)の一部の色をポインタにバインドして、現在の値をハイライト表示できます。例えば、バインドされた色を持つ1つの範囲オブジェクトを使用してプログレスバーを表示できます。 |
ラベルの書式設定 | すべてのゲージラベルと値インジケータに標準またはカスタム.NET数値書式を適用して、小数位、パーセント、通貨などを表示します。カスタム数値書式の一部として、ラベルに静的テキストを表示できます。ラベルの書式設定をプログラムを使用して制御する特殊なイベントを使用することもできます。C1Gaugeコントロールは、ユーザーが常に最も読みやすくなるように、円形ゲージのラベルを自動的に回転します。追加の回転、配置の変更、および放射状/直交オフセットを指定して、興味深い効果が得られます。 |
目盛 | 目盛とは、ゲージスケール上の特定の値に配置できる視覚的なキューです。これらのキューは、ゲージ値を他の定義済みの値と比較する場合に便利です。目盛には、形状またはカスタム画像を使用できます。円形ゲージの場合は、ラベルと同じように、目盛を回転させたり、回転させなかったりできます。ゲージ目盛の追加の回転、配置の変更、およびオフセットを適用できます。 |
インジケータ | バインドされたラベルや目盛を使用し、値のしきい値に基づく視覚的示度を表示できます。これらを範囲に加え、または範囲の代わりに状態インジケータとして使用し、値を色または画像で表示します。例えば、目盛または目盛の画像の背景色をポインタ値に応じて変えることができます。あるいは、固定または移動可能なラベルをポインタにアタッチして、特定の位置に現在値を表示できます。 |
カスタムポインタ | 定義済みのポインタ形状を選択して、形状をカスタマイズし、独自のカスタム画像をインポートして、ポインタとして使用します。複数のポインタと共に使用する共通ポインタ形状を作成します。円形ゲージと直線型ゲージのポインタの原点の正確な位置を指定することもできます。これにより、ゲージの両側または下部にポインタを分散できます。 |
OFF位置 | ゲージポインタは、値が設定されていないことを示すことができます。現在値がDouble.NaNの場合、ポインタはOFF位置に移動します。目盛とラベルをOFF位置に表示できます。インタラクティブ機能を使用する場合、この位置でクリックしてゲージを“OFF”にしたり、値をDouble.NaNにリセットしたりできます。 |
ポインタのアニメーション | 値の変更に応じて、ゲージポインタのアニメーションがスムーズに描画されるように時間間隔を設定します。ソース値が頻繁に変わりすぎて確認できない場合、ゲージコントロールの再描画の頻度を減少させることができます。 |
カスタムゲージの外観 | 使用可能なスタイル属性の充実したセットを使用して、ゲージのフェイスやカバーをカスタマイズし、希望する外観を作成します。単純な形状を使用して、ガラス掛け効果をシミュレートすることさえできます。形状が物足りない場合は、画像を追加できます。回転、反転、色相、彩度、明度、透明度の変更など、さまざまな効果を画像に適用できます。 |
共通の外観の設定 | 塗りつぶし、グラデーション、形状、画像などの共通のコレクションにより、複数のゲージ項目に同じ設定を適用できます。また、これらの共通の設定を変更すると、関連するすべての項目が一度に影響を受けます。例えば、値のしきい値への画像の同じマッピングを共有するバインドされたインジケータを作成できます。この結果、メモリが節約され、その後の変更が容易になります。 |
UIのインタラクティブ操作 | C1Gaugeコントロールの任意の部分をHitTestableにできます。ゲージ項目がホットになったとき、押されたとき、または無効になったときに、ゲージ項目の視覚的外観が簡単に変更されます。特定の時間間隔中に前の状態を非表示にし、新しい状態を表示する遷移効果を使用して、ゲージ項目の視覚的状態をスムーズに変更できます。ユーザーが各種要素をクリックしたり、ゲージポインタをドラッグしたりすると、特殊なイベントが発生します。 スナップ間隔によって指定された均一な値の離散集合に四捨五入するオプションを使用して、これらのイベントからポインタ値を更新できます。 |
複合ゲージ | C1Gaugeコントロールを使用して、複数のゲージを1つのコンテナに配置します。ゲージを重ね合わせたり、並べて表示したりできます(下図参照)。すべてのグラフがベクトルベースなので、任意の方法でコンテナコントロールをサイズ変更できます。設定を微調整する機能により、コンテナコントロールのサイズ変更時に個々のゲージの縦横比と相対位置を維持することができます。 |
レイアウトおよび外観設定の保存とロード | Crゲージまたはコンテナコントロールの複数のビュー(または "スキン")を作成します。ビューは、コンクリートのゲージまたは、C1Gaugeコントロールに属性します。ビューを使用して、既存のスケール、データ、およびイベントバインディングを破棄せずに、ゲージの外観全体を変更できます。同じビューを別のゲージに適用することはできません。 |
テンプレートの保存とロード | ゲージテンプレートの保存と再利用により、開発時間が急激に減少します。個々のゲージまたはコンテナコントロール全体のテンプレートを作成できます。C1Gaugeコントロールは、すぐに始められるデザイン済みの複数のテンプレートも同梱しています。また、テンプレートで作成したゲージを細部にわたりカスタマイズし、独自のゲージに作り替えることも可能です、 |
C1Gaugeコントロールの構成
C1Gaugeコントロールは多くの部品で構成されており、部品ごとにクラス分けされています。円形ゲージを例にとると、次のような部品からなっており、それぞれオブジェクトとしてプロパティを操作することで、カスタムゲージにすることができます。
誌面の関係で、これらの部品のクラスとプロパティをすべて紹介することはできませんので、実際にアプリケーションを作成しながらいくつかの代表的なオブジェクトを操作してみます。
C1Gaugeコントロールのインタラクティブ性とイベント
C1Gaugeコントロールは、ゲージとしてデータを表示できるとともに、マウスイベントと組み合わせることで逆にユーザーがポインタを操作してデータのインプットを行うこともできます。
実行時のさまざまなユーザー操作の結果として、C1GaugeコントロールおよびC1GaugeBaseコンポーネントに対して数多くのイベントが発生します。これらのイベントのソースは、イベントハンドラに ItemEventArgsオブジェクトのItemプロパティから取得できる HitTestable要素です。
利用できるイベントは次のとおりです。
イベント名 | 説明 |
---|---|
ItemStateChanged | Hit-Testable 項目が有効になり、ホットになり、押されたとき、またはそれらの逆の操作が行われたときに発生します。 |
ItemClick | ゲージ要素をクリックしたときに発生します。 |
ItemDoubleClick | ゲージ要素をダブルクリックしたときに発生します。 |
ItemMouseEnter | マウスポインタがゲージ要素に入ったときに発生します。 |
ItemMouseLeave | マウスポインタがゲージ要素から離れたときに発生します。 |
ItemMouseMove | マウスポインタがゲージ要素上を移動したときに発生します。 |
ItemMouseDown | マウスポインタがゲージ要素上にあり、マウスボタンを押したときに発生します。 |
ItemMouseUp | マウスポインタがゲージ要素上にあり、マウスボタンを離したときに発生します。 |
C1Gauge.SupportsTransitionEffectをTrueに設定した場合、ゲージ項目の状態を変更する際に特殊な遷移効果を適用できます。
入力コントロールとして利用する場合は、これらのイベントハンドラでC1GaugePoiner.GetValueAt() 関数を使用してマウスの位置を値に変換します。そして、C1RadialGaugeクラスのValueプロパティを参照すると、ゲージの現在位置の値を取得することができます。
アプリケーションの作成(1)
では、アプリケーションを作成していきます。
作成するアプリケーションは、3つのオプション円形ゲージを使用してRGB値をそれぞれ入力してもらい、その値から色情報を作成してテキストの文字色を変更します。使用するアプリケーションはC1Gauge、Labelコントロールです。
GUIの作成
今回はテンプレートから選んで作成しますので、ゲージの作成はとても簡単です。
(1)Labelコントロールで文字色を変化させたい文字を作成します。
(2)ツールボックスから、C1Gaugeコントロールをフォームにドラッグ&ドロップします。自動的にテンプレートが選べるゲージギャラリーが表示されます。
(3)「円形ゲージ」のリストから「Blue Tracker」をクリックします。右側のペインに作成されるゲージが表示されます。

(4)OKボタンをクリックするとこのゲージがフォームに配置されますので、タスクトレイから「ゲージの編集」をクリックします。

(5)「Gaugeコレクションエディタ」が起動します。このエディタでゲージの各部位を編集できます。まず、ゲージの動作範囲を0~255に変更します。右ペインにある「Maximum」プロパティの値を255に変更します。

(6)次にゲージのポインタ(針)の幅を太くします。これは「Pointer」をクリックして展開し、「Width」の値を「10」にします。また、「Pointer」内の「Filling」を開き、「Color」を「Cyan」に変えます。

(7)次に「Value」プロパティの値を「0」にします。このプロパティがゲージの針の表示位置を決めるプロパティで、針は0の位置に戻ります。

(8)OKボタンをクリックしエディタを閉じます。これで、針がブルーのグラデーションに塗りつぶされ、やや太い形状に変更されました。

(9)同様の方法で、あと2つゲージを追加します。設定するプロパティ値は以下のとおりです。
プロパティ | 設定値 | ||
---|---|---|---|
Maximum | 255 | ||
Pointer | Width | 25 | |
Filling | Color | Red | |
Value | 0 |
プロパティ | 設定値 | ||
---|---|---|---|
Maximum | 255 | ||
Pointer | Width | 10 | |
Filling | Color | Lime | |
Value | 0 |
(10)これで3つのゲージが出来上がりました。
(11)ゲージの外観ができたので、ユーザーの入力操作処理用のイベントハンドラを作成します。まず、ゲージの内側をクリックし、プロパティウィンドウのオブジェクトリストに「C1RadialGauge」オブジェクトを表示させます。


(12)この状態で、イベントリストからItemMouseMoveイベントをダブルクリックしてイベントハンドラを作成します。

このイベントハンドラを3つのゲージそれぞれに作成します。C1GaugeコントロールのItemMouseMoveイベントハンドラではないので、間違えないようにしてください。
(13)最後に、ゲージの現在値を表示するLabelコントロールを作成して完成です。
アプリケーションの作成(2)
ゲージを入力コントロールとして機能させる処理
ゲージが完成したら、このゲージを入力コントロールとして作動できるように処理を組み込みます。
前節「C1Gaugeコントロールのインタラクティブ性とイベント」でも説明したように、ユーザーがゲージのポインタを動かそうとした時のマウス座標を取得し、その位置にポインタを移動させると、いかにもマウスでポインタを動かしたように見えます。この処理をItemMouseMoveイベントハンドラに組み込むことで、C1Gaugeコントロールを入力コントロールとして使うことができるようになります。
そして、ゲージの現在値はValueプロパティに格納されていますから、このプロパティから取り出してRGB値を作成し、テキストのForeColorプロパティに反映させれば、ゲージのポインタを動かすたびに、テキストも文字色が変化していきます。
(1)最初に、C1Gauge名前空間にアクセスできるようにし、3つのメンバ変数を宣言します。
Imports C1.Win.C1Gauge Public Class Form1 Private r, g, b As Integer
using C1.Win.C1Gauge; namespace GaugeInput_Winform_cs { public partial class Form1 : Form { private int r, g, b;
(2)次に、テキストの文字色を変えるプロシージャ(メソッド)を作成します。このプロシージャ(メソッド)では各ゲージの値から、ColorクラスのFromArgbメソッドを使用してRGB値を作成し、テキストの文字色を変える処理を実行します。
Sub textrepaint() Label1.ForeColor = Color.FromArgb(255, r, g, b) End Sub
private void textrepaint() { label1.ForeColor = Color.FromArgb(255, r, g, b); }
(3)各ゲージのItemMouseMoveイベントハンドラでは、マウスの座標からPointerオブジェクトを作成し、イベントが発生したゲージのポインタ座標に代入します。
If (e.Button And MouseButtons.Left) = MouseButtons.Left Then Dim p As C1GaugePointer = e.Gauge.Pointer p.Value = p.GetValueAt(e.X, e.Y) End If
if ((e.Button & MouseButtons.Left) == MouseButtons.Left) { C1GaugePointer p = e.Gauge.Pointer; p.Value = p.GetValueAt(e.X, e.Y); }
(4)また、ゲージのポインタが動くと、Valueプロパティの値もその位置の値に更新されますので、これをゲージの上のLabelコントロールとメンバ変数rgbに代入します。このときValueプロパティがDouble型になっているので、値を整数に変換してから使用します。そして、テキストの文字色を更新するプロシージャ(メソッド)を呼び出して実行します。
Label2.Text = Convert.ToInt16(C1RadialGauge1.Value) b = Convert.ToInt16(C1RadialGauge1.Value) textrepaint()
label2.Text = Convert.ToInt16(c1RadialGauge1.Value).ToString(); b = Convert.ToInt16(c1RadialGauge1.Value); textrepaint();
以上で出来上がりです。これで、ゲージのポインタの上でマウスを動かすとポインタも追従して動き、その時の値がLabelコントロールで表示されるとともにテキストの文字色が変化します。
Imports C1.Win.C1Gauge Public Class Form1 Private r, g, b As Integer Private Sub C1RadialGauge1_ItemMouseMove(sender As System.Object, e As C1.Win.C1Gauge.ItemMouseEventArgs) Handles C1RadialGauge1.ItemMouseMove If (e.Button And MouseButtons.Left) = MouseButtons.Left Then Dim p As C1GaugePointer = e.Gauge.Pointer p.Value = p.GetValueAt(e.X, e.Y) End If Label2.Text = Convert.ToInt16(C1RadialGauge1.Value) b = Convert.ToInt16(C1RadialGauge1.Value) textrepaint() End Sub Private Sub C1RadialGauge2_ItemMouseMove(sender As System.Object, e As C1.Win.C1Gauge.ItemMouseEventArgs) Handles C1RadialGauge2.ItemMouseMove If (e.Button And MouseButtons.Left) = MouseButtons.Left Then Dim p As C1GaugePointer = e.Gauge.Pointer p.Value = p.GetValueAt(e.X, e.Y) End If Label3.Text = Convert.ToInt16(C1RadialGauge2.Value) r = Convert.ToInt16(C1RadialGauge2.Value) textrepaint() End Sub Private Sub C1RadialGauge3_ItemMouseMove(sender As System.Object, e As C1.Win.C1Gauge.ItemMouseEventArgs) Handles C1RadialGauge3.ItemMouseMove If (e.Button And MouseButtons.Left) = MouseButtons.Left Then Dim p As C1GaugePointer = e.Gauge.Pointer p.Value = p.GetValueAt(e.X, e.Y) End If Label4.Text = Convert.ToInt16(C1RadialGauge3.Value) g = Convert.ToInt16(C1RadialGauge3.Value) textrepaint() End Sub Sub textrepaint() Label1.ForeColor = Color.FromArgb(255, r, g, b) End Sub End Class
using C1.Win.C1Gauge; namespace GaugeInput_Winform_cs { public partial class Form1 : Form { private int r, g, b; public Form1() { InitializeComponent(); } private void c1RadialGauge1_ItemMouseMove(object sender, C1.Win.C1Gauge.ItemMouseEventArgs e) { if ((e.Button & MouseButtons.Left) == MouseButtons.Left) { C1GaugePointer p = e.Gauge.Pointer; p.Value = p.GetValueAt(e.X, e.Y); } label2.Text = Convert.ToInt16(c1RadialGauge1.Value).ToString(); b = Convert.ToInt16(c1RadialGauge1.Value); textrepaint(); } private void c1RadialGauge2_ItemMouseMove(object sender, C1.Win.C1Gauge.ItemMouseEventArgs e) { if ((e.Button & MouseButtons.Left) == MouseButtons.Left) { C1GaugePointer p = e.Gauge.Pointer; p.Value = p.GetValueAt(e.X, e.Y); } label3.Text = Convert.ToInt16(c1RadialGauge2.Value).ToString(); r = Convert.ToInt16(c1RadialGauge2.Value); textrepaint(); } private void c1RadialGauge3_ItemMouseMove(object sender, C1.Win.C1Gauge.ItemMouseEventArgs e) { if ((e.Button & MouseButtons.Left) == MouseButtons.Left) { C1GaugePointer p = e.Gauge.Pointer; p.Value = p.GetValueAt(e.X, e.Y); } label4.Text = Convert.ToInt16(c1RadialGauge3.Value).ToString(); g = Convert.ToInt16(c1RadialGauge3.Value); textrepaint(); } private void textrepaint() { label1.ForeColor = Color.FromArgb(255, r, g, b); } } }
まとめ
データ入力によく使われるスライダーやNumericUpDownコントロールは、今や当たり前すぎて新鮮味に欠けますよね。このC1Gaugeコントロールを入力コントロールとして使用すれば、独自のデザインの入力インターフェースが作成できるので、アプリケーションのデザイン性も高くなり、またユーザーにとっても入力が楽しくなるような効果も生まれてくるのではないでしょうか。