画像処理アプリケーションフレームワーク

Classes

ClassDescription
Public classDataInfo
データ情報
Public classDataObject<(Of <(<'TYPE>)>)>
データオブジェクト
Public classParserEventArgs
画像処理イベント引数クラス
Public classParserInfo
画像処理アプリケーション構成情報
Public classParserNode
画像処理ノード (基本クラス)
Public classParserNodeFolder
画像処理ノード (フォルダ) ※WIL-Builder プラグイン対応
Public classParserNodeUnit
画像処理ノード (基本ユニット) ※WIL-Builder プラグイン対応
Public classParserProperty
画像処理処理ノードのプロパティ
Public classParserThread
画像処理アプリケーションスレッド
Public classSharedData
共有データ

Interfaces

InterfaceDescription
Public interfaceIAuxCamera
カメラ初期化パラメータインターフェース
Public interfaceIAuxDio
デジタル入出力インターフェース
Public interfaceIAuxGrabber
イメージグラバーインターフェース
Public interfaceIAuxSerialPort
シリアル通信インターフェース
Public interfaceIAuxTcpClient
TCP/IP 通信クライアントインターフェース
Public interfaceIAuxTcpServer
TCP/IP 通信サーバーインターフェース
Public interfaceIAuxUdpClient
UDP 通信クライアントインターフェース
Public interfaceIDataObject<(Of <(<'TYPE>)>)>
データインターフェース
Public interfaceIParserEntryPoint
プラグインエントリポイントインターフェース
Public interfaceIParserNodeFeatures
実装する機能の説明を取得するインターフェース
Public interfaceIParserNodeIndexer
データ配列指標を持つノードのインターフェース
Public interfaceIParserNodeInstance
インスタンスを保有するノードのインターフェース
Public interfaceIParserNodeMode
処理モードを持つノードのインターフェース
Public interfaceIParserNodePropertyDialog
プロパティダイアログを持つノードのインターフェース
Public interfaceIParserNodeRemarks
ノードと入出力の説明を取得するインターフェース
Public interfaceIParserNodeScope
スコープを持つノードのインターフェース
Public interfaceIParserNodeStatisticsCtrl
統計コントロールを持つノードのインターフェース
Public interfaceIParserNodeVisibleLevel
ノードの描画処理の可視属性のインターフェース
Public interfaceIParserPropertyDenyDisposing
ノード入出力プロパティの解放の拒否インターフェース
Public interfaceIStatisticsCtrl
統計コントロールインターフェース

Delegates

DelegateDescription
Public delegateParserEventHandler
画像処理完了イベントのデリゲート

Enumerations

EnumerationDescription
Public enumerationEventReason
イベント発生理由
Public enumerationIndexMode
データ指標モード
Public enumerationSavingLevel
保存レベル
Public enumerationVisibleLevel
可視レベル

Remarks

このネームスペースには、画像処理アプリケーションを容易に開発するためのフレームワークを集約しています。


トピック:


構成:

画像処理アプリケーションをモデル化すると下記の3つの要素で構成されます。

  1. ユーザーインターフェース
  2. 外部機器の実装部分
  3. 画像処理の実装部分
開発コストの多くは『 1.ユーザーインターフェース 』の構築に集中します。 次いで『 2.外部機器の実装部分 』、『 3.画像処理の実装部分 』の順になります。 このネームスペースに集約されるクラスは、これらの構成要素の連携を容易にすることで 間接的にコスト低減することを目的としています。

主要なクラスは以下の3つ(橙色の矩形)です。
下図はクラス間の依存関係を示します。矢印が依存方向です。

クラス概要
ParserThread 画像処理スレッドです。
後述の画像処理ノードを周期処理するために使用します。 ユーザーが .NET Framework の BackgroundWorker を使用して 周期処理をする事とほぼ等価ですが、 周期処理の実行回数の管理など、僅かにコーディングの手間を省けます。
ParserInfo 外部機器の構成情報を管理するクラスです。
このクラスは XML ファイルから構成情報を読み込み各デバイスの初期化を行います。 内部には各デバイスのコントローラを監視するスレッドを保有しており、 デバイスの状態変化(例:取り込み完了、割り込み発生、データ受信等)をイベントによって ユーザーアプリケーションに通知する仕組みになっています。 通常、構成情報の復元やデバイスの初期化/監視処理をユーザーアプリケーションに実装するには 膨大なコーディングを必要としますので、このクラスを使用する事でコード量を低減することができます。 現在のところ、イメージグラバー・デジタル入出力・シリアル通信・TCP/IP通信・UDP通信に対応しています。
関連:
FVIL.Imaging, FVIL.IO, FVIL.Ports, FVIL.Net
ParserNode 画像処理を実装する為の基本クラスです。
本ライブラリでは、画像処理ノードと呼称しています。 ユーザーはこのクラスの派生クラスを作成し 独自の画像処理を実装することで本フレームワークで動作させることができます。 派生クラスのひな型は WIL-Builder (評価アプリケーション) のソースコード生成機能を 使用すると容易に作成することができます。

[↑戻る]


コンポーネント図 (ParserThread):

下図は ParserThread の構造を示します。

  1. Setup/Dispose によってスレッドの初期化/解放が行えます。
  2. Start/Stop/Abort でスレッドの開始/停止/中断が行えます。
  3. スレッド実行中は、画像処理ノードを繰り返し実行します。


[↑戻る]


コンポーネント図 (ParserInfo):

下図は ParserInfo の構造を示します。

  1. Load/Save によって外部機器の構成情報の読み込みと保存が行えます。
  2. Setup/Dispose で内部のデバイスコントローラの初期化と解放が行えます。
  3. インターフェースを介して内部のデバイスコントローラを操作できます。

関連:
IAuxCamera
IAuxGrabber
IAuxDio
IAuxSerialPort
IAuxTcpServer
IAuxTcpClient
IAuxUdpClient

[↑戻る]

Examples


サンプルコード:

具体的な実装方法を示します。


目次:


1. プロジェクトの準備

本プロジェクトは、3つのソースコード(Program.cs, MainForm.cs, ParserNodeUser.cs)で構成されます。 (参照設定については、ここでは省略します。チュートリアルを参考にしてください。) また、実行時には、構成情報を保存した ParserInfo.xml を使用します。 本例では、ParserInfo.xmlParserNodeUser.csWIL-Builder で下図(1-b, 1-c)のように構築して生成しています。


図1-a) プロジェクト:


図1-b) WIL-Builder - Data タブ:

ParserInfo.xml は、下図 で設定した外部機器構成を保存したものです。
ここでは、イメージグラバー・デジタル入出力・シリアル通信のみを接続しています。
このファイルは、WIL-Builder の File メニューの『 Save Configuration 』で生成できます。


図1-c) WIL-Builder - Task タブ:

ParserNodeUser.cs は 下図 で構築した画像処理ワークフローをソースコードに変換したものです。
このファイルは、WIL-Builder の File メニューの『 Save Source Code 』で生成できます。

[↑戻る]


2. ParserNodeUser (画像処理)

下記は WIL-Builder のソースコード生成機能で出力した画像処理フローです。 (※ Execute メソッド以外のメソッドは本例では使用しないので削除しています。) カメラから画像を1枚取り込んで QR コード認識し、デコードした文字列をシリアル通信で送信しています。 この例で使用している外部機器はイメージグラバーとシリアル通信だけですが、 デジタル入出力を使用する場合は他の外部機器と同様に ParserInfo をインターフェースにキャストすることで操作できます。 外部機器のインターフェースは、IAux プレフィックスが付加されたものです。 イメージグラバーの場合は IAuxGrabber、 シリアル通信の場合は IAuxSerialPort、 デジタル入出力の場合は IAuxDio インターフェースを使用します。

C# Copy imageCopy
namespace FVIL.Parser
{
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Drawing;
    using System.Reflection;
    using System.ComponentModel;
    using System.Windows.Forms;
    using System.Runtime.Serialization;
    using System.Security.Permissions;
    using System.Globalization;
    using fvalgcli;


    [System.SerializableAttribute()]
    [System.ComponentModel.TypeConverterAttribute(typeof(System.ComponentModel.ExpandableObjectConverter))]
    public partial class ParserNodeUser : FVIL.Parser.ParserNodeUnit
    {
        /// <summary>
        /// コンストラクタ.
        /// </summary>
        public ParserNodeUser()
        {
        }

        /// <summary>
        /// コンストラクタ.
        /// </summary>
        protected ParserNodeUser(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) : 
                base(info, context)
        {
        }

        /// <summary>
        /// 実行 (1回分の画像処理を記述します。ParserThread から繰り返し呼ばれます。)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public override void Execute(object sender, System.EventArgs e)
        {
            FVIL.Data.CFviImage target1_out0 = new FVIL.Data.CFviImage(640, 480, FVIL.ImageType.RGB32, 1);
            FVIL.Data.CFviImage target2_out0 = new FVIL.Data.CFviImage(640, 480, FVIL.ImageType.UC8, 1);
            FVIL.QR.CFviQRResult target3_out0 = new FVIL.QR.CFviQRResult();
            FVIL.QR.CFviQRData target4_out0 = new FVIL.QR.CFviQRData();
            FVIL.Data.CFviPoint target4_out1 = new FVIL.Data.CFviPoint(279.59361580612148, 345.94194954668984);
            int target4_out2 = 29;
            string target4_out3 = "http://m.jtad.jp/w/?s=50220585091739";
            double target4_out4 = 4.203502996971773;
            int target4_out5 = 4;
            int target4_out6 = 430;
            int target4_out7 = 4;

            // 画像取り込み (同期)#1
            FVIL.Imaging.GrabberThread target1 = ((FVIL.Parser.IAuxGrabber)(ParserInfo)).Threads[0];
            ((FVIL.Imaging.IGrabImageSync)(target1)).Grab(target1_out0);

            // 濃淡化#1
            FVIL.Conversion.CFviGrayScale target2 = new FVIL.Conversion.CFviGrayScale();
            target2.SrcImages[0] = target1_out0;
            target2.DstImages[0] = target2_out0;
            target2.CoefficientBlue = 0.114;
            target2.CoefficientGreen = 0.587;
            target2.CoefficientRed = 0.299;
            target2_out0.Depth = 8;
            target2.Execute();

            // QRコード認識#1
            FVIL.QR.CFviQR target3 = new FVIL.QR.CFviQR();
            target3.SrcImages[0] = target2_out0;
            target3.Result = target3_out0;
            target3.Param.BinThreshold = 128;
            target3.Param.BinMethod = FVIL.QR.BinMethod.Average;
            target3.Param.EffortLevel = FVIL.QR.EffortLevel.Maximum;
            target3.Param.MinVar = 1000;
            target3.Param.WindowSize = 11;
            target3.Execute();

            // QRコードデータ#1
            target4_out0.CopyFrom(target3_out0[0]);
            target4_out1 = target4_out0.Center;
            target4_out2 = target4_out0.Size;
            target4_out3 = target4_out0.Text;
            target4_out4 = target4_out0.MinCellWidth;
            target4_out5 = target4_out0.ApptsCount;
            target4_out6 = target4_out0.CellOnesCount;
            target4_out7 = target4_out0.DelimitingPtsCount;

            // シリアル通信 (送信)#1
            System.IO.Ports.SerialPort target5 = ((FVIL.Parser.IAuxSerialPort)(ParserInfo)).Ports[0];
            target5.WriteLine(target4_out3.ToString());
        }
    }
}


Visual Basic Copy imageCopy
Imports System.Collections.Generic
Imports System.Text
Imports System.Drawing
Imports System.Reflection
Imports System.ComponentModel
Imports System.Windows.Forms
Imports System.Runtime.Serialization
Imports System.Security.Permissions
Imports System.Globalization
Imports fvalgcli
Imports FVIL.Parser


<System.SerializableAttribute()> _
<System.ComponentModel.TypeConverterAttribute(GetType(System.ComponentModel.ExpandableObjectConverter))> _
Partial Public Class ParserNodeUser
    Inherits FVIL.Parser.ParserNodeUnit
    ''' <summary>
    ''' コンストラクタ
    ''' </summary>
    Public Sub New()
    End Sub

    ''' <summary>
    ''' コンストラクタ
    ''' </summary>
    Protected Sub New(ByVal info As System.Runtime.Serialization.SerializationInfo, ByVal context As System.Runtime.Serialization.StreamingContext)
        MyBase.New(info, context)
    End Sub

    ''' <summary>
    ''' 実行(1回分の画像処理を記述します。ParserThread から繰り返し呼ばれます。)
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Public Overrides Sub Execute(ByVal sender As Object, ByVal e As System.EventArgs)
        Dim target1_out0 As New FVIL.Data.CFviImage(640, 480, FVIL.ImageType.RGB32, 1)
        Dim target2_out0 As New FVIL.Data.CFviImage(640, 480, FVIL.ImageType.UC8, 1)
        Dim target3_out0 As New FVIL.QR.CFviQRResult()
        Dim target4_out0 As New FVIL.QR.CFviQRData()
        Dim target4_out1 As New FVIL.Data.CFviPoint(279.593615806121, 345.94194954669)
        Dim target4_out2 As Integer = 29
        Dim target4_out3 As String = "http://m.jtad.jp/w/?s=50220585091739"
        Dim target4_out4 As Double = 4.20350299697177
        Dim target4_out5 As Integer = 4
        Dim target4_out6 As Integer = 430
        Dim target4_out7 As Integer = 4

        ' 画像取り込み (同期)#1
        Dim target1 As FVIL.Imaging.GrabberThread = DirectCast(ParserInfo, FVIL.Parser.IAuxGrabber).Threads(0)
        DirectCast(target1, FVIL.Imaging.IGrabImageSync).Grab(target1_out0)

        ' 濃淡化#1
        Dim target2 As New FVIL.Conversion.CFviGrayScale()
        target2.SrcImages(0) = target1_out0
        target2.DstImages(0) = target2_out0
        target2.CoefficientBlue = 0.114
        target2.CoefficientGreen = 0.587
        target2.CoefficientRed = 0.299
        target2_out0.Depth = 8
        target2.Execute()

        ' QRコード認識#1
        Dim target3 As New FVIL.QR.CFviQR()
        target3.SrcImages(0) = target2_out0
        target3.Result = target3_out0
        target3.Param.BinThreshold = 128
        target3.Param.BinMethod = FVIL.QR.BinMethod.Average
        target3.Param.EffortLevel = FVIL.QR.EffortLevel.Maximum
        target3.Param.MinVar = 1000
        target3.Param.WindowSize = 11
        target3.Execute()

        ' QRコードデータ#1
        target4_out0.CopyFrom(target3_out0(0))
        target4_out1 = target4_out0.Center
        target4_out2 = target4_out0.Size
        target4_out3 = target4_out0.Text
        target4_out4 = target4_out0.MinCellWidth
        target4_out5 = target4_out0.ApptsCount
        target4_out6 = target4_out0.CellOnesCount
        target4_out7 = target4_out0.DelimitingPtsCount

        ' シリアル通信 (送信)#1
        Dim target5 As System.IO.Ports.SerialPort = DirectCast(ParserInfo, FVIL.Parser.IAuxSerialPort).Ports(0)
        target5.WriteLine(target4_out3.ToString())
    End Sub
End Class

[↑戻る]


3. Program (初期化)
  • 構成情報の初期化:
    Load メソッドで ParserInfo.xml を読み込み、Setup メソッドで初期化しています。 (※ParserInfo.xml の生成は、WIL-Builder を使用してください。生成された XML は下記を参照ください。) この時、XML の内容に従って各デバイスのオープンを行い、デバイスコントローラの監視スレッドを起動します。
  • 画像処理スレッドの初期化:
    Setup メソッドで初期化しています。この時点でスレッドが待機状態になります。 この他、ParserInfo/ParserNode プロパティにインスタンスを設定する必要があります。 このスレッドは、ParserInfo/ParserNode プロパティを介してデバイスの操作や 画像処理ノードの開始/停止を行います。
  • 画像処理ノードの初期化:
    Setup メソッドで初期化しています。(※注:本例では SetupOverlay を省略しています。) この他、ParserInfo プロパティにインスタンスを設定する必要があります。 画像処理ノードに実装した処理でデバイスの操作を行うために必要です。

C# Copy imageCopy
using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace SampleCode
{
    static class Program
    {
        /// <summary>
        /// アプリケーションのメイン エントリ ポイントです.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            // ライブラリの初期化.
            FVIL._SetUp.InitVisionLibrary();
            FVIL._SetUp.AppPath = System.IO.Directory.GetCurrentDirectory();

            try
            {
                // 構成情報の初期化.
                string config_file = "ParserInfo.xml";
                if (System.IO.File.Exists(config_file))
                    Defs.ParserInfo.Load(config_file);
                Defs.ParserInfo.Setup();

                // 画像処理スレッドの初期化.
                Defs.ParserThread.Setup();
                Defs.ParserThread.ParserInfo = Defs.ParserInfo;
                Defs.ParserThread.ParserNode = Defs.ParserNode;

                // 画像処理ノードの初期化.
                Defs.ParserNode.Setup();
                Defs.ParserNode.ParserInfo = Defs.ParserInfo;

                MainForm form = new MainForm();
                Application.Run(form);
            }
            finally
            {
                // 解放.
                Defs.ParserThread.Dispose();
                Defs.ParserInfo.Dispose();
                Defs.ParserNode.Dispose();
            }
        }

    }

    static class Defs
    {
        /// <summary>
        /// 画像処理スレッド.
        /// </summary>
        static public FVIL.Parser.ParserThread ParserThread = new FVIL.Parser.ParserThread();

        /// <summary>
        /// 画像処理ノード.
        /// </summary>
        static public FVIL.Parser.ParserNodeUser ParserNode = new FVIL.Parser.ParserNodeUser();

        /// <summary>
        /// 画像処理アプリケーション構成情報.
        /// </summary>
        static public FVIL.Parser.ParserInfo ParserInfo = new FVIL.Parser.ParserInfo();
    }
}


