Customer + .NET WinForm サンプルの CustomerWinForm.sln は、Dialog System の元の Customer サンプルを取得し、Orders ダイアログをより最新式の Windows Forms Orders フォームに置き換えます。メインの Customer アプリケーションはほとんど未変更のままであるため、アプリケーションはネイティブ コードのメイン プログラムになり、.NET コードを COM オブジェクトとして呼び出して Windows Forms Orders フォームを処理します。
次の図の左側には、ネイティブ コードと、スクリーンセットを処理する Dialog System があります。.NET COBOL コードは、新しい Windows Forms フォームとともに右側にあります。この図は、.NET COBOL コードを含んだ COM 呼び出し可能ラッパー (COM Callable Wrapper; CCW) のインターフェイスとなるネイティブ コード、および渡されて返されるデータ ブロックも示しています。
上図の数字は、プロセス内の重要なポイントを示しています。次では、これらの重要なポイントについて説明します。
データ ブロックのコピーは、使用する .NET クラス用に作成されます。
ソリューションには、ネイティブ プロジェクトと .NET COBOL プロジェクトという 2 つのプロジェクトがあります。ネイティブ プロジェクトの Customer には、元のソースのほかに、別の方法で Orders ダイアログを処理するための変更、および .NET COBOL コード プロジェクトと対話するための変更が含まれています。
Customer ネイティブ プロジェクトの内容は次のとおりです。
ネイティブ プロジェクトをデバッグするには、Customer プロジェクトがスタートアップ プロジェクトとして設定されていることを確認します。これを行うには、プロジェクトを右クリックして [Set as StartUp Project] をクリックします。
.NET COBOL プロジェクトの OrderFormsLibrary には、新しい Windows Forms Orders フォームが含まれています。また、.NET COBOL コードとネイティブ コード間で顧客データ ブロックを渡すためのサポート コードも含まれています。このマネージ プロジェクトは、COM オブジェクトとして登録および公開されます。
OrderFormsLibrary .NET COBOL プロジェクトの内容は次のとおりです。
.NET COBOL プロジェクトをデバッグするには、OrderFormsLibrary プロジェクトがスタートアップ プロジェクトとして設定されていることを確認します。
Customer.cbl には、ビジネス ロジック用および Dialog System スクリーンセットとの対話用の元のコードが含まれています。Customer.cbl には、.NET COBOL プロジェクトと対話するための追加コードと Windows Forms Order フォームを表示するための追加コードも含まれています。Customer.cbl に含まれている追加コードは、次の処理を行います。
$SET を使用して次のコンパイラ指令を設定します。
$SET ans85 mfoo ooctrl(+P) case
CLASS-CONTROL パラグラフで COM クラスの OrderFormsLibrary.FormsFactory を OO COBOL クラス名の OrderFormFact にマッピングします。このパラグラフでは、COM クラスは Micro Focus ネイティブ OO クラス ライブラリの $OLE$ という COM ドメイン内にあります。
class-control. OrderFormFact is class"$OLE$OrderFormsLibrary.FormsFactory".
フラグを評価して Orders ボタンが押されたどうかを判断し、それに応じて応答を行います。
WHEN customer-orders-flg-true PERFORM Show-Orders-Form
customer.gs に元々存在していた Orders ダイアログの Windows Forms バージョンを実装する COM オブジェクトのインスタンス (新しい .NET オーダー フォーム ライブラリ) を作成します。
invoke OrderFormFact "New" Returning formsLibrary
.NET コードでネイティブ コードを呼び出す際に使用できる手続きポインターを設定します。
set pptr to entry "Customer_Callback"
コールバックで使用されるデータ ブロックへのポインターを取得します。
Customer-Callback SECTION. entry "Customer_Callback" stdcall. exit program returning address of CUSTOMER-DATA-BLOCK.
新しい Orders フォームを起動して表示します。
invoke formsLibrary "CreateOrderForm" using by value pptr-val
スクリーンセットの customer.gs は、元の [Orders] ダイアログを表示しなくなっていますが、代わりにネイティブ COBOL プログラムに制御を渡します。[Main-Window] ダイアログ内の [Orders] ボタンに対する命令は、次のように変更されています。
SET-FLAG ORDERS-FLG(1) RETC * REFRESH-OBJECT DIALOG-BOX * SET-FOCUS DIALOG-BOX
上記の命令により、ORDERS-FLG は Orders ボタンが押されたことを示すように設定されます。そのため、ネイティブ COBOL プログラムはフラグを評価し、それに応じて応答を行うことができます。制御は、ネイティブ COBOL プログラムに返されます。余分な行はコメントアウトされるため、古い Orders ダイアログは表示されなくなります。
IFormsFactory.cbl は、Windows Forms Order フォームを作成するためのインターフェイスを定義します。IFormsFactory.cbl には、次の処理を行うコードがあります。
.NET Framework の InteropServices クラスを使用して、インターフェイスを宣言します。また、ComInterfaceType:: InterfaceIsDual の指定によって、遅延バインドに対する COM オブジェクト サポートを確立します。別の方法として、ComInterfaceType::InterfaceIsIDispatch (ComInterfaceType::InterfaceIsIUnknown ではない) を指定することもできます。
interface-id OrderFormsLibrary.IFormsFactory attribute System.Runtime.InteropServices.InterfaceType (type System.Runtime.InteropServices.ComInterfaceType::InterfaceIsDual)
デフォルトでは、'Register For COM Interop' プロパティはすべてのものをデュアル インターフェイスとして公開するので注意してください。
CreateOrderForm() メソッドを定義します。これは、ネイティブ コードから .NET COBOL コードへのエントリ ポイントの定義です。
method-id CreateOrderForm. procedure division using by value callback as binary-long. end method.
FormsFactory.cbl は、ネイティブ プログラムからの要求に応じて Orders フォームのインスタンスを作成します。FormsFactory.cbl には、次の処理を行うコードがあります。
IFormsFactory インターフェイスを実装するクラスを宣言します。
class-id OrderFormsLibrary.FormsFactory implements type OrderFormsLibrary.IFormsFactory.
クラスの可視化によって、そのクラスを COM に公開します。
attribute ComVisible(true)
COM に公開するデフォルト インターフェイスとして IFormsFactory インターフェイスを指定します。
attribute ComDefaultInterface (type of OrderFormsLibrary.IFormsFactory)
コールバック関数のデリゲートを取得し、それを使用して顧客データ ブロックを確保します。GetDelegateForFunctionPointer() は、アンマネージ関数ポインターをデリゲートに変換します。
set pptr to new System.IntPtr(callback) set custCallback to type System.Runtime.InteropServices.Marshal::GetDelegateForFunctionPointer (pptr, type of CustomerCallback) as type CustomerCallback
コールバック関数のデリゲートを宣言します。
delegate-id CustomerCallback. procedure division returning pCustomerDataBlock as type IntPtr. end delegate.
Orders フォームを作成し、それをモーダル ダイアログ ボックスとして表示します。
set form to new OrderFormsLibrary.OrderForm(custCallback) invoke form::ShowDialog()
OrderForm.cbl [Code] は部分クラスであり、OrderFormsLibrary.OrderForm とも呼ばれ、Windows Forms Orders フォームを処理するためのコードを含んでいます。
OrderForm.cbl [Code] には、次のメソッドがあります。
ネイティブ コードにコールバックして、顧客データ ブロックを取得します。ポインターは、_pCustomerDataBlock. に格納します。
set _pCustomerDataBlock to callback::Invoke()
データ ブロックをローカル記憶域内のコピーにアンパックします。このコピーには、ネイティブ コードの場合と同じ方法でアクセスできます。Marshal::Copy() メソッドは、_pCustomerDataBlock ポインターを pData にコピーします。
invoke type Marshal::Copy (_pCustomerDataBlock, pData, 0, length of CUSTOMER-DATA-BLOCK) set CUSTOMER-DATA-BLOCK to pData
次のような PERFORM ブロックおよび文とともに CUSTOMER-DATA-BLOCK 内のオーダー情報を使用して Orders フォームを初期化します。
perform varying row thru OrdersGridView::Rows move CUSTOMER-ORD-NO(array-ind) to row::Cells::get_Item("OrderNo")::Value move CUSTOMER-ORD-DATE(array-ind) to dt1 ...
フォーム クローズ イベントを処理し、ローカルに保持された Dialog System データ ブロックを呼び出し元に移動します。Marshal::Copy() メソッドは、pData ポインターを _pCustomerDataBlock にコピーします。
set pData to CUSTOMER-DATA-BLOCK invoke type Marshal::Copy (pData, 0, _pCustomerDataBlock, LENGTH OF CUSTOMER-DATA-BLOCK)
[OK] ボタン クリック イベントを処理します。
[Delete] ボタン クリック イベントを処理します。