このドキュメントでは、次のトピックについて説明します。
このセクションでは、任意のユーザー定義情報("クライアントデータ")とダイアログまたはダイアログエレメントとの関連付けについて説明します。 この関連付けを実現するためのさまざまな補完的方法があります。これらの方法の詳細については、以降のセクションで説明します。 Natural のクライアントデータ操作に関連する属性やアクションは、以下のとおりです(このドキュメントでの説明順)。
CLIENT-DATA
属性
CLIENT-KEY
属性
CLIENT-VALUE
属性
SET-CLIENT-VALUE
アクション
GET-CLIENT-VALUE
アクション
ENUM-CLIENT-KEYS
アクション
多くのダイアログエレメントのタイプでは、CLIENT-DATA
属性を使用して、単一の任意の 4 バイト整数値をダイアログエレメントに関連付けることができます。 これは、データを特定のダイアログエレメントにリンクするのに便利です。 例えば、リストボックス項目は、データベースレコードの ISN を受け渡しできます。
CLIENT-DATA
属性値は随時変更できます。
このための Natural コードは以下のようになります。
DEFINE DATA LOCAL 1 #LBITEM-1 HANDLE OF LISTBOXITEM 1 #ISN (I4) ... END-DEFINE ... READ... #LBITEM-1.CLIENT-DATA:= #ISN END-READ ...
注意:
ダイアログの CLIENT-DATA
属性はダイアログ ID のために予約されています。ユーザー定義のクライアントデータには使用しないでください。
整数データと同様に、多くのダイアログエレメントについて、CLIENT-HANDLE
属性は任意の GUI オブジェクトハンドルを取ることができます。 例えば、「ダイアログバーコントロールの操作」では、ダイアログ内で使用されるツールバーコントロールおよびダイアログバーコントロールのそれぞれに対してエントリが組み込まれたコンテキストメニューを構築する、一般的なサンプルコードが記載されています。このコードを使用すると、ユーザーはこれらのダイアログエレメントを個別に表示したり非表示にしたりできます。
この例では、各メニュー項目の CLIENT-HANDLE
属性を、対応するツールバーまたはダイアログバーのハンドルに設定しています。これにより、メニュー項目がクリックされると、その項目を直接かつ簡単に取得できます。
注意:
"キー付き" という用語は、特定のダイアログエレメントに対し、複数の項目情報を設定できることを意味します。各項目情報は、一意の取得キーに基づいて格納されます。
また、CLIENT-KEY
属性および CLIENT-VALUE
属性の組み合わせを使用することにより、最大 253 文字の英数字文字列としてクライアントデータを設定したり取得したりすることもできます。
ダイアログエレメントに特定の文字列を設定するには
ダイアログエレメントの CLIENT-KEY
属性に必要な値が設定されていない場合はまず、この属性に値を割り当てます。 これにより、文字列をダイアログエレメントに格納する際のキーが決定します。
次に、英数字の文字列をダイアログエレメントの CLIENT-VALUE
属性に割り当てます。
これにより、1 つのダイアログエレメントに多くのキー/値のペアを格納できます。
例:
#LB-1.CLIENT-KEY:= 'ANYKEY' #LB-1.CLIENT-VALUE:= 'ANYSTRING' /* The string to be stored
注意:
上記の例および以降のすべての例において、ハンドル変数 #LB-1
が使用されています。この変数は、通常は(規則に従って)リストボックスを参照します。 ただし、CLIENT-DATA
属性には例外があり、タイマやシグナルなどのユーザーインタフェースを持たないものを含め、あらゆるタイプの GUI オブジェクトにクライアントデータを関連付けることができます。
ダイアログエレメントを特定の文字列でクエリするには
この属性に必要な値が含まれていない場合は、最初に CLIENT-KEY
値をダイアログエレメントに割り当ててください。
次に、ダイアログエレメントの CLIENT-VALUE
属性をクエリして、対応する値を取得します。
CLIENT-KEY
に対応する CLIENT-VALUE
をクエリした結果、ダイアログエレメントにそのようなキー/値のペアがなかった場合、空の文字列(" ")が返されます。
例:
#LB-1.CLIENT-KEY:= 'ANYKEY' IF #LB-1.CLIENT-VALUE EQ 'ANYSTRING' THEN ... END-IF
英数字以外のデータを格納および取得する場合は少し複雑となり、以下の例のように、データを元のフォーマットに戻します。
例:
DEFINE DATA LOCAL 01 #DATE (D) ... END-DEFINE #LB-1.CLIENT-KEY := 'ANYKEY' /* Store the current date #LB-1.CLIENT-VALUE := *DATX /* Retrieve it as a date (D) field STACK TOP DATA #LB-1.CLIENT-VALUE INPUT #DATE
STACK
ステートメントは、英数字フォーマットでクライアント値を取得し、Natural スタックに格納します。INPUT
ステートメントはスタックからその値を取り出し、暗黙的に英数字フォーマットから日付フォーマットに変換して、指定された変数 #DATE
に格納します。 また、クライアント値を取得して英数字変数に格納することもできます。この場合、格納後に MOVE EDITED
ステートメントを使用して、明示的に日付フィールドに変換します。 ただし、日付フォーマット(DTFORM
)に依存せず、中間的な英数字変数も必要としないため、前述のアプローチの方が適しています。
日付や時刻など、データタイプによっては、CLIENT-VALUE
属性で指定されているデフォルトの英数字表記が、元のデータタイプの情報すべてに対応していない場合があります。 例えば、時間(T)の値を表すデフォルトの英数字表記には時間、分、秒のみが含まれ、日付や 1/10 秒などは含まれません。 同様に、日付(D)の値を表すデフォルトの英数字表記には、世紀の情報は含まれません。
したがって、上記の例で正しい世紀を使用するには、プログラムを実行する前に "スライディングウィンドウ"(YSLW
)パラメータを正しく設定する必要があります。
ダイナミック文字変数を使用して CLIENT-VALUE
属性値を直接受け取る場合、受け取った値は 253 文字の長さになり、必要に応じて空白が埋め込まれます。 これは、A253 フォーマットの属性バッファが内部的に使用されているためです。これについては、後で説明します。 明示的に A253 で定義されているフィールドをダイナミック変数に割り当てるときも同様です。
どちらの場合も、ダイナミック変数の末尾に空白が格納されることを回避するには、以下の例のように、単純な MOVE
や割り当ての代わりに COMPRESS
ステートメントを使用する必要があります。
DEFINE DATA LOCAL 01 #DYN (A) DYNAMIC ... END-DEFINE #DYN := 'ANYSTRING' /* Set the client data #LB-1.CLIENT-KEY := 'ANYKEY' #LB-1.CLIENT-VALUE := #DYN /* Retrieve value as 253-character string: #DYN := #LB-1.CLIENT-VALUE /* Retrieve value without trailing blanks: COMPRESS #LB-1.CLIENT-VALUE INTO #DYN
このようにすると、どちらのアプローチを使用したかに関係なく、CLIENT-VALUE
属性の値を取得および格納しても、ダイナミック英数字変数の末尾に空白は埋め込まれません。
ダイアログエレメントから特定の文字列を削除するには
この属性に必要な値が含まれていない場合は、最初に CLIENT-KEY
値をダイアログエレメントに割り当ててください。
ダイアログエレメントの CLIENT-VALUE
属性を RESET
するか、または明示的に空白値を割り当てて、対応する値を削除します。
例:
#LB-1.CLIENT-KEY:= 'ANYKEY' RESET #LB-1.CLIENT-VALUE
CLIENT-KEY
属性および CLIENT-VALUE
属性の組み合わせを使用してクライアントデータを英数字文字列に設定する代わりに、SET-CLIENT-VALUE
アクションおよび GET-CLIENT-VALUE
アクションを使用すると、クライアントデータをそのままのフォーマットで変換せずに、直接格納したり取得したりできます。 ただし、この値は圧縮形式で格納される場合があります。 特に非ダイナミック英数字データの末尾の空白は、スペースを節約するため、格納されません。
例えば、"FRED" という値とこれに続く 249 文字の空白文字が格納されている A253 フィールドを指定すると、A4 値の "FRED" のみがクライアントデータとして内部的に格納されます。 この最適化は、CLIENT-VALUE
属性経由で格納されたクライアントデータにも適用されます。
これらの 2 つの手法は、一緒に使用できます(1 つの手法をデータの設定に使用し、もう 1 つの手法をデータの取得に使用するなど)。 ただし、アクションの使用には、属性を使用する以上に多くの利点があります。この点については、以降のセクションで説明します。
アクションベースの手法を使用して、ダイアログエレメントのクライアントデータを更新するには
SET-CLIENT-VALUE
アクションを呼び出し、ダイアログエレメントのハンドル、格納する値の(クライアント)キー、および値そのものを渡します。 または、KEY パラメータを省略することもできます。この場合、ダイアログエレメントの CLIENT-KEY
属性の現在値が暗黙的にキーとして使用されます。
例:
#LB-1.CLIENT-KEY := 'ANYKEY' /* The following three statements are equivalent ways of setting the same /* information: /* (1) attribute-based approach: #LB-1.CLIENT-VALUE := 'ANYVALUE' /* (2) action-based approach, with explicitly-specified key PROCESS GUI ACTION SET-CLIENT-VALUE WITH #LB-1 'ANYVALUE' 'ANYKEY' GIVING *ERROR /* (3) action-based approach without key; CLIENT-KEY attribute implicitly used PROCESS GUI ACTION SET-CLIENT-VALUE WITH #LB-1 'ANYVALUE' GIVING *ERROR
SET-CLIENT-VALUE
アクションを使用してクライアントデータを格納する大きな利点は、CLIENT-VALUE
属性を使用する場合と異なり、英数字(A253)フォーマットに中間的に変換する必要がないという点です。 このことを以下の図で説明します。フォーマット X は任意のデータタイプを表し、フォーマット An は末尾の空白が除去された英数字値を表します。
この図の矢印 "(1)" および "(2)" で示されているように、CLIENT-VALUE
属性を使用したクライアントデータの格納と取得には 2 つの手順を実行する必要があります(Natural のすべての属性で同じことが当てはまります)。また、属性に定義されているフォーマットに対応する属性バッファ(この場合は A253)も使用します。
一方、SET-CLIENT-VALUE
アクションおよび GET-CLIENT-VALUE
アクションを使用すると、属性バッファとソースフィールドまたはターゲットフィールドとの変換を行わずに、単一の手順で、手順 "(2)" と同じ処理を効率よく実行できます。 これにより、(処理がいくらか高速になる以外に)以下の利点がもたらされます。
属性バッファを経由する必要がないため、253 文字を超える英数字データも切り捨てを行わずに格納できます。
ハンドル値を格納できます。 ハンドルと英数字フィールドとの変換は認められていないため、ハンドル値に英数字属性バッファは使用できません。
ソースデータがダイナミック英数字変数の場合、任意の末尾の空白を保持できます。 属性バッファを使用すると、末尾の空白はバッファの充填文字と区別できなくなるため(また、バッファの充填文字とみなされるため)、格納するときに変数から除去されます。
英数字フォーマットとの変換を行わずにデータを格納するため、非英数字データも情報を失うことなく格納できます。 例えば、時間値を格納しても、日付情報および 1/10 秒は失われません。また、日付値を格納しても、世紀情報は失われません。
その他に、クライアントデータの格納にアクションベースのアプローチを使用することには、以下のような利点があります。
空白のみの英数字値を格納できます。 これは、CLIENT-VALUE
属性経由では、削除操作を暗黙的に意味するため実行できません。
GIVING
フィールドを指定すると、標準のエラー処理を実行しなくても(必要であれば、GIVING *ERROR
を使用して実行可能)このフィールドにエラーコード(無効なコントロールハンドルが渡された場合など)が返されます。
アクションベースの手法を使用して、ダイアログエレメントのクライアントデータをクエリするには
GET-CLIENT-VALUE
アクションを呼び出し、ダイアログエレメントのハンドル、取得する値の(クライアント)キー、および値そのものを受け取るフィールドを渡します。 または、KEY パラメータを省略することもできます。この場合、ダイアログエレメントの CLIENT-KEY
属性の現在値が暗黙的にキーとして使用されます。
例:
DEFINE DATA LOCAL 01 #VALUE (A253) ... END-DEFINE PROCESS GUI ACTION GET-CLIENT-VALUE WITH #LB-1 #VALUE 'ANYKEY' GIVING *ERROR IF #VALUE <> ' ' /* Value found ... ELSE /* Value not found ... END-IF
値を受け取るために指定するフィールドのフォーマットは、格納する値のフォーマットとの MOVE
での互換性が必要であることに注意してください。
指定したダイアログエレメントに対して指定したキーが見つからない場合、値フィールドは RESET
されます。 例えば、英数字フォーマットの受け取りフィールドは空白で充填され、数値フォーマットの受け取りフィールドはゼロに設定されます。
ただし、このような値はプログラムで明示的にキーに対して設定できますが、この値のみを使用して必要なクライアントデータが見つかったかどうかを判断することはできません。
リセットされた値が明示的に格納されている場合にクライアントデータをクエリするには
GET-CLIENT-VALUE
アクションを呼び出し、前述の標準のパラメータに追加して、検出ステータスを受け取るためのタイプ L のフィールドを渡します。
例:
DEFINE DATA LOCAL 01 #VALUE (A253) 01 #FOUND (L) ... END-DEFINE * PROCESS GUI ACTION GET-CLIENT-VALUE WITH #LB-1 #VALUE 'ANYKEY' #FOUND GIVING *ERROR * IF #FOUND ... END-IF
GET-CLIENT-VALUE
アクションを使用してクライアントデータを読み込む主な利点もやはり、CLIENT-VALUE
属性を使用する場合と異なり、属性バッファを介さない(前述の図を参照)、つまり、英数字(A253)フォーマットとの中間的な変換を行う必要がないという点です。 代わりに、格納されているデータは値を受け取るフィールドのフォーマットに直接変換されます。
これにより、以下の利点がもたらされます。
CLIENT-VALUE
属性バッファ(未使用)の長さで切り捨てずに、253 文字を超える英数字データを取得できます。
CLIENT-VALUE
属性バッファの英数字フォーマットでは MOVE
での互換性がないハンドル値を取得できます。
データをダイナミック英数字変数に読み込む場合、格納する英数字データの任意の末尾の空白を保持できます。 CLIENT-VALUE
属性を使用すると、ダイナミック変数でバッファの充填文字も受け取るため、元のデータの末尾の空白と区別できません。
また、空白のみで構成される、格納する英数字値を認識できます。 CLIENT-VALUE
属性では、この値と暗黙的な "データなし" 値とを区別できないため、この属性経由では実行できません。
アクションベースの手法を使用して、ダイアログエレメントのクライアントデータを削除するには
SET-CLIENT-VALUE
アクションを呼び出し、ダイアログエレメントのハンドル、削除する値の(クライアント)キー、および削除する値そのものを渡します。 または、KEY パラメータを省略することもできます。この場合、ダイアログエレメントの CLIENT-KEY
属性の現在値が暗黙的にキーとして使用されます。
例:
/* No value supplied => delete any existing value for specified key PROCESS GUI ACTION SET-CLIENT-VALUE WITH #LB-1 1X 'ANYKEY' GIVING *ERROR /* Alternatively, a mixed attribute/action approach can be used: #LB-1.CLIENT-KEY := 'ANYKEY' PROCESS GUI ACTION SET-CLIENT-VALUE WITH #LB-1 GIVING *ERROR
これまでのセクションでは、クライアントキーおよびクライアント値データの作成、更新、クエリ、および削除について説明してきました。 ほとんどの場合はこれで十分です。 ただし、場合によっては、ダイアログエレメントで使用されているキーを読み込むコード側でそのキーが認識できない場合や、デバッグやテストで想定されるキーの検証が必要な場合があります。 特定のダイアログエレメントで現在使用されているキーを取得する繰り返しのプロセスを、キーの列挙と呼びます。
ダイアログエレメントのクライアントキーを列挙するには
ENUM-CLIENT-KEYS
アクションを呼び出し、キーパラメータは省略して、クライアントキーを列挙するダイアログエレメントのハンドルを渡します。 これにより、ダイアログエレメントの列挙カーソル(つまり、位置)が内部キーリストの先頭にリセットされます。 列挙カーソルはダイアログエレメントが作成されるときに初期化されるため、ダイアログエレメントに対する最初のキーの列挙では、この手順は厳密には必要ありません。
ただし、状況に関係なく列挙できるようにするために、このようにカーソルを明示的にリセットするのはよい習慣です。
ENUM-CLIENT-KEYS
アクションを再度呼び出し、ダイアログエレメントのハンドル、および返される最初のキー(存在する場合)を受け取るキーパラメータを渡します。
上記の呼び出しによって、キーフィールドが内部的に空白に RESET
される場合、これはそれ以上キーが残っていないことを意味するため、プログラムは列挙プロセスを終了する必要があります。
そうでない場合、手順 2 に戻って次のキー(存在する場合)を取得します。
例:
/* Enumerate and output all client keys in use by control #LB-1: /* (1) Reset enumeration cursor: PROCESS GUI ACTION ENUM-CLIENT-KEYS WITH #LB-1 GIVING *ERROR /* (2) Enumerate and delete the keys one-by-one: REPEAT PROCESS GUI ACTION ENUM-CLIENT-KEYS WITH #LB-1 #LB-1.CLIENT-KEY GIVING *ERROR IF #LB-1.CLIENT-KEY <> ' ' RESET #LB-1.CLIENT-VALUE /* delete the key END-IF WHILE #LB-1.CLIENT-KEY <> ' ' END-REPEAT
この例は、列挙プロセス中にキーが削除されても ENUM-CLIENT-KEYS
アクションは対応可能であることを示しています。 この例のように、最後に列挙された、つまり "現在の" キーが削除されると、Natural によって自動的に、内部の列挙カーソルがそのキーの前の列挙シーケンスに移されるか、または先行するキーがない場合はリセットされます。 どちらの場合も、ENUM-CLIENT-KEYS
によって返される次のキーは、前のキーが削除されなかった場合に返されるキーと同じキーになります。
注意:
キーが列挙されるシーケンスは実装に依存しているため、将来の Natural のバージョンで同一である保証はありません。 したがって、特定の列挙シーケンスに依存するようなコードをプログラムに記述しないようにしてください。