Visual Basic Copy imageCopy
Imports System.Collections.Generic
Imports System.Windows.Forms

NotInheritable Class Program
    Private Sub New()
    End Sub
    ''' <summary>
    ''' アプリケーションのメイン エントリ ポイントです。
    ''' </summary>
    <STAThread> _
    Friend Shared Sub Main()
        Application.EnableVisualStyles()
        Application.SetCompatibleTextRenderingDefault(False)

        ' ライブラリの初期化.
        FVIL._SetUp.InitVisionLibrary()
        FVIL._SetUp.AppPath = System.IO.Directory.GetCurrentDirectory()

        Try
            ' 構成情報の初期化.
            Dim config_file As String = "ParserInfo.xml"
            If System.IO.File.Exists(config_file) Then
                Defs.ParserInfo.Load(config_file)
            End If
            Defs.ParserInfo.Setup()

            ' 画像処理スレッドの初期化.
            Defs.ParserThread.Setup()
            Defs.ParserThread.ParserInfo = Defs.ParserInfo
            Defs.ParserThread.ParserNode = Defs.ParserNode

            ' 画像処理ノードの初期化.
            Defs.ParserNode.Setup()
            Defs.ParserNode.ParserInfo = Defs.ParserInfo

            Dim form As New MainForm()
            Application.Run(form)
        Finally
            ' 解放.
            Defs.ParserThread.Dispose()
            Defs.ParserInfo.Dispose()
            Defs.ParserNode.Dispose()
        End Try
    End Sub

End Class

NotInheritable Class Defs
    Private Sub New()
    End Sub
    ''' <summary>
    ''' 画像処理スレッド
    ''' </summary>
    Public Shared ParserThread As New FVIL.Parser.ParserThread()

    ''' <summary>
    ''' 画像処理ノード
    ''' </summary>
    Public Shared ParserNode As New FVIL.Parser.ParserNodeUser()

    ''' <summary>
    ''' 画像処理アプリケーション構成情報
    ''' </summary>
    Public Shared ParserInfo As New FVIL.Parser.ParserInfo()
