入門の手引き 第 5 章 前の章 次の章

VB C# ALL プログラミング言語によるフィルタ (ここで選んだ言語で選別された説明や図だけが表示されます)

5. 新規アプリ開発支援 (2)

この章では、前章で作成してきた画面アプリの肉付けを行います。これまでの作業によって、アプリ操作者が実際に操作することのできる程度の画面アプリになってきましたが、 このままでは何の業務も果たしません。そこで、業務仕様を反映したビジネスロジックを記述して、意味のある動作を行うプログラムにしていきます。

5.1 フッククラスの新規作成

5.2 入力値のチェック (Check)

5.3 チェック結果の応答表示 (Response)

5.4 他項目からの派生値表示 (Derived)

5.5 初期値の設定 (InitVal)

5.6 画面フックメソッド


5.1 フッククラスの新規作成

ここでは、新たに項目フッククラス (項目部品) を作成し、プロジェクト Rensyuu1 に追加します。 なお、サンプル画面アプリ Rensyuu3 は、これから作ろうとするものの完成形ですから、分からなくなったら、Rensyuu3 をご参照ください。 ソリューション名およびプロジェクト名が Rensyuu1 ではなく Rensyuu3 となっている点が異なるだけで、他は全く同じです。

◇ フックメソッドとは

MANDALA.net を使用してアプリケーションを開発する際、ビジネスロジックは、フックメソッドという形態のメソッドとして記述します。フックメソッドは、それを実行させることが必要になったときに、MANDALA.net 実動フレームワークから呼び出されます。

たとえば、ある項目に対するインプット値が確定した際には、その値が正しいかどうかをチェックすることが必要になるものです。 この場合、Check というフックメソッドを記述しておけば (そしてコード合成をすれば)、入力操作がなされインプット値が確定した際にその Check フックメソッドが呼び出されるようになります。

なお、インプット値が確定した際と一言で述べましたが、様々なタイミングがあります。 入力操作の後に Enter キーを押下した場合もあれば、他の項目をクリックした場合もありますし、また更新のようなボタンをクリックした場合などもあります。いずれの場合にもインプット値のチェックが必要です。 MANDALA.net 実動フレームワークは、このような操作をすべて検出し、必要な場合だけフックメソッドを呼び出します。

この節では、プロジェクト Rensyuu1 にフッククラスを作成して、そこにフックメソッドを追加する作業を行います。 フックメソッドに関しては、この後に説明がありますが、詳細はマニュアル 「MANDALA.net 基本仕様」 のフックメソッドの説明、およびマニュアル 「MANDALA.net フック一覧」 をご参照ください。

◇ 項目フッククラスおよび画面フッククラス

フックメソッドは、項目フッククラス (項目部品) または画面フッククラス (画面部品) の中に MANDALA.net の規約に合わせ、プログラミング言語 Visual Basic Visual C# の文法に従って記述します。

