Customer + .NET WinForm サンプルの CustomerWinForm.sln は、Dialog System の元の Customer サンプルを取得し、Orders ダイアログをより最新式の Windows Forms Orders フォームに置き換えます。メインの Customer アプリケーションはほとんど未変更のままであるため、アプリケーションはネイティブ・コードのメイン・プログラムになり、マネージ・コードを COM オブジェクトとして呼び出して Windows Forms Orders フォームを処理します。
次の図の左側には、ネイティブ・コードと、スクリーンセットを処理する Dialog System があります。マネージ・コードは、新しい Windows Forms フォームとともに右側にあります。この図は、マネージ・コードを含んだ COM 呼び出し可能ラッパ (COM Callable Wrapper; CCW) のインターフェースとなるネイティブ・コード、および渡されて返されるデータ・ブロックも示しています。
上図の数字は、プロセス内の重要なポイントを示しています。次では、これらの重要なポイントについて説明します。
データ・ブロックのコピーは、使用するマネージ・クラス用に作成されます。
エントリ・ポイントはネイティブ・コードで作成され、マネージ・コードからコールバックできる状態になります。
ソリューションには、ネイティブ・プロジェクトとマネージ・プロジェクトという 2 つのプロジェクトがあります。ネイティブ・プロジェクトの Customer には、元のソースのほかに、別の方法で Orders ダイアログを処理するための変更、およびマネージ・コード・プロジェクトと対話するための変更が含まれています。
Customer ネイティブ・プロジェクトの内容は次のとおりです。
ネイティブ・プロジェクトをデバッグするには、Customer プロジェクトがスタートアップ・プロジェクトとして設定されていることを確認します。これを行うには、プロジェクトを右クリックして [Set as StartUp Project] をクリックします。
マネージ・プロジェクトの OrderFormsLibrary には、新しい Windows Forms Orders フォームが含まれています。また、マネージ・コードとネイティブ・コード間で顧客データ・ブロックを渡すためのサポート・コードも含まれています。このマネージ・プロジェクトは、COM オブジェクトとして登録および公開されます。
OrderFormsLibrary マネージ・プロジェクトの内容は次のとおりです。
マネージ・プロジェクトをデバッグするには、OrderFormsLibrary プロジェクトがスタートアップ・プロジェクトとして設定されていることを確認します。
Customer.cbl には、ビジネス・ロジック用および Dialog System スクリーンセットとの対話用の元のコードが含まれています。また、マネージ 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
マネージ・コードでネイティブ・コードを呼び出す際に使用できるプロシージャ・ポインタを設定します。
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() メソッドを定義します。これは、ネイティブ・コードからマネージ・コードへのエントリ・ポイントの定義です。
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] ボタン・クリック・イベントを処理します。