End Class


ParserInfo.xml

Xml Copy imageCopy
<?xml version="1.0" encoding="utf-8"?>
<ParserInfo>
  <Description />
  <Passcode />
  <IsAuto>false</IsAuto>
  <IsFullscreen>false</IsFullscreen>
  <IsMaintenance>false</IsMaintenance>
  <ImageSavingDir>images</ImageSavingDir>
  <ImageSavingLevel>Error</ImageSavingLevel>
  <ImageSavingMax>30</ImageSavingMax>
  <DataInfos />
  <CameraParams />
  <GrabberInfos>
    <GrabberInfo>
      <ConfigFile>C:\FAST\WIL\3.0.0\CameraFiles\DS\DS_USB0.xml</ConfigFile>
      <BufferNum>2</BufferNum>
      <PluginAssembly />
      <PluginClassName />
      <SimulatorFile />
      <SimulatorFileMode>Normal</SimulatorFileMode>
      <SimulatorOption>Auto</SimulatorOption>
      <Commands />
    </GrabberInfo>
  </GrabberInfos>
  <DioInfos>
    <DioInfo>
      <Kind>II320</Kind>
      <DeviceID>0</DeviceID>
      <PluginAssembly />
      <PluginClassName />
      <SimulatorOption>Auto</SimulatorOption>
      <Commands>
        <string>InterruptEdge=Rise</string>
      </Commands>
      <BitAssignDI />
      <BitAssignDO />
    </DioInfo>
  </DioInfos>
  <SerialPortInfos>
    <SerialPortInfo>
      <PortName>COM11</PortName>
      <BaudRate>9600</BaudRate>
      <Parity>None</Parity>
      <DataBits>8</DataBits>
      <StopBits>One</StopBits>
      <Handshake>None</Handshake>
      <NewLine>CR</NewLine>
      <ReadBufferSize>4096</ReadBufferSize>
      <ReadTimeout>500</ReadTimeout>
      <ReceivedBytesThreshold>1</ReceivedBytesThreshold>
      <WriteBufferSize>2048</WriteBufferSize>
      <WriteTimeout>500</WriteTimeout>
      <DtrEnable>false</DtrEnable>
      <RtsEnable>false</RtsEnable>
    </SerialPortInfo>
  </SerialPortInfos>
  <TcpServerInfos />
  <TcpClientInfos />
  <UdpClientInfos />