項目フッククラスは、原則として各項目ごとに一つのクラスにします。項目フッククラスのクラス名およびファイル名としては、項目略称を用います。たとえば、項目略称が CdBangou のフッククラスの名前は CdBangou とし、クラスモジュールのファイル名は CdBangou.vb (VB の場合) CdBangou.cs (C# の場合) とします。そして、項目フッククラスの中には、その項目に関する項目フックメソッドを記述します。

同様に、画面フッククラスは、各画面ごとに一つのクラスにします。画面フッククラスのクラス名およびファイル名としては、画面略称を用います。 たとえば、Rensyuu1 アプリケーションの場合、そのフッククラスの名前は Rensyuu とし、クラスモジュールのファイル名は Rensyuu.vb (VB の場合) Rensyuu.cs (C# の場合) とします。そして、画面フッククラスの中には、その画面に関する画面フックメソッドを記述します。

このように、フッククラスのクラス名は、項目略称または画面略称とし、クラスモジュールのファイル名は、クラス名に .vb (VB の場合) .cs (C# の場合) を連ねた名前にします。 なお、クラス名として This を用いることは禁止されています。

◇ フッククラスの作成

ここでは、項目フッククラス CdBangou を新たに作成してみます。 なお、以下の操作方法は、項目フッククラスの場合も画面フッククラスの場合も同じです。

CdBangou.vb (VB の場合) CdBangou.cs (C# の場合) という名前のクラスモジュールをプロジェクトに追加するには、メニュー操作 [プロジェクト(P)] - [クラスの追加(C)...] を行います。すると、ダイアログボックス 新しい項目の追加 が登場するので、下図のようにファイル名を指定し、ボタン追加(A)をクリックします。


(クリックすると原寸大の図が登場します)

これでプロジェクトに新たなフッククラスを追加できました。 VS2008 の編集ペインに CdBangou.vb (VB の場合) CdBangou.cs (C# の場合) の内容が表示されて、プログラムコードが編集可能になっているはずです。この後の作業として、この中にメソッドの記述をしていきます。


5.2 入力値のチェック (Check)

◇ 項目フックメソッド Check の追加

クラス (フッククラス) を追加した直後は、次のようにクラスの宣言だけが記述されています。 この 2 行の間にフックメソッドを追加していきます。

' VB 版「CD 番号」項目フッククラス
Public Class CdBangou

End Class
// C# 版「CD 番号」項目フッククラス
public class CdBangou {

}

最初に Check という名前のフックメソッドを追加してみましょう。 下記の太文字のプログラムコードを VS2008 のエディタに向かってキーボードからインプットするか、 またはコピーアンドペースト機能を用いてクラス宣言の 2 行の間に挿入してください。

' VB 版「CD 番号」項目フッククラス
Public Class CdBangou

    Friend Function Check(ByVal CdBangou As String) As Integer
        If CdBangou.Length = 0 Then
            Return 1 ' エラーコードとして 1 を返す
        ElseIf CdBangou.Length = 1 AndAlso CdBangou >= "A" AndAlso CdBangou <= "C" Then
            Return ItemBase.CHECK_OK ' チェック OK を示す 0 を返す
        ElseIf CdBangou.StartsWith("AT-") Then
            Return ItemBase.CHECK_OK ' チェック OK を示す 0 を返す
        Else
            Return 2 ' エラーコードとして 2 を返す
        End If
    End Function ' Check

End Class ' CdBangou
// C# 版「CD 番号」項目フッククラス
public class CdBangou {

    internal int Check(string CdBangou)
        if( CdBangou.Length == 0 ) {
            return 1; // エラーコードとして 1 を返す
        }
        else if( CdBangou.Length == 1 && CdBangou >= "A" && CdBangou <= "C" ) {
            return ItemBase.CHECK_OK; // チェック OK を示す 0 を返す
        }
        else if( CdBangou.StartsWith("AT-") ) {
            return ItemBase.CHECK_OK; // チェック OK を示す 0 を返す
        }
        else
            return 2; // エラーコードとして 2 を返す
        }
    } // Check

} // CdBangou

太文字の最初の行は、メソッド宣言です。 ここでは Check という名前の、戻り値が Integer 型のファンクションを宣言しています。 括弧の中にはこのメソッドのパラメタとして項目 CdBangou が宣言してあります。 このメソッドが呼び出されるとき、この項目にはインプット値が引き渡されます。 なお、この処理は MANDALA.net 実動フレームワークによって行われます。

太文字の 2 行目の If (VB の場合) if (C# の場合) ステートメントでは、String クラスの Length プロパティを調べることで、渡された CdBangou の文字列の長さを判定しています。 そして、長さがゼロであれば、入力エラーであることを示すために 1 という値を持って戻るように Return (VB の場合) return (C# の場合) ステートメントが記述してあります。

一般的な説明になりますが、Check フックメソッドでは、項目に正しい値が入力されていない場合、つまり入力エラーの場合には ItemBase.CHECK_OK (= ゼロ) 以外の値を返すことになっています。そして、入力エラーがない場合には ItemBase.CHECK_OK (= ゼロ) を返す決まりになっています。

なお、この戻り値は MANDALA.net 実動フレームワークに渡されて、エラーの有無に従って以下に述べるそれぞれの処理がなされます。 Check フックメソッドからゼロ (ItemBase.CHECK_OK) が返された場合、MANDALA.net 実動フレームワークはこの項目の状態を 「入力完了」 と設定し、次の入力項目にフォーカスを移動します。 ゼロ以外の値が返された場合、フォーカスを移動せずに、この項目を 「エラー」 状態にして、項目の文字 (または背景) を赤色に変えます。

太文字の 4 行目の ElseIf (VB の場合) else if (C# の場合) ステートメントでは、CdBangou へのインプット値が "A" か "B" か "C" であるかどうか調べています。 そうであれば、項目に正しい値が入力されたことを示す ItemBase.CHECK_OK (= 0) という値を持って戻ります。

太文字の 6 行目の ElseIf (VB の場合) else if (C# の場合) ステートメントでは、CdBangou へのインプット値が "AT-" で始まるかどうか調べています。 そうであれば、項目に正しい値が入力されたことを示す ItemBase.CHECK_OK (= 0) という値を持って戻ります。

これら以外の場合は、入力エラーであることを示す 2 という値を持って戻ります。

◇ 再生成の実施

上記のプログラムコードの編集を済ませたら、まず VS2008 に向かってメニュー操作 [ファイル(F)] - [すべて保存(L)] を行って、 上記の内容を保存します。そして保存の後に、機械生成を再度実施してください。 すなわち、スタートメニューから MANDALA.net コード合成ツールを起動し、プロジェクト Rensyuu1 を選択し、合成の指示を与えます。

この操作方法は 「4.3 コード合成の実施」 とほぼ同じですが、今回は総括表の内容をチェックする必要があることを知らせるダイアログボックスが登場しませんし、総括表の内容を変更する必要もありません (すでに設定済みなので)。

総括表が表示されたら、下図赤枠の部分に注目してください。ボディ部の H 欄の列に 1 という値が表示されているはずです。


(クリックすると原寸大の図が登場します)

これは、項目 CdBangou に対して一つのフックメソッドが記述されていることを示しています。 もしも、ここが 0 のままであれば、フックメソッドとみなされるメソッドを記述できていないことになります (もしも 0 と表示されていたら、フックメソッドの編集作業を見直してください)。

ここで、この 1 と表示されている H 欄の項目をクリックすると、次のダイアログが表示されます。

この情報により、CdBangou 項目に Check フックメソッドが記述されていることが分かります。

これで必要な確認が済んだので、このダイアログを閉じてから、メニュー操作 [操作(O)] - [コード合成(G)] を行ってください。 Check フックメソッドを呼び出す新版のプログラムコードが機械生成されます。

◇ 項目フックメソッド Check の動作テスト

生成が終わったら、プログラムの動作テストをしてみましょう。

CD 番号という項目にデータをインプットすると (インプット値が確定すると)、Check フックメソッドが呼び出されます。これは、Check フックメソッドの中にブレークポイントを設定することで確認できます。

あるいは、以下の操作とその結果からも確認できます。たとえば "123456789" のように 1 文字目が数字の文字列をインプットすると、項目の文字色が赤になり、フォーカスは次の項目に移動しません。 また、1 文字もインプットせずに空の Enter キーを押下した場合もエラーになり、フォーカスの移動はなされません。 このように Check フックメソッドを組み込まなかった以前の動作と明らかに違っています。

なお、Check フックメソッドに関する仕様は、フック一覧Check 項目フックメソッドの説明をご参照ください。 ちなみに、Check フックメソッドは単項目のチェックを行うものであり、複数の項目間の関係をチェックするには、別のフックメソッド RelCheck をお使いください。


5.3 チェック結果の応答表示 (Response)

ここまでの作業によって、すなわち Check フックメソッドを組み込むことで、入力エラーかどうかは分かるようになりましたが、何が悪くてエラーになったのかはアプリ操作者に通知できていません。 できれば、インプット値のエラーの原因をアプリ操作者に通知したいものです。

◇ 項目フックメソッド Response の追加

ここでは、インプットへの応答メッセージを表示するためのフックメソッド Response を追加することにします。太文字部分が今回追加するフックメソッドです。

' VB 版「CD 番号」項目フッククラス
Public Class CdBangou

    Friend Function Check(ByVal CdBangou As String) As Integer
        If CdBangou.Length = 0 Then
            Return 1 ' エラーコードとして 1 を返す
        ElseIf CdBangou.Length = 1 AndAlso CdBangou >= "A" AndAlso CdBangou <= "C" Then
            Return ItemBase.CHECK_OK ' チェック OK を示す 0 を返す
        ElseIf CdBangou.StartsWith("AT-") Then
            Return ItemBase.CHECK_OK ' チェック OK を示す 0 を返す
        Else
            Return 2 ' エラーコードとして 2 を返す
        End If
    End Function ' Check

    Friend Function Response(ByVal fB As FormBase, ByVal Cd_Error As Integer) As Boolean
        If Cd_Error <> ItemBase.CHECK_OK Then ' <> 0
            Select Case Cd_Error
                Case 1
                    fB.StatusOut("CD 番号は必ず入力してください。", Color.Red)
                Case 2
                    fB.StatusOut("CD 番号は AT- で始まる文字列か、A, B または C です。", Color.Red)
            End Select
        End If
    End Function ' Response

End Class ' CdBangou
// C# 版「CD 番号」項目フッククラス
public class CdBangou

    internal int Check( string CdBangou ) {
        if( CdBangou.Length == 0 ) {
            return 1; // エラーコードとして 1 を返す
        }
        else if( CdBangou.Length == 1 && CdBangou >= "A" && CdBangou <= "C" ) {
            return ItemBase.CHECK_OK; // チェック OK を示す 0 を返す
        }
        else if( CdBangou.StartsWith("AT-") ) {
            return ItemBase.CHECK_OK; // チェック OK を示す 0 を返す
        }
        else
            return 2; // エラーコードとして 2 を返す
        }
    } // Check        If CdBangou.Length = 0 Then

    internal bool Response( FormBase fB, int Cd_Error ) {
        if( Cd_Error != ItemBase.CHECK_OK ) { // != 0
            switch( Cd_Error ) {
                case 1:
                    fB.StatusOut("CD 番号は必ず入力してください。", Color.Red);
                    break;
                case 2:
                    fB.StatusOut("CD 番号は AT- で始まる文字列か、A, B または C です。", Color.Red);
                    break;
            }
        }
    } // Response

} // CdBangou

このフックメソッド ResponseCheck フックメソッドの処理が終わった後に呼び出されます。

ちなみに、CheckResponse が別のフックメソッドになっている理由は、通常 Check はセントラル側で (データベースを参照するなどして) 動作し、Response はアプリ操作者のいるローカル側で動作するものだからです。

太文字の最初の行の括弧の中の第 2 パラメタに注目してください。Cd_Error というパラメタが宣言されています。このパラメタには Check フックメソッドの戻り値が設定されてきます。したがって、このパラメタの内容によってアプリ操作者に適切な応答表示をすることができます。

ここでは、Cd_Error の内容が 1 または 2 であった場合それぞれにふさわしいメッセージを表示するようにしています。

ちなみに、第 1 パラメタとして宣言されている fB の型は FormBase となっています。これは、MANDALA.net 実動フレームワークの主要なクラスであり、画面に対応するものです。 ここでは、5 行目および 7 行目の fB.StatusOut というメソッドを呼び出す際に、そのオブジェクト (インスタンス) が必要になるので fB という FormBase クラスのパラメタが宣言されています。

MANDALA.net のフックメソッドでは、このように必要な項目やオブジェクトをパラメタとして宣言することにより、それを実動フレームワークから受け取ることができるようになっています。

FormBaseStatusOut というメソッドは、パラメタに文字列と表示色を与えることにより、画面上のステータス表示域にメッセージを表示するものです。 StatusOut についての仕様は、メンバ一覧の中のメソッド StatusOut の説明をご参照ください。

◇ 再生成の実施と項目フックメソッド Response の動作テスト

上記のプログラムコードの編集が済んだら、まず VS2008 に向かってメニュー操作 [ファイル(F)] - [すべて保存(L)] を行って、上記の内容を保存します。 そして保存の後に、機械生成を再度実施してください。 すなわち、スタートメニューから MANDALA.net コード合成ツールを起動し、プロジェクト Rensyuu1 を選択し、合成の指示を与えます。

機械生成が終わったら、動作テストをしてみましょう。 CD 番号という欄で Enter キーをカラ打ちすると、下図のようにエラーメッセージが表示されます。

また、CD 番号という欄に "123456789" のように 1 文字目が数字の文字列をインプットすると、下図のようにエラーメッセージが表示されます。

なお、Response フックメソッドに関する仕様は、フック一覧Response 項目フックメソッドの説明をご参照ください。


5.4 他項目からの派生値表示 (Derived)

ある項目へのインプットがなされた際に、そのインプット値から何らかの値を求めて他の項目に表示するという処理は、しばしば必要になるものです。 たとえば商品コードがインプットされた際に、その商品名称商品単価を表示するような場合です。 こうした処理は派生と呼ばれており、Derived フックメソッドによって処理します。 すなわち、派生元項目 (たとえば商品コード) へのインプット値を基にして、その値から派生する何らかの値 (派生値) を求めて派生先項目 (たとえば商品名称) に設定するという統一的な方法を用います。

Derived フックメソッドは、派生先項目のフッククラスの中に記述します。上記の例では、商品名称商品単価のフッククラスの中に Derived フックメソッドを記述することになります。そして、Derived フックメソッドのパラメタとして、派生元項目 (上の例では商品コード) を宣言します。

こうした Derived フックメソッドの記述方法は、最初は奇異に感じられるかもしれませんが、派生値を求めるための関数型メソッド だと捉えれば、素直な記述方法だとご納得いただけるかもしれません。たとえば、商品コードをパラメタとして、商品名称という派生値を求めるための関数をプログラミングするのだ、とみなすのです。 多分、この関数の中では商品コードをキーにしてデータベースを検索して商品名称を求めることでしょう。 一般に派生値を求めるためには、データベースなどの検索を必要とするかもしれませんし、計算や演算を必要とするかもしれませんが、 いずれにしても派生値 (つまり関数の値) を求めることに変わりはありません。

なお、このような記述方法を採用している理由は、各フッククラスの再利用性を高めるためです。 上記の例で、もしも逆に商品コードのフッククラスの中に商品名称および商品単価に値を設定するプログラムを記述することにすると、 そのフッククラスは商品名称および商品単価を含む画面にしか使えないものになり、再利用性が低くなってしまいます。

◇ フッククラスの作成と項目フックメソッド Derived の追加

ここでは、呼び名という項目の値を求める Derived フックメソッド、および曲数という項目の値を求める Derived フックメソッドの二つを作成することにします。

これらの Derived フックメソッドを記述するためには、それぞれ Yobina および Kyokusuu という名前のクラスを必要とします。そこで、これらのクラスを新たに作成してプロジェクトに追加してください。 この操作方法は 「5.1 フッククラスの新規作成」 と同様です。

二つの新たなクラスが作成できたら、それぞれに下記の太文字のプログラムコードを挿入してください。

呼び名の値を求める Derived フックメソッド:

' VB 版「呼び名」用項目フッククラス
Public Class Yobina

    Friend Function Derived(ByVal CdBangou As String) As String
        Select Case CdBangou
            Case "A"
                Return "アルバム民謡全集"
            Case "B"
                Return "ベストポップス選"
            Case "C"
                Return "クラシック名曲集"
            Case Else
                If CdBangou.StartsWith("AT-") Then
                    Return "特選特製版" + CdBangou.SubString(3)
                Else
                    Return String.Empty ' = ""
                End If
        End Select
    End Function ' Derived

End Class ' Yobina
// C# 版「呼び名」項目フッククラス
public class Yobina {

    internal string Derived( string CdBangou ) {
        switch( CdBangou ) {
            case "A":
                return "アルバム民謡全集";
            case "B":
                return "ベストポップス選";
            case "C":
                return "クラシック名曲集";
            default:
                if( CdBangou.StartsWith("AT-") ) {
                    return "特選特製版" + CdBangou.SubString(3);
                }
                else {
                    return string.Empty; // = ""
                }
        }
    } // Derived

} // Yobina

呼び名 (Yobina) という項目の値を求める Derived フックメソッドは、CdBangou がパラメタになっています。
 通常は、CdBangou をキーにしてデータベースを検索して Yobina を求めることでしょうが、ここではプログラムを簡単にするために Yobina の値を文字列定数などから求めるようになっています。
 プログラムを読めばお分かりのとおり、Yobina の値は、パラメタの CdBangou が "A" ならば "アルバム民謡全集"、"B" ならば "ベストポップス選"、"C" ならば "クラシック名曲集" となります。 それから、パラメタ CdBangou が "AT-" で始まる文字列ならば、Yobina の値は "特選特製版" で始まる文字列になります。
 このようにプログラミングしてあるので、CD 番号へのインプット値が確定すると、それに対応する上述の呼び名が表示されることになります。

曲数の値を求める Derived フックメソッド:

' VB 版「曲数」項目フッククラス
Public Class Kyokusuu

    Friend Function Derived(ByVal fB As FormBase, ByVal KyokuMei As String) As Decimal
        Return fB.LastDe
    End Function ' Derived

End Class ' Kyokusuu
// C# 版「曲数」項目フッククラス
public class Kyokusuu {

    internal decimal Derived( FormBase fB, string KyokuMei ) {
        return fB.LastDe;
    } // Derived

} // Kyokusuu

曲数 (Kyokusuu) という項目の値を求める Derived フックメソッドは、fB および KyokuMei がパラメタになっています。
 この Function 中では、パラメタの KyokuMei が参照されていませんが、このパラメタは必要です。なぜなら、この KyokuMei という項目へのインプット値が確定した際にこの Derived フックメソッドを呼び出すようにせよ、との指示を意味するものだからです。

一般に Derived フックメソッドは、そのパラメタとして宣言されている項目へのインプット値が確定した際に呼び出されます。
 なお、この例の場合、パラメタとして宣言された項目は一つだけですが、複数の項目をパラメタとして宣言することもできます。 そうした場合には、パラメタとして宣言されたどの項目についても、その項目へのインプット値が確定した際には Derived フックメソッドが呼び出されます。
 ただし、Kyokusuu という項目の Derived フックメソッドのパラメタとして同じ Kyokusuu を宣言したような場合は、 その Kyokusuu という項目へのインプットがなされても Derived フックメソッドは呼び出されません。

このフックメソッドの戻り値となっている FormBase クラスの LastDe プロパティは、ボディ部の何行目までインプットがなされているのかを示す整数値を意味します。 そして、これが項目 Kyokusuu に設定されます。
 すなわち、ボディ部の項目曲名へのインプット値が確定すると、テール部の項目曲数にボディ部の行数、つまり曲名の数が表示されることになります。

より正確にするには:

ちなみに、より正確にするには、下記の太文字のプログラムにすべきです。すなわち、ボディ部の明細の途中に空欄があれば、それは曲数に含めるべきではないからです。 しかし、ボディ部の明細の途中に空欄があれば、この画面データを登録しようとする際に画面データ完備チェックではじかれますから、元の「fB.LastDe を返す」という仕様のままでも大きな問題にはなりません。

' VB 版「曲数」項目フッククラス
Public Class Kyokusuu

    Friend Function Derived(ByVal fB As FormBase, ByVal KyokuMei As String) As Decimal
        ' 置換 Return fB.LastDe
        Dim 曲数 As Integer = 0
        Dim 明細行インデックス As Integer = 0
        While 明細行インデックス < fB.LastDe
            If fB.getValue(ii_KyokuMei, 明細行インデックス) <> String.Empty Then
                曲数 += 1 ' カウントアップ
            End If
            '
            明細行インデックス += 1 ' カウントアップ
        End While
        Return 曲数
    End Function ' Derived

End Class ' Kyokusuu
// C# 版「曲数」項目フッククラス
public class Kyokusuu {

    internal decimal Derived( FormBase fB, string KyokuMei ) {
        // 置換 return fB.LastDe;
        int 曲数 = 0;
        int 明細行インデックス = 0;
        while( 明細行インデックス < fB.LastDe ) {
            if( fB.getValue(Rensyuu1FormBase.ii_KyokuMei, 明細行インデックス) != string.Empty ) {
                曲数 += 1; // カウントアップ
            }
            //
            明細行インデックス += 1; // カウントアップ
        }
        return 曲数;
    } // Derived
} // Kyokusuu

◇ 再生成の実施と項目フックメソッド Derived の動作テスト

上記のプログラムコードの編集が済んだら、まず VS2008 に向かってメニュー操作 [ファイル(F)] - [すべて保存(V)] を行って、上記の内容を保存します。 そして保存の後に、機械生成を再度実施してください。 すなわち、スタートメニューから MANDALA.net コード合成ツールを起動し、プロジェクト Rensyuu1 を選択し、合成の指示を与えます。

機械生成が終わったら、動作テストをしてみましょう。CD 番号という欄に A とインプットして Enter キーを押下すると、下図のようにアルバム民謡全集と表示されます。

次に、上矢印キーを押下してフォーカスを CD 番号欄に戻し、B とインプットして Enter キーを押下すると、下図のようにベストポップス選と表示されます。

さらに動作テストを続けましょう。上矢印キーを押下してフォーカスを CD 番号欄に戻し、AT-000001 とインプットして、続けて適当な曲名をインプットしていくと、下図のようになります。 曲名を一つインプットする度に、曲数が増えていくことをご確認ください。

なお、Derived フックメソッドに関する仕様は、フック一覧Derived 項目フックメソッドの説明をご参照ください。


5.5 初期値の設定 (InitVal)

入力項目にあらかじめ初期値を表示しておくことによって、アプリ操作者の負荷を軽減できる場合があります。 その初期値のままでよければインプット操作を行わずに済ませることができるからです。 こうした負荷の軽減は、InitVal フックメソッドによって初期値の設定をすることで実現できます。 なお、この初期値の設定は、TextBox の Text プロパティへの初期値の設定 (表示例の設定) とは違った意味をもっています。 どのように違うのか、以下をご覧ください。

◇ 項目フックメソッド InitVal の追加

ここでは、CD 番号という項目に初期値を設定することにします。 したがって、フッククラス CdBangou の中に InitVal フックメソッドのプログラムコードを追加します。太文字部分が今回追加するコードです。

' VB 版「CD 番号」項目フッククラス
Public Class CdBangou

    Friend Function Check(ByVal CdBangou As String) As Integer
        If CdBangou.Length = 0 Then
            Return 1 ' エラーコードとして 1 を返す
        ElseIf CdBangou.Length = 1 AndAlso CdBangou <= "A" AndAlso CdBangou >= "C" Then
            Return ItemBase.CHECK_OK ' チェック OK を示す 0 を返す
        ElseIf CdBangou.StartsWith("AT-") Then
            Return ItemBase.CHECK_OK ' チェック OK を示す 0 を返す
        Else
            Return 2 ' エラーコードとして 2 を返す
        End If
    End Function ' Check

    Friend Function Response(ByVal fB As FormBase, ByVal Cd_Error As Integer) As Boolean
        If Cd_Error <> ItemBase.CHECK_OK Then ' <> 0
            Select Case Cd_Error
                Case 1
                    fB.StatusOut("CD 番号は必ず入力してください。", Color.Red)
                Case 2
                    fB.StatusOut("CD 番号は AT- で始まる文字列か、A, B または C です。", Color.Red)
            End Select
        End If
    End Function ' Response

    Friend Function InitVal() As String
        Return "AT-000001"
    End Function ' InitVal

End Class ' CdBangou
// C# 版「CD 番号」項目フッククラス
public class CdBangou

    internal int Check( string CdBangou ) {
        if( CdBangou.Length == 0 ) {
            return 1; // エラーコードとして 1 を返す
        }
        else if( CdBangou.Length == 1 && CdBangou >= "A" && CdBangou <= "C" ) {
            return ItemBase.CHECK_OK; // チェック OK を示す 0 を返す
        }
        else if( CdBangou.StartsWith("AT-") ) {
            return ItemBase.CHECK_OK; // チェック OK を示す 0 を返す
        }
        else
            return 2; // エラーコードとして 2 を返す
        }
    } // Check

    internal bool Response( FormBase fB, int Cd_Error ) {
        if( Cd_Error != ItemBase.CHECK_OK ) { // != 0
            switch( Cd_Error ) {
                case 1:
                    fB.StatusOut("CD 番号は必ず入力してください。", Color.Red);
                    break;
                case 2:
                    fB.StatusOut("CD 番号は AT- で始まる文字列か、A, B または C です。", Color.Red);
                    break;
            }
        }
    } // Response

    internal string InitVal( ) {
        return "AT-000001";
    } // InitVal

} // CdBangou

InitVal フックメソッドの中では "AT-000001" という文字列を戻り値としていますが、 この文字列が CD 番号という項目の初期値になります。

◇ 再生成の実施と項目フックメソッド InitVal の動作テスト

上記のプログラムコードの編集が済んだら、まず VS2008 に向かってメニュー操作 [ファイル(F)] - [すべて保存(V)] を行って、上記の内容を保存します。 そして保存の後に、機械生成を再度実施してください。 すなわち、スタートメニューから MANDALA.net コード合成ツールを起動し、プロジェクト Rensyuu1 を選択し、合成の指示を与えます。

機械生成が終わったら、プログラムの実行を開始してみましょう。InitVal フックメソッドが正しく追加できていれば、下図のように表示されます。

ここで、CD 番号の欄に "AT-123456" とインプットします。 そして、ボディ部の 1 行目の項目曲名に適当な文字列をインプットして、2 行目には何もインプットせずに Enter キーを押下してください。 すると下図のダイアログボックスが表示されます。

ここでは、ボタン OK をクリックします。こうすると、通常この画面データはデータベースに書き出されて、次のデータを受け付けるために画面が初期化されます。 すなわち、このときに InitVal フックメソッドが呼び出されます。この結果、表示は下図のようになります。

ここで補足説明ですが 「通常この画面データはデータベースに書き出される」 と述べたのは、あくまでも通常の場合のことであって、Rensyuu1 には当てはまりません。 なぜなら、画面データをデータベースに追加するための画面フックメソッド AppendRensyuu1 にはまだ組み込まれていないからです。

以前には、CD 番号欄に "AT-123456" と表示されていましたが、初期化されて "AT-000001" になっており、InitVal フックメソッドが動作したことが確認できます。

なお、InitVal フックメソッドに関する仕様は、フック一覧InitVal 項目フックメソッドの説明をご参照ください。

項目への値の設定:

上記の InitValDerived など限られた項目フックメソッドでは、その項目に限ってその値を変更することが許されています。 この種のもの以外の項目フックメソッドでは、項目への値の設定や変更をするプログラムを書かないようにお勧めいたします。 特に、ある項目のフッククラスの中で別の項目への値の設定や変更は、禁止するようにお勧めいたします。

このようにすれば、ある項目に値を設定するプログラムは、特定のものに限定されますから、メンテナンスしやすいプログラムにすることができます。 すなわち、とんでもないところで、項目の値が変更されるということがなくなります。


5.6 画面フックメソッド

ここでは、画面フックメソッドをいくつか作成してみます。これらは、実際に役立つ業務プログラムに仕立てるためのヒントとなることでしょう。

◇ フッククラスの作成と画面フックメソッドの追加

画面フックメソッドを記述するためには、画面フッククラス Rensyuu が必要です。そこで、クラスモジュールを新たに作成してプロジェクトに追加します。 この操作方法は 「5.1 フッククラスの新規作成」 と同様です。画面フッククラスの作成方法は、項目フッククラスの場合と何ら変わりありません。

ここでは、BeginPrg, Open, Append および Close という 4 つの画面フックメソッドを作成することにします。 したがって、画面フッククラス Rensyuu の中にこれら 4 つの画面フックメソッドのプログラムコード (太文字部分) を追加します。 これらのコードは、主にデバッグ用のログを表示するものです。

' VB 版画面フッククラス
Public Class Rensyuu

    ' プログラムの実行開始時の初期設定処理を行う。
    Friend Function BeginPrg(ByVal fB As FormBase) As Boolean
        Debug.WriteLine("(画面フックメソッド) Rensyuu_BeginPrg")
        '
        Return FormBase.BEGINPRG_Allow
    End Function ' BeginPrg

    ' CD 管理データベースをオープンする。
    Friend Function Open(ByVal fB As FormBase) As Boolean
        Debug.WriteLine("(画面フックメソッド) Rensyuu_Open")
        '
        Return FormBase.OPEN_Allow
    End Function ' Open

    ' CD 管理データベースに伝票 (カレント画面データ) の追加 (書出し) 処理を行う。
    Friend Function Append(ByVal fB As FormBase, ByVal CdBangou As String) As Integer
        Debug.WriteLine("(画面フックメソッド) Rensyuu_Append")
        '
        Debug.WriteLine(" 画面データ CdBangou: " + fB.getValue(ii_CdBangou))
        Debug.WriteLine(" 画面データ Yobina:  " + fB.getValue(ii_Yobina))
        Debug.WriteLine(" 画面データ Kyokusuu: " + fB.getValue(ii_Kyokusuu).toString())
        '
        Dim 明細行インデックス As Integer = 0
        While 明細行インデックス < fB.LastDe
            Debug.WriteLine(" 画面データ KyokuMei: " & fB.getValue(ii_KyokuMei, 明細行インデックス))
            '
            明細行インデックス += 1
        End While
        '
        Return FormBase.APPEND_Append
    End Function ' Append

    ' CD 管理データベースをクローズする。
    Friend Function Close(ByVal fB As FormBase) As Integer
        Debug.WriteLine("(画面フックメソッド) Rensyuu_Close")
        '
        Return FormBase.CLOSE_Allow
    End Function ' Close

End Class ' Rensyuu
// C# 版画面フッククラス
using System.Diagnostics;
using AppliTech.WorkFrame;
public class Rensyuu {

    // プログラムの実行開始時の初期設定処理を行う。
    internal bool BeginPrg( FormBase fB ) {
        Debug.WriteLine("(画面フックメソッド) Rensyuu_BeginPrg");
        return FormBase.BEGINPRG_Allow;
    }

    // CD 管理データベースをオープンする。
    internal bool Open( FormBase fB ) {
        Debug.WriteLine("(画面フックメソッド) Rensyuu_Open");
        return FormBase.OPEN_Allow;
    }

    // CD 管理データベースに伝票 (カレント画面データ) の追加 (書出し) 処理を行う。
    internal int Append( FormBase fB, string CdBangou ) {
        Debug.WriteLine("(画面フックメソッド) Rensyuu_Append");
        Debug.WriteLine(" 画面データ CdBangou: " + fB.getValue(RensyuuFormBase.ii_CdBangou));
        Debug.WriteLine(" 画面データ Yobina:  " + fB.getValue(RensyuuFormBase.ii_Yobina));
        Debug.WriteLine(" 画面データ Kyokusuu: " + fB.getValue(RensyuuFormBase.ii_Kyokusuu).toString());
        int 明細行インデックス = 0;
        while( 明細行インデックス < fB.LastDe ) {
            Debug.WriteLine(" 画面データ KyokuMei: " + fB.getValue(ii_KyokuMei, 明細行インデックス));
            明細行インデックス += 1;
        }
        return FormBase.APPEND_Append;
    }

    // CD 管理データベースをクローズする。
    int Close( FormBase fB ) {
        Debug.WriteLine("(画面フックメソッド) Rensyuu_Close");
        return FormBase.CLOSE_Allow;
    }

}

◇ 再生成の実施と画面フックメソッドの動作テスト

上記のプログラムコードの編集が済んだら、まず VS2008 に向かってメニュー操作 [ファイル(F)] - [すべて保存(L)] を行って、上記の内容を保存します。そして保存の後に、機械生成を再度実施してください。すなわち、スタートメニューから MANDALA.net コード合成ツールを起動し、プロジェクト Rensyuu1 を選択し、合成の指示を与えます。

BeginPrg, Open, Close の動作テスト:

機械生成が終わったら、Debug 構成にしてプログラムの実行を開始してみましょう。 すると、出力ウィンドウに下記のログが表示されます。なお、出力ウィンドウを表示するには、VS2008 に向かってメニュー操作 [表示(V)] - [その他のウィンドウ(H)] - [出力(O)] を行ってください。

(画面フックメソッド) Rensyuu_BeginPrg
(画面フックメソッド) Rensyuu_Open

このログは、画面フックメソッド BeginPrg および Open が呼び出されたことを示しています。 BeginPrg はプログラムの実行を開始して、画面の表示を行う前に 1 回だけ呼び出されます。 そして、Open は画面を初めて表示した直後に 1 回だけ呼び出されます。したがって、BeginPrg がまず初めに、次に画面表示がなされて、その後に Open という順序になります。
 初期設定処理の大半は、これらの画面フックメソッドで行うことができそうです。 どちらの画面フックメソッドで行う方がよいかは、以下のように考えて決めてください。 たとえば、ファイルやデータベースに関するオープン処理は時間がかかるものですから、そういう処理は何はともあれ画面を表示してから行うことをお勧めいたします。 さもないと、プログラムを起動してもなかなか画面が現れないことになり、アプリ操作者は不安に感じるからです。 したがって、ファイルやデータベースに関するオープン処理は、BeginPrg ではなく Open で行う方がよいと思われます。

ここでこのサンプル画面アプリの画面右上端の 印のボタン閉じるをクリックして、実行を終えてみましょう。すると、出力ウィンドウに下記の Close のログが追加表示されます。

(画面フックメソッド) Rensyuu_BeginPrg
(画面フックメソッド) Rensyuu_Open
(画面フックメソッド) Rensyuu_Close

画面フックメソッド Close が呼び出されたことがこのログから分かります。Close はプログラムの実行を終える直前に呼び出されるので、ここでは各種の後始末処理を行うことができます。 たとえば、ファイルやデータベースに関するクローズ処理は、Close で行えばよいでしょう。

Append の動作テスト:

再度、プログラムの実行を開始して、ボディ部の何行かの曲名欄に適当な文字列をインプットしてから、インプットを終える合図として曲名欄に何もインプットせずに Enter キーを押下してください。すると下図のダイアログボックスが表示されます。

ここでは、ボタン OK をクリックします。こうすると、この画面データをデータベースに書き出すために、Append フックメソッドが呼び出されます。この結果、ログの表示は下図のようになります。

(画面フックメソッド) Rensyuu_BeginPrg
(画面フックメソッド) Rensyuu_Open
(画面フックメソッド) Rensyuu_Append
 画面データ CdBangou: AT-000001
 画面データ Yobina:  特選特製版000001
 画面データ Kyokusuu: 3
 画面データ KyokuMei: 英雄
 画面データ KyokuMei: 運命
 画面データ KyokuMei: 田園

通常 Append の中では画面データをデータベースに追加するのですが、ここでは画面データをログに書き出しています。 このために上記のように画面データがログに表示されています。 そしてこの後、InitVal フックメソッドによって画面が初期化され、次のデータのインプットが受け付けられるようになります。 ですから、さらに同様のインプット操作を続ければ、次々と Append および画面データに関するログが追加されていくことでしょう。データをインプットしてお試しください。

Append フックメソッドのプログラムをご覧いただくと分かるように、Debug.WriteLine というメソッドを用いてそれぞれの情報をログに書いています。 この中では、画面データを取り出すために fB.getValue というメソッドが使われています。 そして、このメソッドのパラメタとして、ii_CdBangou のようにプレフィックス ii_項目略称を連ねた名前 (項目識別子) が使われています。なお、この項目識別子は、画面内の各項目を指し示す識別子であり、画面内の項目に関する各種メソッドのパラメタとして使われる定数 (ReadOnly 変数) です。

メソッド fB.getValue の戻り値の型は、項目識別子で示された項目の型に従って決まります。 項目 CdBangou, Yobina, KyokuMei は、総括表でそれぞれコード名称名称と指定してあるので、これらはすべて文字列型 (String) となります。 項目 Kyokusuu は、総括表で十進数と指定してあるので、十進数オブジェクト型 (AppliTech.WorkFrame.WrpDecimal) となります。 なお、十進数型 (Decimal) ではなく十進数オブジェクト型 (AppliTech.WorkFrame.WrpDecimal) となっているのは、空欄を Nothing 値で表現できるようにするためです。

ここでは、フックメソッド Append の中で画面データをログに書き出していますが、通常はデータベースに書き出すことが普通です。 こうすることで、実際に役立つ業務プログラムに仕立てることができます。

項目フックメソッドのログ:

上述のログを見ながら、このサンプル画面アプリの操作をすることによって、各画面フックメソッドがどのような場合に呼び出されるのかを体得することができます。 同様に各項目フックメソッドの中に、ログをするプログラムコードを追加すれば、各画面フックメソッドがどのような場合に呼び出されるのかを体得することができることでしょう。

ここで、実際にログをするプログラムコードを追加してみましょう。以下のプログラムコードをそれぞれの項目フックメソッドの Function 宣言の次に追加すればよいでしょう。

        Debug.WriteLine("(項目フックメソッド) CdBangou_Check")

        Debug.WriteLine("(項目フックメソッド) CdBangou_Response")

        Debug.WriteLine("(項目フックメソッド) Yobina_Derived")

        Debug.WriteLine("(項目フックメソッド) Kyokusuu_Derived")

        Debug.WriteLine("(項目フックメソッド) CdBangou_InitVal")
        Debug.WriteLine("(項目フックメソッド) CdBangou_Check");

        Debug.WriteLine("(項目フックメソッド) CdBangou_Response");

        Debug.WriteLine("(項目フックメソッド) Yobina_Derived");

        Debug.WriteLine("(項目フックメソッド) Kyokusuu_Derived");

        Debug.WriteLine("(項目フックメソッド) CdBangou_InitVal");


入門の手引き 第 5 章 前の章 次の章