VCDPropertiesをリストする
VCDプロパティインターフェースを使用してビデオキャプチャデバイスのプロパティを呼び出す方法について説明します。
画像取り込みデバイスから呼び出されるプロパティは全てツリービューで表示されます。プロパティの体系自体がツリー状であるためこの表示方法
が最適なものです。ツリーの根元にあたるのが VCDPropertyItemsクラスライブラリリファレンス>クラス>VCDPropertyItems
コレクションです。この中には現在の画像取り込みデバイスより提供される全 VCDPropertyItemクラスライブラリリファレンス>クラス>VCDPropertyItems
が含まれています。全てのVCDPropertyItemクラスライブラリリファレンス>クラス>VCDPropertyItem
が一つ以上のVCDPropertyElementクラスライブラリリファレンス>クラス>VCDPropertyElements
を持ち、さらに それぞれが一つ以上のVCDPropertyInterfaceクラスライブラリリファレンス>クラス>VCDPropertyInterfaces
を持ち、それらを使ってプロパティにアクセスします。
今回のサンプルプログラムのVB.NET 、C#用のソースコードはMy Documents/IC
Imaging Control 3.5内の以下ののディレクトリに格納されています。
samples\C# *\List VCDProperties
プロジェクトの新規作成
新しいプロジェクトを作成し、IC imaging Controlをフォームに追加してください。プログラムを実行する前に、はじめに: Visual Studio .NETプログラマーズガイド>Visual Studioでスタート にあるように映像デバイスの選択、入力方式、ビデオフォーマットを選択してください。もしくはデバイスを選択せずにプログラムを実行してください。その際はIC Imaging Controlによってデバイス選択のダイアログが出現します。選択をせずにダイアログを閉じた場合、プログラムはエラーメッセージを表示し、終了します。
フォームにボタンを2つ追加し、CaptionプロパティをSelect Device、Show Property Pageとします。そしてそれぞれbtnSelectDevice、btnShowPageと名前を付けます。これらはプロパティページダイアログにて各デバイス設定
を表示するのに使用されます。では各ユーザーコントロールあたり一つのインスタンスをフォームに追加してください。名前をそれぞれbtnPush,cboMapStrings,chkSwitch, sldAbsVal,sldRangeとします。各ユーザーコントロールはVCDPropertyInterfaceクラスライブラリリファレンス>クラス>VCDPropertyInterfaceから派生するそれぞれのインターフェースです。
ではImage ListとTree Viewをフォームに追加します。イメージリストはツリーを視覚化するためのグラフィック要素を含んでいます。ツリービューにTreeと名前を付けます。 グラフィック要素をイメージリストに追加するにはImagesの下にあるイメージリストのプロパティウィンドウ内で ... ボタンを クリックします。では次の画像を以下の順に追加してください。(item.bmp,value.bmp,auto.bmp, button.bmp,slider.bmp,switch.bmp,combo.bmp)
これら全てのビットマップファイルはこのサンプルのディレクトリ内にあります。イメージリストのModifiersプ
ロパティをFriend(C#の場合は internal)
に変更します。 これでイメージリストをツリービューに追加できるようになりました。 ツリービューのプロパティImageListを
イメージリストの名前として設定してください。それで完了です。
機能を追加する
ClickイベントをSelect Device、Show Property Pageボタンに追加 し、以下のコードを挿入します。
private void btnSelectDevice_Click( object sender, EventArgs e )
{
// デバイス設定ダイアログを表示するためにライブモードを停止する
if( icImagingControl1.LiveVideoRunning )
{
icImagingControl1.LiveStop();
}
// デバイス設定ダイアログ表示
icImagingControl1.ShowDeviceSettingsDialog();
// デバイスを選択しなかった場合、プログラムを終了する
if( !icImagingControl1.DeviceValid )
{
MessageBox.Show("No device was selected.");
this.Close();
return;
}
UpdateStateAfterDeviceSelect();
}
private void UpdateStateAfterDeviceSelect()
{
// デバイスがない場合はExit
// デバッグウィンドウにすべてのプロパティを出力
ListAllPropertyItems;
// ライブモード開始
icImagingControl1.LiveStart();
// ツリービューの(再)初期化
BuildVCDPropertiesTree();
}
private void btnShowPage_Click( object sender, EventArgs e )
{
if( icImagingControl1.DeviceValid )
{
// 組み込みのプロパティダイアログを表示
icImagingControl1.ShowPropertyDialog();
}
}
Form_Loadイベントを追加し次のコードを挿入します。
private void Form1_Load( object sender, EventArgs e )
{
if( !icImagingControl1.LoadShowSaveDeviceState("lastSelectedDeviceState.xml") )
{
MessageBox.Show("No device was selected.");
this.Close();
return;
}
UpdateStateAfterDeviceSelect();
}
上記のコードにあるように、btnSelectDevice_ClickとForm_Loadイベントは共にプロシージャListAllPropertyItemsとQueryVCDPropertiesを呼び出します。QueryVCDPropertiesは現在使用している画像取り込みデバイスのプロパティをツリー状に表示します。さらにListAllPropertyItemsがそれらのプロパティのツリー構造をデバッグ出力ウィンドウに表示します。デバッグ出力はコントロール等の他の側面を除いた純粋なVCDPropertiesの体系を表します。ではプロシージャListAllPropertyItems用のコードを見てみましょう。
private void ListAllPropertyItems()
{
// 全プロパティ項目の取得
foreach (TIS.Imaging.VCDPropertyItem PropertyItem in icImagingControl1.VCDPropertyItems)
{
System.Diagnostics.Debug.WriteLine(PropertyItem.Name);
// 現在のプロパティ項目の全エレメントを取得
foreach (TIS.Imaging.VCDPropertyElement PropertyElement in PropertyItem.Elements)
{
System.Diagnostics.Debug.WriteLine(" Element : " + PropertyElement.Name);
// 現在のプロパティエレメントの全インターフェースを取得
foreach (TIS.Imaging.VCDPropertyInterface PropertyInterFace in PropertyElement)
{
System.Diagnostics.Debug.Write(" Interface ");
try
{
// 特殊インターフェースプロパティへアクセスするために現在のインターフェー スを
// 最適な型にキャスト
if( PropertyInterFace.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_AbsoluteValue )
{
var AbsoluteValue = (TIS.Imaging.VCDAbsoluteValueProperty)PropertyInterFace;
System.Diagnostics.Debug.Write("Absolut Value : ");
System.Diagnostics.Debug.WriteLine(AbsoluteValue.Value.ToString());
}
else if ( PropertyInterFace.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_MapStrings )
{
var MapString = (TIS.Imaging.VCDMapStringsProperty)PropertyInterFace;
System.Diagnostics.Debug.Write("Mapstring : ");
System.Diagnostics.Debug.WriteLine(MapString.String);
}
else if ( PropertyInterFace.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_Switch )
{
var Switch = (TIS.Imaging.VCDSwitchProperty)PropertyInterFace;
System.Diagnostics.Debug.Write("Switch : ");
System.Diagnostics.Debug.WriteLine(Switch.Switch.ToString());
}
else if ( PropertyInterFace.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_Button )
{
var Button = (TIS.Imaging.VCDButtonProperty)PropertyInterFace;
System.Diagnostics.Debug.WriteLine("Button");
}
else if ( PropertyInterFace.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_Range )
{
var Range = (TIS.Imaging.VCDRangeProperty)PropertyInterFace;
System.Diagnostics.Debug.Write("Range : ");
System.Diagnostics.Debug.WriteLine(Range.Value.ToString());
}
}
catch ( Exception ex )
{
System.Diagnostics.Debug.WriteLine("<error>:" + ex);
}
}
}
}
}
上のコードにある3つのFor EachループはVCDPropertiesのツリー構造を反映しているものです。 最初のループは利用可能な全VCDPropertyItemクラスライブラリリファレンス>クラス>VCDPropertyItemをカバーしその名前をデバッグアウトプットに表示します。 2つ目のループは各項目ごとに、利用可能な全VCDPropertyElementクラスライブラリリファレンス>クラス>VCDPropertyElementを表示します。そして3つ目のループがエレメントの提供する全インターフェースの型を表示します。インターフェースは詳細の程度によってソートされます。最も詳細なものは "AbsoluteValue(絶対値)" インターフェースでそれに続くのが "MapStrings(マップストリングス)" インターフェース、"スイッチ" と"ボタン"インターフェースは詳細なインターフェースですがトリガーのオンとオフなどシンプルな機能を提供するものです。 "Range(レンジ)"インターフェースは最も汎用的ですが、表す値に意味はありません。例えば "Brightness" の値の範囲は 0 から 255ですが、0 と 255 のどちらが最大の輝度値を表すかについては示されていません。
BuildVCDPropertiesTreeプロシージャを見てみましょう。このプロシージャは 適切な値をツリービューで表示します。このプロシージャのコードは以下の通りです。
private void BuildVCDPropertiesTree()
{
// ツリーを完全に消去
Tree.Nodes.Clear();
// ツリーの形成
TreeNode root = new TreeNode("VCDPropertyItems");
Tree.Nodes.Add(root);
BuildVCDPropertiesTreeItems(root, icImagingControl1.VCDPropertyItems);
root.ExpandAll();
Tree.SelectedNode = root;
}
上のプロシージャはツリービューを消去して新しいルートノードを作成します。ルートノードのCaptionプロパティをVCDPropertyItemsとします。それからプロシージャBuildVCDPropertiesTreeItemsが利用可能な全プロパティ項目を挿入します。そのプロシージャは以下のようになります。
private void BuildVCDPropertiesTreeItems (TreeNode pp, TIS.Imaging.VCDPropertyItems props)
{
// VCDPropertyItems をツリーコントロールに挿入
foreach (TIS.Imaging.VCDPropertyItem item in props)
{
// プロパティ項目のための新しいツリーノードを作成
TreeNode newNode = new TreeNode(item.Name, 0, 0);
pp.Nodes.Add(newNode);
QueryVCDPropertyElements(newNode, item);
}
}
BuildVCDPropertiesTreeItemsは利用可能な全てのプロパティ項目の実行を繰り返し、毎回新しいノードを作成します。これらのノードは全てルートノードの子ノードです。VCDPropertyItemクラスライブラリリファレンス>クラス>VCDPropertyItemの名前 (e.g. "Brightness", "Gain" or "Exposure") はそのノードのTextプロパティに割り当てられます。Nothing(C#であればnull)はノードのtagプロパティに割り当てられます。そしてQueryVCDPropertyElementsが新しいノード用に呼び出されます。QueryVCDPropertyElementsは以下の通りです。
private void QueryVCDPropertyElements(TreeNode pp, TIS.Imaging.VCDPropertyItem item)
{
foreach (TIS.Imaging.VCDPropertyElement elem in item.Elements)
{
TreeNode.newNode = null
if ( elem.ElementGUID == TIS.Imaging.VCDGUIDs.VCDElement_Value )
newNode = new TreeNode("VCDElement_Value: '" + elem.Name + "'", 1, 1);
else if ( elem.ElementGUID == TIS.Imaging.VCDGUIDs.VCDElement_Auto )
newNode = new TreeNode("VCDElement_Auto: '" + elem.Name + "'", 2, 2);
else if ( elem.ElementGUID == TIS.Imaging.VCDGUIDs.VCDElement_OnePush )
newNode = new TreeNode("VCDElement_OnePush: '" + elem.Name + "'", 3, 3);
else if ( elem.ElementGUID == TIS.Imaging.VCDGUIDs.VCDElement_WhiteBalanceRed )
newNode = new TreeNode("VCDElement_WhiteBalanceRed: '" + elem.Name + "'", 4, 4);
else if ( elem.ElementGUID == TIS.Imaging.VCDGUIDs.VCDElement_WhiteBalanceBlue )
newNode = new TreeNode("VCDElement_WhiteBalanceBlue: '" + elem.Name + "'", 4, 4);
else
newNode = new TreeNode("Other Element ID: '" + elem.Name + "'", 4, 4);
pp.Nodes.Add(newNode);
// 全インターフェースを挿入
QueryVCDPropertyInterface(newNode, elem);
}
}
QueryVCDPropertyElementsは利用可能なエレメントの実行を繰り返し、そのすべてに対して、新しいノードを作成します。これらのノードは全てルートノードの子ノードで、これらのVCDPropertyElementクラスライブラリリファレンス>クラス>VCDPropertyElementが属するVCDPropertyItemクラスライブラリリファレンス>クラス>VCDPropertyItemを表します。Selectブロック (C#であればswitchブロック) はそのノードに最適なグラフィックツリーエレメントを決定し、そのベースネームをエレメントの型に応じて設定します。VCDPropertyElementクラスライブラリリファレンス>クラス>VCDPropertyElementの名前(e.g. "Value", "Auto" or "Enable") はベースネームに追加され、ノードのTextプロパティに割り当てられます。Nothing(C#であれば null)はノードのtagプロパティに割り当てられ、QueryVCDPropertyInterfaceが新しいノード用に呼び出されます。QueryVCDPropertyInterfaceは以下の通りです。
private void QueryVCDPropertyInterface(TreeNode pp, TIS.Imaging.VCDPropertyElement elem)
{
foreach (TIS.Imaging.VCDPropertyInterface itf in elem)
{
TreeNode newNode;
if ( itf.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_AbsoluteValue )
newNode = new TreeNode("AbsoluteValue", 4, 4);
else if ( itf.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_MapStrings )
newNode = new TreeNode("MapStrings", 6, 6);
else if ( itf.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_Range )
newNode = new TreeNode("Range", 4, 4);
else if ( itf.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_Switch )
newNode = new TreeNode("Switch", 5, 5);
else if ( itf.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_Button )
newNode = new TreeNode("Button", 3, 3);
else
{
newNode = new TreeNode(itf.InterfaceGUID.ToString(), 4, 4);
// Tag プロパティがノードでインターフェースを保持
newNode.Tag = itf;
pp.Nodes.Add(newNode);
}
}
QueryVCDPropertyInterfaceは利用可能なエレメントのインターフェースの実行を繰り返し、そのすべてに対して新しいノードを作成します。これらのノードは全てルートノードの子ノードで、これらVCDPropertyInterfaceクラスライブラリリファレンス>クラス>VCDPropertyInterfaceが属するVCDPropertyElementクラスライブラリリファレンス>クラス>VCDPropertyElementを表します。Selectブロック (C#であれば switchブロック)はそのノードに最適なグラフィックツリーエレメントを決定し、そのベースネームをエレメントの型に応じて設定します。そしてその名前はノードのTextプロパティに割り当てられます。インターフェースパスは itemID,elementID, interfaceID から構成されノードのtagプロパティに割り当てられます。インターフェースノードはツリーの葉の部分の形成します。
VCDPropertyへのアクセスと操作
ツリーは完成したので、プロパティにアクセスしましょう。ツリービューにAfterSelectイ ベントを追加して次のコードを挿入します。
private void treeView1_AfterSelect( object sender, TreeViewEventArgs e )
{
// Tag プロパティが空の場合、リーフノードは選択されません
if (Tree.SelectedNode.Tag == null)
{
return;
}
// コン トロールグループを隠す
foreach( var ctrl in _currentControls )
{
ctrl.Dispose();
}
_currentControls.Clear();
TIS.Imaging.VCDPropertyInterface itf = Tree.SelectedNode.Tag as TIS.Imaging.VCDPropertyInterface;
if (itf != null)
{
itf.Update();
// 選択されたインターフェース型に対応するコントロールグループを表示し初期化
if ( itf.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_AbsoluteValue )
ShowAbsoluteValueControl(itf);
else if ( itf.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_MapStrings)
ShowComboBoxControl(itf);
else if ( itf.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_Range)
ShowRangeControl(itf);
else if ( itf.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_Switch)
ShowSwitchControl(itf);
else if ( itf.InterfaceGUID == TIS.Imaging.VCDGUIDs.VCDInterface_Button)
ShowButtonControl(itf);
}
}
インターフェースノードのタグがインターフェースパスを格納することがわかります。インターフェースノードをクリックすると、フォームに最適なコントロールが現れ、プロパティの設定を調整できるようになります。正確なインターフェースを取得する為にFindInterfaceクラスライブラリリファレンス>クラス>VCDPropertyItems>VCDPropertyItems.FindInterface Methodメソッドが使用されます。FindInterfaceクラスライブラリリファレンス>クラス>VCDPropertyItems>VCDPropertyItems.FindInterface Methodはインターフェースパス(もしくはGUID)をパラメータとして必要とします。Selectブロック (C#であれば switch ブロック)が目的のインターフェースに最適なユーザーコントロールを与え各 "Show%%" プロシージャを呼び出します。これらのプロシージャはユーザーコントロールの"Visible"プロパティをTrueに設定し、特定のプロパティの設定を調整できるようにします。ShowAbsoluteValueControlプロシージャの実装方法を示します。
private void ShowAbsoluteValueControl(TIS.Imaging.VCDPropertyInterface itf)
{
var newCtrl = new AbsValSlider((TIS.Imaging.VCDAbsoluteValueProperty)itf);
CtrlFrame.Controls.Add(newCtrl);
newCtrl.SetBounds(20, 20, 500, 27);
CtrlFrame.Text = "Absolute Value";
_currentControls.Add(newCtrl);
}
他のユーザーコントロール用のプロシージャも同じようにして実装できます。