</ParserInfo>

[↑戻る]


4. MainForm

下記はメインフォームのアウトラインです。
コード中に記載するコメントの (1)~(4) の部分の実装内容については 後述の 4-1~4-4 をご参照ください。

C# Copy imageCopy
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace SampleCode
{
    /// <summary>
    /// 画像処理アプリケーションメインフォーム.
    /// </summary>
    public partial class MainForm : Form
    {
        /// <summary>
        /// コンストラクタ.
        /// </summary>
        public MainForm()
        {
            InitializeComponent();
        }

        /// <summary>
        /// フォームロード時の初期化処理.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainForm_Load(object sender, EventArgs e)
        {
            // (1) 画像処理スレッド関連.(イベントハンドラ登録)

            // (2) イメージグラバー関連.(イベントハンドラ登録)

            timerUpdateUI.Enabled = true;
        }

        /// <summary>
        /// フォームが閉じられるときの解放処理.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            timerUpdateUI.Enabled = false;
        }

        /// <summary>
        /// 定期的な表示更新処理.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timerUpdateUI_Tick(object sender, EventArgs e)
        {
            // (1) 画像処理スレッド関連.(表示更新)

            // (2) イメージグラバー関連.(表示更新)

            // (3) デジタル入出力関連.(表示更新)

            // (4) シリアル通信関連.(表示更新)

            // (2) イメージグラバー関連.(取り込み完了イベント)

            // (1) 画像処理スレッド関連.(完了イベント)
        }

        // (1) 画像処理スレッド関連.

        // (2) イメージグラバー関連.

        // (3) デジタル入出力関連.

        // (4) シリアル通信関連.
    }
}


Visual Basic Copy imageCopy
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Text
Imports System.Windows.Forms

''' <summary>
''' 画像処理アプリケーションメインフォーム
''' </summary>
Public Partial Class MainForm
    Inherits Form
    ''' <summary>
    ''' コンストラクタ
    ''' </summary>
    Public Sub New()
        InitializeComponent()
    End Sub

    ''' <summary>
    ''' フォームロード時の初期化処理
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub MainForm_Load(sender As Object, e As EventArgs)
        '' (1) 画像処理スレッド関連.(イベントハンドラ登録)

        '' (2) イメージグラバー関連.(イベントハンドラ登録)

        timerUpdateUI.Enabled = True
    End Sub

    ''' <summary>
    ''' フォームが閉じられるときの解放処理
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub MainForm_FormClosing(sender As Object, e As FormClosingEventArgs)
        timerUpdateUI.Enabled = False
    End Sub

    ''' <summary>
    ''' 定期的な表示更新処理
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub timerUpdateUI_Tick(sender As Object, e As EventArgs)
        '' (1) 画像処理スレッド関連.(表示更新)

        '' (2) イメージグラバー関連.(表示更新)

        '' (3) デジタル入出力関連.(表示更新)

        '' (4) シリアル通信関連.(表示更新)

        '' (2) イメージグラバー関連.(取り込み完了イベント)

        '' (1) 画像処理スレッド関連.(完了イベント)
    End Sub

    '' (1) 画像処理スレッド関連.

    '' (2) イメージグラバー関連.

    '' (3) デジタル入出力関連.

    '' (4) シリアル通信関連.
End Class

[↑戻る]


4-1. MainForm (画像処理スレッド)

下記のソースコードには、画像処理スレッド(ParserThread)に関連する処理のみ抜粋しています。
MainForm_Load ではイベントハンドラを登録しています。 このハンドラはスレッド実行中に画像処理が完了するたびにコールバックされます。

toolThreadStart_Click/toolThreadAbort_Click では、スレッドの開始/停止/中断を行っています。 これらはツールストリップボタンのイベントに関連づけられたハンドラです。

