VCDプロパティ:プロパティダイアログ画面のカスタマイズ編
概要
カメラのプロパティを設定するにはShowPropertyDialogを使用するだけでいいのですが、ここではカスタマイズしたデバイスダイアログ画面の作成方法について説明します。
サンプルプログラム
Software | IC Imaging Control 3.5, Visual Studio™ 2019 |
---|---|
サンプル(C#) | VCDPropertyPage_cs_3.5.zip |
実行結果
Visual Studioのプログラム上ではすでにボタンの設置や関数は定義済ですので、IC Imaging Contorl3.5をインストールされていれば、実行ボタンだけですぐにデバッグで動作確認することができます。
画面にあるそれぞれのボタンなどのコントローラの機能は下記の通りです。
[select Device]ボタン | デバイスダイアログ画面を表示します。 |
---|---|
[Show My Dialog]ボタン | VCDPropetiesDlgを表示します。 |
[Show Orginal]ボタン | Device Properties画面を表示します。 |
初期設定
private void Form1_Load(object sender, EventArgs e)
{
if( !icImagingControl1.LoadShowSaveDeviceState("lastSelectedDeviceState.xml") )
{
MessageBox.Show("No device was selected.", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
this.Close();
return;
}
//カメラから出力された映像をIC Imaging Contorolのコントロール表示サイズにする
icImagingControl1.LiveDisplayDefault = false;
icImagingControl1.LiveDisplaySize = icImagingControl1.Size;
icImagingControl1.LiveStart();
}
[Show Orginal]ボタンをクリックした時の処理
private void cmdShowOriginalDialog_Click(object sender, EventArgs e)
{
// プロパティダイアログをメソッドを使って表示する
icImagingControl1.ShowPropertyDialog();
}
プロパティダイアログをメソッドを使って呼び出す。
カメラのプロパティを設定するにはShowPropertyDialogを使用するだけでOKです。
IControlBase.cs
IControlBaseインターフェースとIControlSliderインターフェース
AbsValSlider.cs(AbsoluteValue用Sliderのユーザコントロール)
VCDAbsoluteValuePropertyインターフェースを使ってボタンをコントロールするためのクラス
PushButton.cs(ボタンのユーザコントロール)
VCDButtonPropertyインターフェースをコントロールするためのクラス
RangeSlider.cs(VCDRangeProperty用Sliderのユーザコントロール)
VCDRangePropertyインターフェースとスライダー・テキストボックスをコントロールするためのクラス
StringCombo.cs(コンボボックスのユーザコントロール)
VCDMapStringsPropertyインターフェースとコンボボックスをコントロールするためのクラス
Switch.cs(Switchコントローラのユーザコントロール)
VCDSwitchPropertyインターフェースとチェックボックスをコントロールするためのクラス
VCDPropertiesDlg.cs
上記のユーザコントローラを張り付けるためのWindowsフォーム
VCDPropertiesDlgのフォームでの処理
public partial class VCDPropertiesDlg : Form
{
private TIS.Imaging.ICImagingControl icImagingControl;
// 現在コントロールで埋められているカテゴリのフレーム
private System.Windows.Forms.GroupBox currentFrame;
// スイッチをチェックした後、処理を早くするためにコレクションを使う
private System.Collections.ArrayList currentSisterControls;
private System.Collections.ArrayList currentSisterSliders;
// グローバルオブジェクトが更新されたときに動作する
private readonly System.Collections.ArrayList allControls = new System.Collections.ArrayList();
// これらの定数は、プロパティページのレイアウトを制御します
private const int CTRL_HEIGHT = 27;
private const int ROW_HEIGHT = 28;
private const int PAGE_WIDTH = 800;
private const int LABEL_WIDTH = 100;
private const int SLIDER_WIDTH = 580;
private const int COMBO_EXTRA_WIDTH = 280;
private const int BUTTON_EXTRA_WIDTH = 20;
private const int CHECK_EXTRA_WIDTH = 27;
private const int CTRL_MARGIN = 3;
public VCDPropertiesDlg( TIS.Imaging.ICImagingControl ic )
{
icImagingControl = ic;
InitializeComponent();
}
private void VCDPropertiesDlg_Load(object sender, EventArgs e)
{
int height = 7;
// カテゴリーの繰り返し処理
foreach (string Cat in icImagingControl.VCDPropertyItems.CategoryMap.Categories)
{
int subHeight;
// カテゴリのフレームとコントロールを挿入します
InsertCategory(Cat, 7, height, PAGE_WIDTH - 14, out subHeight);
height = height + subHeight;
}
// ページのサイズを変更し、ボタンの位置を調整します
this.Width = PAGE_WIDTH;
this.Height = height + OKButton.Height + 14 + 14 + 7;
OKButton.Top = height;
OKButton.Left = this.Width - 14 - OKButton.Width;
UpdateButton.Top = height;
UpdateButton.Left = OKButton.Left - 7 - UpdateButton.Width;
this.Height = 500;
}
private void UpdateControls()
{
// コントローラーを更新する
icImagingControl.VCDPropertyItems.Update();
foreach (IControlBase ctl in allControls)
{
ctl.UpdateControl();
}
}
private void UpdateButton_Click(object sender, EventArgs e)
{
UpdateButton.Enabled = false;
UpdateControls();
UpdateButton.Enabled = true;
}
private void OKButton_Click(object sender, EventArgs e)
{
this.Close();
}
private void CreateCategoryFrame(string name, int left, int top, int width)
{
// フレームオブジェクトを作成する
System.Windows.Forms.GroupBox frm = new System.Windows.Forms.GroupBox();
frm.Name = "Group" + allControls.Count;
this.Controls.Add(frm);
frm.Text = Name;
frm.SetBounds(left, top, width, 0);
// グローバルなフレームオブジェクトを適用する
currentFrame = frm;
}
private void CreatePropertyLabel(string name, int left, int top, int width, int height)
{
// ラベルオブジェクトを作成する
System.Windows.Forms.Label lbl = new System.Windows.Forms.Label();
lbl.Name = "Label" + allControls.Count;
currentFrame.Controls.Add(lbl);
lbl.SetBounds(left, top, width, height);
lbl.Text = name;
}
private void CreateRangeSlider(TIS.Imaging.VCDRangeProperty itf, int left, int top, int width, int height)
{
// RangeSlider controlを作成する
RangeSlider Slider = new RangeSlider( itf );
Slider.Name = "slider" + allControls.Count;
currentFrame.Controls.Add(Slider);
Slider.SetBounds(left, top, width, height);
// sistercontrols collectionを追加
currentSisterControls.Add(Slider);
// sistersliders collectionを追加
currentSisterSliders.Add(Slider);
//コントローラにthe sistersliders groupを引き渡す
Slider.setSisterSliders(currentSisterSliders);
// グローバルリストコントロールに追加する
allControls.Add(Slider);
}
private void CreateAbsValSlider(TIS.Imaging.VCDAbsoluteValueProperty itf, int left, int top, int width, int height)
{
// VCDAbsoluteValuePropertyに対応したスライダーを作成する
AbsValSlider Slider = new AbsValSlider( itf );
Slider.Name = "absvalslider" + allControls.Count;
currentFrame.Controls.Add(Slider);
Slider.SetBounds(left, top, width, height);
// sistercontrols collectionを追加
currentSisterControls.Add(Slider);
// sistersliders collectionを追加
currentSisterSliders.Add(Slider);
// コントローラにthe sistersliders groupを引き渡す
Slider.setSisterSliders(currentSisterSliders);
// グローバルリストコントロールに追加する
allControls.Add(Slider);
}
private void CreateSwitch(TIS.Imaging.VCDSwitchProperty itf, int left, int top, int width, int height)
{
// Switch Controlを作成
Switch swtch = new Switch( itf );
swtch.Name = "switch" + allControls.Count;
currentFrame.Controls.Add(swtch);
swtch.SetBounds(left, top, width, height);
// sistercontrols collectionを追加
currentSisterControls.Add(swtch);
// コントロールにthe sistersliders groupを引き渡す
swtch.setSisterControls(currentSisterControls);
// グローバルリストコントロールに追加する
allControls.Add(swtch);
}
private void CreateButton(TIS.Imaging.VCDButtonProperty itf, int left, int top, int width, int height)
{
// PushButton controlを追加
PushButton btn = new PushButton( itf );
btn.Name = "button" + allControls.Count;
currentFrame.Controls.Add(btn);
btn.SetBounds(left, top, width, height);
// sistercontrols collectionにコントロールを追加
currentSisterControls.Add(btn);
// コントロールにthe sistersliders groupを引き渡す
btn.setSisterControls(currentSisterControls);
// グローバルリストコントロールに追加する
allControls.Add(btn);
}
private void CreateCombo(TIS.Imaging.VCDMapStringsProperty itf, int left, int top, int width, int height)
{
// StringCombo controlを追加
StringCombo cbo = new StringCombo( itf );
cbo.Name = "combo" + allControls.Count;
currentFrame.Controls.Add(cbo);
cbo.SetBounds(left, top, width, height);
// sistercontrols collectionにコントロールを追加
currentSisterControls.Add(cbo);
// sistersliders collectionにコントロールを追加
currentSisterSliders.Add(cbo);
// コントロールにthe sistersliders groupを引き渡す
cbo.setSisterSliders(currentSisterSliders);
// グローバルリストコントロールに追加する
allControls.Add(cbo);
}
private void InsertElement(TIS.Imaging.VCDPropertyElement elem, ref int x, ref int y, string txt)
{
// すべてのインターフェースを宣言
VCDAbsoluteValueProperty AbsValItf = elem.Find<VCDAbsoluteValueProperty>();
VCDMapStringsProperty MapStringsItf = elem.Find<VCDMapStringsProperty>();
VCDRangeProperty RangeItf = elem.Find<VCDRangeProperty>();
VCDSwitchProperty SwitchItf = elem.Find<VCDSwitchProperty>();
VCDButtonProperty buttonItf = elem.Find<VCDButtonProperty>();
// スライダーで表示され、スライダーにはプロパティの名前が表示されないため
// VCDAbsoluteValueProperty、VCDMapStringsProperty、VCDRangePropertyのときにラベルを用意する。
int labelWidth = 0;
if ((AbsValItf != null || MapStringsItf != null || RangeItf != null) && (txt != ""))
{
labelWidth = TextWidth(txt);
if (labelWidth < LABEL_WIDTH)
{
labelWidth = LABEL_WIDTH;
}
CreatePropertyLabel(txt, x, y + CTRL_HEIGHT / 4, labelWidth, CTRL_HEIGHT / 4 * 3);
x = x + labelWidth;
}
int w = 0;
// VCDAbsoluteValuePropertyを取得できた場合は、適切なスライダーを作成
if (AbsValItf != null)
{
CreateAbsValSlider(AbsValItf, x, y, SLIDER_WIDTH, CTRL_HEIGHT);
x = x + SLIDER_WIDTH + CTRL_MARGIN;
// VCDMapStringsPropertyを取得できた場合は、コンボボックスを作成
}
else if (MapStringsItf != null)
{
// エントリの幅に基づいて、コンボボックスの必要なwithを計算します
int boxWidth = 0;
foreach (string s in MapStringsItf.Strings)
{
w = TextWidth(s);
if (w > boxWidth)
{
boxWidth = w;
}
}
// ドロップダウンボタン用にスペースを追加します
boxWidth = boxWidth + COMBO_EXTRA_WIDTH;
CreateCombo(MapStringsItf, x, y, boxWidth, CTRL_HEIGHT);
x = x + boxWidth + CTRL_MARGIN;
// 範囲インターフェイスを取得できた場合は、範囲スライダーを作成します
}
else if (RangeItf != null)
{
CreateRangeSlider(RangeItf, x, y, SLIDER_WIDTH, CTRL_HEIGHT);
x = x + SLIDER_WIDTH + CTRL_MARGIN;
// VCDSwitchPropertyを取得した場合は、スイッチチェックボックスを作成します
}
else if (SwitchItf != null)
{
// スイッチコントロールの必要な幅を決定する
int switchWidth = TextWidth(elem.Name);
switchWidth = switchWidth + CHECK_EXTRA_WIDTH;
CreateSwitch(SwitchItf, x, y, switchWidth, CTRL_HEIGHT);
x = x + switchWidth + CTRL_MARGIN;
}
// ボタンコントローラを作成する
else if (buttonItf != null)
{
//ボタンコントロールの必要な幅を決定する
int buttonWidth = TextWidth(elem.Name);
buttonWidth = buttonWidth + BUTTON_EXTRA_WIDTH;
CreateButton(buttonItf, x, y, buttonWidth, CTRL_HEIGHT);
x = x + buttonWidth + CTRL_MARGIN;
}
}
private void InsertItem(TIS.Imaging.VCDPropertyItem item, ref int y)
{
int x = 20;
// valueやAutoやOne Pushのアイテムを探す
VCDPropertyElement valueElem = item.Elements.FindElement(TIS.Imaging.VCDGUIDs.VCDElement_Value);
VCDPropertyElement autoElem = item.Elements.FindElement(TIS.Imaging.VCDGUIDs.VCDElement_Auto);
VCDPropertyElement onepushElem = item.Elements.FindElement(TIS.Imaging.VCDGUIDs.VCDElement_OnePush);
//ホワイトバランスは例外
if (item.ItemGUID == TIS.Imaging.VCDGUIDs.VCDID_WhiteBalance)
{
if (item.Elements.FindElement(TIS.Imaging.VCDGUIDs.VCDElement_WhiteBalanceRed) != null)
{
valueElem = null;
}
}
// ラベルの適切なサイズに調整する
int labelWidth = TextWidth(item.Name);
if (labelWidth < LABEL_WIDTH)
{
labelWidth = LABEL_WIDTH;
}
CreatePropertyLabel(item.Name, x, y + CTRL_HEIGHT / 4, labelWidth, CTRL_HEIGHT / 4 * 3);
x = x + labelWidth + CTRL_MARGIN;
// valueやAutoやOne Pushのアイテムを作成する
if (valueElem != null)
{
InsertElement(valueElem, ref x, ref y, "");
}
if (autoElem != null)
{
InsertElement(autoElem, ref x, ref y, "");
}
if (onepushElem != null)
{
InsertElement(onepushElem, ref x, ref y, "");
}
y = y + ROW_HEIGHT;
// valueやAutoやOne Push以外のコントロールは作成しない
foreach (TIS.Imaging.VCDPropertyElement elem in item.Elements)
{
Guid guid = elem.ElementGUID;
if (guid != TIS.Imaging.VCDGUIDs.VCDElement_Value & guid != TIS.Imaging.VCDGUIDs.VCDElement_Auto & guid != VCDGUIDs.VCDElement_OnePush)
{
x = 25;
InsertElement(elem, ref x, ref y, elem.Name);
y = y + ROW_HEIGHT;
}
}
}
private void InsertCategory(string category, int left, int top, int right, out int height)
{
int y = 20;
// カテゴリに対するフレームを作成する
CreateCategoryFrame(category, left, top, right - left);
// このカテゴリに対する新しいコントロールグループを作成する
currentSisterControls = new System.Collections.ArrayList();
// このカテゴリーの中のアイテムを探しだし、あったらアイテムを追加する
foreach (Guid itemID in icImagingControl.VCDPropertyItems.CategoryMap.ItemIDs[category])
{
TIS.Imaging.VCDPropertyItem item = icImagingControl.VCDPropertyItems.FindItem(itemID);
// コントロールを挿入する
if (item != null)
{
currentSisterSliders = new System.Collections.ArrayList();
InsertItem(item, ref y);
}
}
// フレームの高さを調整する
currentFrame.Height = y + 7;
// フレームの高さをコントロールが増えた分調整する
height = y + 14;
}
private void UpdateTimer_Tick(object sender, EventArgs e)
{
UpdateControls();
}
private int TextWidth(string s)
{
System.Drawing.Graphics g = this.CreateGraphics();
int w = (int)g.MeasureString(s, this.Font).Width + 7;
g.Dispose();
return w;
}
VCDPropertiesDlgでは先述したAbsValSlider、PushButton、RangeSlider、StringCombo、Switchなどを使い、VCDPropertyItemsからすべてのVCDPropertyItem, VCDPropertyElement, VCDPropertyInterfaceにアクセスすることで全プロパティを見つけ出すことができます。
VCDPropertyInterfaceにあったユーザコントロールを割り当て配置していくことで、すべてのプロパティを把握していなくても全プロパティを網羅したダイアログ画面を作成することができます。