timerUpdateUI_Tick では、ツールストリップボタンの有効/無効やチェックの ON/OFF を行っています。 また、画像処理スレッドの完了イベントを監視して処理結果をステータスストリップに表示しています。

表示処理はプライマリスレッド(ウィンドウハンドルを所有しているスレッド)のタイミングで行う必要があることに注意してください。 別スレッドから直接フォームにアクセスすることはできません。 この例ではタイマーコンポーネントを使用することでプライマリスレッドのタイミングで処理する方法を使用しています。 一般的には、Invoke メソッドを使用します。 その場合は、ParserThread_Notify に表示処理を実装することになります。 Invoke メソッドについては MSDN Library をご参照ください。

MSDN Library:
http://msdn.microsoft.com/ja-jp/library/system.windows.forms.control.invoke(v=vs.80).aspx

C# Copy imageCopy
namespace SampleCode
{
    public partial class MainForm : Form
    {
        public MainForm()
        {
            InitializeComponent();
        }

        /// <summary>
        /// フォームロード時の初期化処理.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainForm_Load(object sender, EventArgs e)
        {
            #region 画像処理スレッド関連.
            Defs.ParserThread.Notify += ParserThread_Notify;
            #endregion
        }

        /// <summary>
        /// 定期的な表示更新処理.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timerUpdateUI_Tick(object sender, EventArgs e)
        {
            #region 画像処理スレッド関連.
            {
                toolThreadStart.Enabled = (Defs.ParserThread != null);
                toolThreadStart.Checked = (Defs.ParserThread != null && Defs.ParserThread.IsBusy);
                toolThreadAbort.Enabled = (Defs.ParserThread != null && Defs.ParserThread.IsBusy);
            }
            #endregion

            #region 画像処理スレッド関連.(完了イベント)
            if (ParserEventArgs != null)
            {
                statusTimeStamp.Text = string.Format(
                    "{0:00}:{1:00}:{2:00}",
                    ParserEventArgs.TimeStamp.Hour,
                    ParserEventArgs.TimeStamp.Minute,
                    ParserEventArgs.TimeStamp.Second);

                statusProcessTime.Text = string.Format(
                    "{0:0.000} ms",
                    ParserEventArgs.ProcessTime);

                if (ParserEventArgs.Exception == null)
                    statusMessage.Text = ParserEventArgs.Message;
                else
                    statusMessage.Text = ParserEventArgs.Exception.Message;

                if (Defs.ParserNode != null)
                {
                    Defs.ParserNode.ChangeVisibleLevel(FVIL.Parser.VisibleLevel.Enable);
                    Defs.ParserNode.Draw(ImageView);
                }
                ParserEventArgs = null;
            }
            #endregion
        }

        /// <summary>
        /// 画像処理スレッドの開始と停止.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolThreadStart_Click(object sender, EventArgs e)
        {
            if (Defs.ParserThread == null) return;
            if (Defs.ParserThread.IsBusy == false)
                Defs.ParserThread.Start();
            else
                Defs.ParserThread.Stop();
        }

        /// <summary>
        /// 画像処理スレッドの中断.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolThreadAbort_Click(object sender, EventArgs e)
        {
            if (Defs.ParserThread == null) return;
            Defs.ParserThread.Abort();
        }

        /// <summary>
        /// 画像処理完了通知イベント.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ParserThread_Notify(object sender, FVIL.Parser.ParserEventArgs e)
        {
            ParserEventArgs = e;
        }

        /// <summary>
        /// 画像処理完了通知イベント引数.
        /// </summary>
        private FVIL.Parser.ParserEventArgs ParserEventArgs = null;
    }
}


Visual Basic Copy imageCopy
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Text
Imports System.Windows.Forms

''' <summary>
''' 画像処理アプリケーションメインフォーム
''' </summary>
Public Partial Class MainForm
    Inherits Form
    ''' <summary>
    ''' コンストラクタ
    ''' </summary>
    Public Sub New()
        InitializeComponent()
    End Sub

    ''' <summary>
    ''' フォームロード時の初期化処理
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub MainForm_Load(sender As Object, e As EventArgs)
        '#Region "画像処理スレッド関連."
        AddHandler Defs.ParserThread.Notify, AddressOf ParserThread_Notify
        '#End Region
    End Sub

    ''' <summary>
    ''' フォームが閉じられるときの解放処理
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub MainForm_FormClosing(sender As Object, e As FormClosingEventArgs)
        timerUpdateUI.Enabled = False
    End Sub

    ''' <summary>
    ''' 定期的な表示更新処理
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub timerUpdateUI_Tick(sender As Object, e As EventArgs)
        '#Region "画像処理スレッド関連."
        If True Then
            toolThreadStart.Enabled = (Defs.ParserThread IsNot Nothing)
            toolThreadStart.Checked = (Defs.ParserThread IsNot Nothing AndAlso Defs.ParserThread.IsBusy)
            toolThreadAbort.Enabled = (Defs.ParserThread IsNot Nothing AndAlso Defs.ParserThread.IsBusy)
        End If
        '#End Region

        '#Region "画像処理スレッド関連.(完了イベント)"
        If ParserEventArgs IsNot Nothing Then
            statusTimeStamp.Text = String.Format("{0:00}:{1:00}:{2:00}", ParserEventArgs.TimeStamp.Hour, ParserEventArgs.TimeStamp.Minute, ParserEventArgs.TimeStamp.Second)

            statusProcessTime.Text = String.Format("{0:0.000} ms", ParserEventArgs.ProcessTime)

            If ParserEventArgs.Exception Is Nothing Then
                statusMessage.Text = ParserEventArgs.Message
            Else
                statusMessage.Text = ParserEventArgs.Exception.Message
            End If

            If Defs.ParserNode IsNot Nothing Then
                Defs.ParserNode.ChangeVisibleLevel(FVIL.Parser.VisibleLevel.Enable)
                Defs.ParserNode.Draw(ImageView)
            End If
            ParserEventArgs = Nothing
        End If
        '#End Region
    End Sub

    ''' <summary>
    ''' 画像処理スレッドの開始と停止
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub toolThreadStart_Click(sender As Object, e As EventArgs)
        If Defs.ParserThread Is Nothing Then
            Return
        End If
        If Defs.ParserThread.IsBusy = False Then
            Defs.ParserThread.Start()
        Else
            Defs.ParserThread.[Stop]()
        End If
    End Sub

    ''' <summary>
    ''' 画像処理スレッドの中断
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub toolThreadAbort_Click(sender As Object, e As EventArgs)
        If Defs.ParserThread Is Nothing Then
            Return
        End If
        Defs.ParserThread.Abort()
    End Sub

    ''' <summary>
    ''' 画像処理完了通知イベント
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub ParserThread_Notify(sender As Object, e As FVIL.Parser.ParserEventArgs)
        ParserEventArgs = e
    End Sub

    ''' <summary>
    ''' 画像処理完了通知イベント引数
    ''' </summary>
    Private ParserEventArgs As FVIL.Parser.ParserEventArgs = Nothing
End Class

[↑戻る]


4-2. MainForm (イメージグラバー)

下記のソースコードには、イメージグラバーに関連する処理のみ抜粋しています。
イメージグラバーを操作するには
ParserInfoIAuxGrabber にキャストして Threads プロパティから GrabberThread を抽出します。 この例では処理の簡略化の為、配列の 0 番目の要素からのみ抽出しています。

MainForm_Load ではイベントハンドラを登録しています。 このハンドラは画像取り込みが完了するたびにコールバックされます。

toolGrabberStart_Click では、スレッドの開始/中断を行っています。 toolGrabberFocusing_Click では、焦点調整フォームをポップアップ表示しています。 これらはツールストリップボタンのイベントに関連づけられたハンドラです。

timerUpdateUI_Tick では、ツールストリップボタンの有効/無効やチェックの ON/OFF を行っています。 また、イメージグラバースレッドの画像取り込み完了イベントを監視して取り込み画像を画像ビューに表示しています。

表示処理はプライマリスレッド(ウィンドウハンドルを所有しているスレッド)のタイミングで行う必要があることに注意してください。 別スレッドから直接フォームにアクセスすることはできません。 この例ではタイマーコンポーネントを使用することでプライマリスレッドのタイミングで処理する方法を使用しています。 一般的には、Invoke メソッドを使用します。 その場合は、GrabberThread_FrameValid に表示処理を実装することになります。 Invoke メソッドについては MSDN Library をご参照ください。

MSDN Library:
http://msdn.microsoft.com/ja-jp/library/system.windows.forms.control.invoke(v=vs.80).aspx

C# Copy imageCopy
namespace SampleCode
{
    public partial class MainForm : Form
    {
        /// <summary>
        /// フォームロード時の初期化処理.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void MainForm_Load(object sender, EventArgs e)
        {
            #region イメージグラバー関連.
            // (注) この例ではコードの簡素化の為に1つ目のグラバーのみ使用しています.
            {
                FVIL.Parser.IAuxGrabber grabber = (FVIL.Parser.IAuxGrabber)Defs.ParserInfo;
                if (grabber.Threads.Length > 0 &&
                    grabber.Threads[0] != null)
                    grabber.Threads[0].FrameValid += GrabberThread_FrameValid;
            }
            #endregion
        }

        /// <summary>
        /// 定期的な表示更新処理.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timerUpdateUI_Tick(object sender, EventArgs e)
        {
            #region イメージグラバー関連.
            {
                FVIL.Parser.IAuxGrabber grabber = (FVIL.Parser.IAuxGrabber)Defs.ParserInfo;
                bool grabber_enable = (grabber.Threads.Length > 0 && grabber.Threads[0] != null);
                toolGrabberStart.Enabled = grabber_enable;
                toolGrabberStart.Checked = (grabber_enable && grabber.Threads[0].IsBusy);
                toolGrabberFocusing.Enabled = (grabber_enable && GrabberFocusingForm == null);
            }
            #endregion

            #region イメージグラバー関連.(取り込み完了イベント)
            if (GrabberEventArgs != null)
            {
                if (GrabberEventArgs.Exception == null &&
                    GrabberEventArgs.Images.Length > 0 &&
                    GrabberEventArgs.Images[0] != null)
                {
                    ImageView.Image = GrabberEventArgs.Images[0];
                    ImageView.Refresh();
                }
                GrabberEventArgs = null;
            }
            #endregion
        }

        /// <summary>
        /// イメージグラバーの開始・停止.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolGrabberStart_Click(object sender, EventArgs e)
        {
            FVIL.Parser.IAuxGrabber grabber = (FVIL.Parser.IAuxGrabber)Defs.ParserInfo;
            if (grabber.Threads.Length == 0) return;
            if (grabber.Threads[0] == null) return;

            try
            {
                FVIL.Imaging.GrabberThread thread = grabber.Threads[0];
                if (thread.IsBusy == false)
                    thread.Start();
                else
                    thread.Abort();
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(this, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 焦点調整フォームの表示.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolGrabberFocusing_Click(object sender, EventArgs e)
        {
            FVIL.Parser.IAuxGrabber grabber = (FVIL.Parser.IAuxGrabber)Defs.ParserInfo;
            if (grabber.Threads.Length == 0) return;
            if (grabber.Threads[0] == null) return;

            try
            {
                FVIL.Imaging.GrabberThread thread = grabber.Threads[0];
                GrabberFocusingForm = thread.CreateFocusingDialog();
                GrabberFocusingForm.FormClosed += GrabberFocusingForm_FormClosed;
                GrabberFocusingForm.Show();
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(this, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 焦点調整フォーム.
        /// </summary>
        private Form GrabberFocusingForm = null;

        /// <summary>
        /// 焦点調整フォームが閉じたとき.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void GrabberFocusingForm_FormClosed(object sender, EventArgs e)
        {
            GrabberFocusingForm = null;
        }

        /// <summary>
        /// イメージグラバーの取り込み完了通知イベント.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void GrabberThread_FrameValid(object sender, FVIL.Imaging.GrabberEventArgs e)
        {
            GrabberEventArgs = e;
        }

        /// <summary>
        /// イメージグラバーの取り込み完了通知イベント引数.
        /// </summary>
        private FVIL.Imaging.GrabberEventArgs GrabberEventArgs = null;
    }
}


Visual Basic Copy imageCopy
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Text
Imports System.Windows.Forms

''' <summary>
''' 画像処理アプリケーションメインフォーム
''' </summary>
Public Partial Class MainForm
    Inherits Form

    ''' <summary>
    ''' フォームロード時の初期化処理
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub MainForm_Load(sender As Object, e As EventArgs)
        '#Region "イメージグラバー関連."
        ' (注) この例ではコードの簡素化の為に1つ目のグラバーのみ使用しています.
        If True Then
            Dim grabber As FVIL.Parser.IAuxGrabber = DirectCast(Defs.ParserInfo, FVIL.Parser.IAuxGrabber)
            If grabber.Threads.Length > 0 AndAlso grabber.Threads(0) IsNot Nothing Then
                AddHandler grabber.Threads(0).FrameValid, AddressOf GrabberThread_FrameValid
            End If
        End If
        '#End Region
    End Sub

    ''' <summary>
    ''' 定期的な表示更新処理
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub timerUpdateUI_Tick(sender As Object, e As EventArgs)
        '#Region "イメージグラバー関連."
        If True Then
            Dim grabber As FVIL.Parser.IAuxGrabber = DirectCast(Defs.ParserInfo, FVIL.Parser.IAuxGrabber)
            Dim grabber_enable As Boolean = (grabber.Threads.Length > 0 AndAlso grabber.Threads(0) IsNot Nothing)
            toolGrabberStart.Enabled = grabber_enable
            toolGrabberStart.Checked = (grabber_enable AndAlso grabber.Threads(0).IsBusy)
            toolGrabberFocusing.Enabled = (grabber_enable AndAlso GrabberFocusingForm Is Nothing)
        End If
        '#End Region

        '#Region "イメージグラバー関連.(取り込み完了イベント)"
        If GrabberEventArgs IsNot Nothing Then
            If GrabberEventArgs.Exception Is Nothing AndAlso GrabberEventArgs.Images.Length > 0 AndAlso GrabberEventArgs.Images(0) IsNot Nothing Then
                ImageView.Image = GrabberEventArgs.Images(0)
                ImageView.Refresh()
            End If
            GrabberEventArgs = Nothing
        End If
        '#End Region
    End Sub

    ''' <summary>
    ''' イメージグラバーの開始・停止
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub toolGrabberStart_Click(sender As Object, e As EventArgs)
        Dim grabber As FVIL.Parser.IAuxGrabber = DirectCast(Defs.ParserInfo, FVIL.Parser.IAuxGrabber)
        If grabber.Threads.Length = 0 Then
            Return
        End If
        If grabber.Threads(0) Is Nothing Then
            Return
        End If

        Try
            Dim thread As FVIL.Imaging.GrabberThread = grabber.Threads(0)
            If thread.IsBusy = False Then
                thread.Start()
            Else
                thread.Abort()
            End If
        Catch ex As System.Exception
            MessageBox.Show(Me, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.[Error])
        End Try
    End Sub

    ''' <summary>
    ''' 焦点調整フォームの表示
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub toolGrabberFocusing_Click(sender As Object, e As EventArgs)
        Dim grabber As FVIL.Parser.IAuxGrabber = DirectCast(Defs.ParserInfo, FVIL.Parser.IAuxGrabber)
        If grabber.Threads.Length = 0 Then
            Return
        End If
        If grabber.Threads(0) Is Nothing Then
            Return
        End If

        Try
            Dim thread As FVIL.Imaging.GrabberThread = grabber.Threads(0)
            GrabberFocusingForm = thread.CreateFocusingDialog()
            AddHandler GrabberFocusingForm.FormClosed, AddressOf GrabberFocusingForm_FormClosed
            GrabberFocusingForm.Show()
        Catch ex As System.Exception
            MessageBox.Show(Me, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.[Error])
        End Try
    End Sub

    ''' <summary>
    ''' 焦点調整フォーム
    ''' </summary>
    Private GrabberFocusingForm As Form = Nothing

    ''' <summary>
    ''' 焦点調整フォームが閉じたとき
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub GrabberFocusingForm_FormClosed(sender As Object, e As EventArgs)
        GrabberFocusingForm = Nothing
    End Sub

    #End Region

    #Region "イメージグラバー関連.(イベントハンドラ)"

    ''' <summary>
    ''' イメージグラバーの取り込み完了通知イベント
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub GrabberThread_FrameValid(sender As Object, e As FVIL.Imaging.GrabberEventArgs)
        GrabberEventArgs = e
    End Sub

    ''' <summary>
    ''' イメージグラバーの取り込み完了通知イベント引数
    ''' </summary>
    Private GrabberEventArgs As FVIL.Imaging.GrabberEventArgs = Nothing
End Class

[↑戻る]


4-3. MainForm (デジタル入出力)

下記のソースコードには、デジタル入出力デバイスに関連する処理のみ抜粋しています。
デジタル入出力デバイスを操作するには
ParserInfoIAuxDio にキャストして Threads プロパティから DioThread を抽出します。 この例では処理の簡略化の為、配列の 0 番目の要素からのみ抽出しています。

toolDioMonitor_Click では、デジタル入出力テストフォームをポップアップ表示しています。 これはツールストリップボタンのイベントに関連づけられたハンドラです。

timerUpdateUI_Tick では、ツールストリップボタンの有効/無効やチェックの ON/OFF を行っています。

C# Copy imageCopy
namespace SampleCode
{
    public partial class MainForm : Form
    {
        /// <summary>
        /// 定期的な表示更新処理.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timerUpdateUI_Tick(object sender, EventArgs e)
        {
            #region デジタル入出力関連.
            {
                FVIL.Parser.IAuxDio dio = (FVIL.Parser.IAuxDio)Defs.ParserInfo;
                bool dio_enable = (dio.Threads.Length > 0 && dio.Threads[0] != null);
                toolDioMonitor.Enabled = (dio_enable && DioMonitorForm == null);
            }
            #endregion
        }

        /// <summary>
        /// デジタル入出力モニタの表示.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolDioMonitor_Click(object sender, EventArgs e)
        {
            FVIL.Parser.IAuxDio dio = (FVIL.Parser.IAuxDio)Defs.ParserInfo;
            if (dio.Threads.Length == 0) return;
            if (dio.Threads[0] == null) return;

            try
            {
                FVIL.IO.DioThread thread = dio.Threads[0];
                DioMonitorForm = thread.CreateTestDialog();
                DioMonitorForm.FormClosed += DioMonitorForm_FormClosed;
                DioMonitorForm.Show();
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(this, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// デジタル入出力モニタ.
        /// </summary>
        private Form DioMonitorForm = null;

        /// <summary>
        /// デジタル入出力モニタが閉じたとき.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void DioMonitorForm_FormClosed(object sender, EventArgs e)
        {
            DioMonitorForm = null;
        }
    }
}


Visual Basic Copy imageCopy
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Text
Imports System.Windows.Forms

''' <summary>
''' 画像処理アプリケーションメインフォーム
''' </summary>
Public Partial Class MainForm
    Inherits Form

    ''' <summary>
    ''' 定期的な表示更新処理
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub timerUpdateUI_Tick(sender As Object, e As EventArgs)
        '#Region "デジタル入出力関連."
        If True Then
            Dim dio As FVIL.Parser.IAuxDio = DirectCast(Defs.ParserInfo, FVIL.Parser.IAuxDio)
            Dim dio_enable As Boolean = (dio.Threads.Length > 0 AndAlso dio.Threads(0) IsNot Nothing)
            toolDioMonitor.Enabled = (dio_enable AndAlso DioMonitorForm Is Nothing)
        End If
        '#End Region
    End Sub

    ''' <summary>
    ''' デジタル入出力モニタの表示
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub toolDioMonitor_Click(sender As Object, e As EventArgs)
        Dim dio As FVIL.Parser.IAuxDio = DirectCast(Defs.ParserInfo, FVIL.Parser.IAuxDio)
        If dio.Threads.Length = 0 Then
            Return
        End If
        If dio.Threads(0) Is Nothing Then
            Return
        End If

        Try
            Dim thread As FVIL.IO.DioThread = dio.Threads(0)
            DioMonitorForm = thread.CreateTestDialog()
            AddHandler DioMonitorForm.FormClosed, AddressOf DioMonitorForm_FormClosed
            DioMonitorForm.Show()
        Catch ex As System.Exception
            MessageBox.Show(Me, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.[Error])
        End Try
    End Sub

    ''' <summary>
    ''' デジタル入出力モニタ
    ''' </summary>
    Private DioMonitorForm As Form = Nothing

    ''' <summary>
    ''' デジタル入出力モニタが閉じたとき
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub DioMonitorForm_FormClosed(sender As Object, e As EventArgs)
        DioMonitorForm = Nothing
    End Sub
End Class

[↑戻る]


4-4. MainForm (シリアル通信)

下記のソースコードには、シリアル通信ポートに関連する処理のみ抜粋しています。
シリアル通信ポートを操作するには
ParserInfoIAuxSerialPort にキャストして Ports プロパティから System.IO.Ports.SerialPort を抽出します。 この例では処理の簡略化の為、配列の 0 番目の要素からのみ抽出しています。

toolSerialPort_Click では、シリアル通信プロパティフォームをポップアップ表示しています。 これはツールストリップボタンのイベントに関連づけられたハンドラです。

timerUpdateUI_Tick では、ツールストリップボタンの有効/無効やチェックの ON/OFF を行っています。

C# Copy imageCopy
namespace SampleCode
{
    public partial class MainForm : Form
    {
        /// <summary>
        /// 定期的な表示更新処理.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void timerUpdateUI_Tick(object sender, EventArgs e)
        {
            #region シリアル通信関連.
            {
                FVIL.Parser.IAuxSerialPort com = (FVIL.Parser.IAuxSerialPort)Defs.ParserInfo;
                bool com_enable = (com.Ports.Length > 0 && com.Ports[0] != null);
                toolSerialPort.Enabled = (com_enable && SerialPortForm == null);
            }
            #endregion
        }

        /// <summary>
        /// シリアル通信フォームの表示.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void toolSerialPort_Click(object sender, EventArgs e)
        {
            FVIL.Parser.IAuxSerialPort com = (FVIL.Parser.IAuxSerialPort)Defs.ParserInfo;
            if (com == null) return;
            if (com.Ports.Length == 0) return;
            if (com.Ports[0] == null) return;

            try
            {
                System.IO.Ports.SerialPort port = com.Ports[0];
                SerialPortForm = FVIL.Ports.SerialPortTool.CreatePropertyDialog(port);
                SerialPortForm.FormClosed += SerialPortForm_FormClosed;
                SerialPortForm.Show();
            }
            catch (System.Exception ex)
            {
                MessageBox.Show(this, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// シリアル通信フォーム.
        /// </summary>
        private Form SerialPortForm = null;

        /// <summary>
        /// シリアル通信フォームが閉じたとき.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SerialPortForm_FormClosed(object sender, EventArgs e)
        {
            SerialPortForm = null;
        }
    }
}


Visual Basic Copy imageCopy
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Data
Imports System.Drawing
Imports System.Text
Imports System.Windows.Forms

''' <summary>
''' 画像処理アプリケーションメインフォーム
''' </summary>
Public Partial Class MainForm
    Inherits Form

    ''' <summary>
    ''' 定期的な表示更新処理
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub timerUpdateUI_Tick(sender As Object, e As EventArgs)
        '#Region "シリアル通信関連."
        If True Then
            Dim com As FVIL.Parser.IAuxSerialPort = DirectCast(Defs.ParserInfo, FVIL.Parser.IAuxSerialPort)
            Dim com_enable As Boolean = (com.Ports.Length > 0 AndAlso com.Ports(0) IsNot Nothing)
            toolSerialPort.Enabled = (com_enable AndAlso SerialPortForm Is Nothing)
        End If
        '#End Region
    End Sub

    ''' <summary>
    ''' シリアル通信フォームの表示
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub toolSerialPort_Click(sender As Object, e As EventArgs)
        Dim com As FVIL.Parser.IAuxSerialPort = DirectCast(Defs.ParserInfo, FVIL.Parser.IAuxSerialPort)
        If com Is Nothing Then
            Return
        End If
        If com.Ports.Length = 0 Then
            Return
        End If
        If com.Ports(0) Is Nothing Then
            Return
        End If

        Try
            Dim port As System.IO.Ports.SerialPort = com.Ports(0)
            SerialPortForm = FVIL.Ports.SerialPortTool.CreatePropertyDialog(port)
            AddHandler SerialPortForm.FormClosed, AddressOf SerialPortForm_FormClosed
            SerialPortForm.Show()
        Catch ex As System.Exception
            MessageBox.Show(Me, ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.[Error])
        End Try
    End Sub

    ''' <summary>
    ''' シリアル通信フォーム
    ''' </summary>
    Private SerialPortForm As Form = Nothing

    ''' <summary>
    ''' シリアル通信フォームが閉じたとき
    ''' </summary>
    ''' <param name="sender"></param>
    ''' <param name="e"></param>
    Private Sub SerialPortForm_FormClosed(sender As Object, e As EventArgs)
        SerialPortForm = Nothing
    End Sub
End Class

[↑戻る]


E. スクリーンショット

図 1 が今回作成したメインフォームです。
ツールストリップの左側にある緑の三角ボタンや四角ボタンで画像処理スレッドの開始/停止/中断を行います。
その他のボタンは接続しているデバイスの操作を行うものです。 ツールストリップボタンを押すと 図 2,3,4 に示すフォームをポップアップ表示します。 これらのフォームは本ライブラリに組み込まれたものです。


図1) メインフォーム:


図2) 焦点調整フォーム:


図3) デジタル入出力テストフォーム:


図4) シリアル通信プロパティフォーム:

[↑戻る]