自動翻訳によりレイアウトの一部が崩れます

FLEXSCHEスクリプティングフォーム

FLEXSCHEスクリプティングフォーム(以下、FSF)を利用することにより、従来スクリプトで記述できなかった高度なユーザーインターフェース(モーダルフォームとモードレスフォーム)をスクリプトだけで容易に構築することができるようになります。またWSCGenで生成される雛形を利用することで、コードの記述量を最小限に抑えることができます。

FSFはSDLib.ISDLFormに実装されており、このインスタンスを生成するためのProgIDは"SDLib.Form"です。なお各コントロールを表すインターフェースはSDLib.ISDLFormControlもあります。

ここでは特に断りのない限り、VBScriptの表記方式に準じます。

リファレンス情報
フォームの生成とハンドラの実装
フォームの構築
イベントの処理
モーダルフォームの終了と設定内容の取得

設定のシリアライズ
アドインパラメタとして与えられたデータの受け渡し

コーディングの例については「FSFのサンプルコード」もご覧ください。

リファレンス情報

ISDLFormのメソッドとプロパティ

基本メソッドは次の4つだけです。これだけでFSFのすべてを操作することができます。

Sub Setup( name, type, progID )
   フォームを初期化する
name フォームを識別する名前
type フォームの種類
種類  説明 
 _ok OKボタンのみのモーダルフォーム
 _ok_cancel OKボタンとキャンセルボタンがあるモーダルフォーム
 _yes_no YesボタンとNoボタンがあるモーダルフォーム
 _yes_no_cancel YesボタンとNoボタンとキャンセルボタンがあるモーダルフォーム
 view カスタムビュー(モードレスフォーム)
 panel カスタムパネル(モードレスフォーム)
 project_pane プロジェクトパネル内のペイン(モードレスフォーム)
progID ハンドラが実装されているコンポーネントのProgID。通常はこのスクリプトのProgID
Function ShowForm( project )
  フォームを開く。singletonプロパティがTrueのモードレスフォームの場合、同種のフォームがすでに存在すれば、新規に作成せずにそれにアタッチする。
project GUIのプロジェクト
戻り値 モーダルフォームの場合は閉じる際に押されたボタン。"ok"、"cancel"、"yes"、"no"のいずれか。モードレスフォームの場合は無意味
Function Command( target, command, [param] )
  コントロールやフォームにコマンドを与えて操作する
  target  操作対象となるコントロールの名前。フォームの場合はフォームの名前、あるいは"form"を与える
  command コマンド名。拡張オプションを付加することができる。詳しくは『コマンド一覧』を参照
  param コマンドのパラメタ(補足情報)。省略可
  戻り値 実行結果(結果がある場合)
Function AddControl( name, ctrlType, [option] )
   フォームにコントロールを追加する
  name コントロール名。以後識別が不要な場合は空文字列でも構わない
  ctrlType コントロールの種類。拡張オプションを付加することができる。詳しくは『コントロール一覧』を参照
  option 生成オプション。詳しくは『生成オプション一覧』を参照
  戻り値 追加されたコントロール(ISDLFormControl)を返す

プロパティには以下のものがあります。これらはすべてCommandメソッドで代用できます。

Property( target, name )
  プロパティを取得・設定する。詳しくは『フォーム一覧』を参照
target 対象となるコントロールの名前を指定。フォームの場合はフォームの名前、あるいは"form"を与える
name プロパティ名。拡張オプションを付加することができる。詳しくは『プロパティ一覧』を参照
同義の表記 取得時:Command( target, "get_" + name )
設定時:Command target, "set_" + name, <設定値>
Value( ctrl )
  指定したコントロールの値を取得・設定する。詳しくは『コントロール値一覧』を参照
ctrl フォームを識別する名前
同義の表記 Property( ctrl, "value" )
Control( ctrl )
  指定したコントロール(ISDLFormControlオブジェクト)を取得する
  ctrl コントロール名を指定
  同義の表記 Property(ctrl, "control" )
FormData( key )
  フォームに保持させるデータ。FLEXSCHEのプロジェクト(IProject)を保持させることはできません。
  key データを識別するためのキー文字列
  同義の表記 Property( "form", "_" + key )
FormCaption
  フォームのキャプション
  同義の表記 Property( "form", "caption" )
Project
  FLEXSCHEのプロジェクト。ShowFormメソッドで渡されたもの。取得専用で、設定はできない
  同義の表記 Property( "form", "project" )

基本メソッド以外のメソッドには以下のものがあります。これらはすべて基本メソッドで代用できます。

Sub AddNull( width )
  スペーサーオブジェクトを追加する
width スペーサーの幅を指定する
同義の表記 AddControl "", "null:" + width
Sub AddLabel( caption )
  ラベル
caption キャプション文字列を指定する
同義の表記 AddControl "", "label:" + caption
Sub AddTab( pos )
  タブ位置を追加する
pos 追加するタブ位置。左端からのピクセル数
同義の表記 Command "form", "add_tab", pos
Sub NextRow( ctrl )
  改行する
  ctrl 下辺を改行の基準とするコントロールの名前。省略すると、現在のカーソルのY座標が基準となる
  同義の表記 Command "form", "next_row:" + ctrl

ISDLFormControlのプロパティ

ISDLFormControlのメソッドとプロパティです。これらはすべてISDLFormのメソッドで代用することができます。下記の「同義の表記」中の"ctrlName"はコントロールの名前を表しています。

Name
  コントロールの名前を取得する。これは既定のプロパティなので、Nameプロパティを指定しなくても暗黙に取得することができる
同義の表記 form.Property( ctrlName, "type" )
Type
  コントロールの種類を取得する
  同義の表記 form.Property( ctrlName. "type" )
Property( name )
  指定したプロパティを取得・設定する。取得できる値についての詳細はプロパティ一覧』を参照
name プロパティ名
同義の表記 form.Property( ctrl, name )
Function Command( command, [param] )
  指定したコントロール(ISDLFormControlオブジェクト)を取得する
  command コマンド名。拡張オプションを付加することができる。詳しくは『コマンド一覧』を参照
  param コマンドのパラメタ(補足情報)。省略可
  戻り値 実行結果(結果がある場合)
  同義の表記 form.Command( ctrlName, command, param" )
Value
  コントロールの値を取得・設定する。詳しくは『コントロール値一覧』を参照
  同義の表記 form.Property( ctrlName, "value" )
Anchor
  アンカー設定文字列を取得・設定する
  同義の表記 form.Property( ctrlName. "anchor" )

コントロール一覧

コントロール名と
拡張オプション
説明  表示  第1拡張オプション 第2拡張オプション 
label:<caption> ラベル キャプション文字列 -
list:<lines>:<width> リストボックス  幅(行数) 幅(ピクセル数)
combo_list:<lines>:<width> ドロップダウン選択のみのコンボボックス ドロップダウン部の最大の行数 幅(ピクセル数) 
combo_edit:<lines>:<width> 文字編集可能なコンボボックス ドロップダウン部の最大の行数 幅(ピクセル数)
edit:<lines>:<width> エディットボックス 行数 幅(ピクセル数)
button:<caption>:<width> ボタン  キャプション文字列 幅(ピクセル数)
radio:<caption> ラジオボタン   キャプション文字列 -
radio_group ラジオボタンをグループ化する不可視オブジェクト - -
check:<caption> チェックボックス   -
date 日付入力(時刻部分は無し)   - -
datetime 日時入力 - -
null:<width>  スペーサーオブジェクト 不可視 幅(ピクセル数) -

コマンド一覧

コマンド名と
オプション
対象 動作 パラメタ 拡張オプション 戻り値
next_row:<ctrl> フォーム  改行 - 指定されている場合は、名前で指定されたコントロールの下辺を基準に改行する -
add_tab フォーム   タブ位置を追加する タブ位置(X座標)を表す整数値 - -
clear_tabs フォーム  タブ位置情報をクリアする - - -
focus_on コントロール共通 キーボードフォーカスをセットする - - -
set_*  コントロール共通 Propertyへの設定と同じ。詳しくは『プロパティ一覧』を参照 プロパティ値 - -
get_* コントロール共通 Propertyからの取得と同じ。詳しくは『プロパティ一覧』を参照 - - プロパティ値
add_string:<index> combo_list
combo_edit
list
文字列をリストに挿入する 挿入する文字列  挿入位置。省略された場合は末尾へ 挿入したインデックス
clear combo_list
combo_edit
list
 リストをクリアする - -
delete combo_list
combo_edit
list
文字列をリストから削除する 削除位置のインデックス、あるいは削除対象の文字列 - -
find_string combo_list
combo_edit
list
文字列をリストから検索するする 検索したい文字列 - 見つけたインデックス。見つからなければ-1を返す

プロパティ一覧

プロパティ名  対象  内容 拡張オプション 
caption フォーム キャプション文字列。FormCaptionと同じ -
singleton フォーム  モードレスフォームのインスタンスが単一存在であるかどうかを表すブール値。既定はTrue -
dynamic_layout フォーム 動的レイアウトを有効にするかどうかを表すブール値。既定はTrue -
control:<ctrl> フォーム 指定した名前のコントロール。取得のみ コントロール名
debug フォーム デバッグモードかどうか。既定はFalse。デバッグモードではモードレスフォームのハンドラの変更が即座に反映されるが、多少のオーバーヘッドがある コントロール名
'_'で始まる文字列 フォーム
コントロール共通
各コントロールが保持するユーザー定義の任意の値 -
value コントロール共通  コントロールの値を取得する。詳しくは『コントロール値一覧』を参照 -
type コントロール共通  コントロールの種類を取得する。詳しくは『コントロール一覧』を参照 -
enabled コントロール共通 コントロールが有効化無効かを取得・設定する。ブール値 -
width コントロール共通 コントロールの幅を取得する。Initialize中は設定もできる -
visible コントロール共通  表示されるかどうかを取得・設定する。ブール値 -
anchor コントロール共通 アンカー文字列を取得する。Initialize中は設定もできる -
caption button
label
キャプション文字列  -
cur_sel combo_list
combo_edit
list
現在の選択位置。選択されていない場合は-1 -
string:<index> combo_list
combo_edit
list 
リスト内の文字列 インデックス。指定されていない場合はcur_sel
count combo_list
combo_edit
list 
リスト内の文字列の数  -
selected_count list 選択されている項目の数 -
selected:<index> list 項目が選択されているかどうかを表すブール値 インデックス 
read_only edit  読み取り専用であるかどうかを表すブール値 -

コントロール値一覧

コントロールのValueプロパティで取得・設定できる値です。

対象 値 
radio_group 選択されているradioコントロールの名前
radio 選択されているかどうかを表すブール値 
check チェックされているかどうかを表すブール値 
combo_list
list
選択されているインデックス
combo_edit
edit
label
テキストの文字列
datetime
date
日時(DATE値)

イベント一覧

 イベント名 対象  意味 パラメタ
change edit
combo_edit
テキスト文字列が変わった -
clicked button
radio
check 
クリックされた -
sel_change combo_list
combo_edit
list
radio_group
選択が変わった  -
drop_down combo_edit ドロップダウンされた -
double_clicked list ダブルクリックされた -

生成オプション一覧

AddControlメソッドの生成オプションとして以下のオプションを指定できます。生成オプションには':'(コロン)に続けてパラメタを付加できるものがあります。複数の指定がある場合は"/"でつないで複数列記できます。

例) form.AddControl "btnDelete", "button:削除(&D)", "x:50/y:+30/update_cursor"
生成オプション 対象 意味 パラメタ
x:<xcoord> コントロール共通 X座標を指定する フォーム左端を基点とするX座標を表す整数値。先頭が"+"ならば直前に追加されたコントロール位置の左端からの相対指定となる。"++"ならば直前に追加されたコントロール位置の右端からの相対指定となる
y:<ycoord> コントロール共通 X座標を指定する フォーム上端を基点とするY座標を表す整数値。先頭が"+"ならば直前に追加されたコントロール位置の上端からの相対指定となる。"++"ならば直前に追加されたコントロール位置の下端からの相対指定となる
update_cursor コントロール共通 xまたはyが指定されているときに、カーソルも強制的に連動させる -
down コントロール共通 直前に追加したコントロールの下に配置するが、カーソルは動かさない。詳しくは『行・カーソルモデル』を参照 -
anchor:<string> コントロール共通 アンカーを設定する。詳しくは『コントロールのアンカリング』を参照 アンカー指定の文字列。'l' / 't' / 'r' / 'b'の組み合わせ、または'a'
align_right:<ctrl> コントロール共通 このコントロールの右端を指定したコントロールの右端に合わせるように移動または伸長する 揃える相手のコントロールの名前。省略した場合はフォーム右端に揃えることを意味する
width:<pixels> null
label
list
combo_list
combo_edit
edit
コントロールの幅を指定する 幅(ピクセル数)
multi_sel list 複数選択であることを指定する
read_only edit 読み取り専用であることを指定する -
h_center label ラベルを左右方向の中央に描画する -
v_center label ラベルを上下方向の中央に描画する。この場合、文字列中の改行は無効になる -

フォームの生成とハンドラの実装

"SDLib.Form"をProgIDとしてフォームオブジェクトを生成し、生成後にSetupメソッドを呼ぶことでフォームを利用できる状態になります。次にShowFormメソッドを呼ぶことで、フォームが画面上に現れます。

set form = CreateObject( "SDLib.Form" );
form.Setup( "TestForm", "view","Test01.Manager" );
form.ShowForm( project );

変数"project"はアドインパラメタなどから取得したものです。"TestForm"はフォームの任意の名前、第2引数はフォームの種類を指定するもので、"view"はカスタムビューです。第3引数の"Test01.Manager"はハンドラを実装したオブジェクトのProgIDで、通常はこのスクリプトのそれと同一です。

WSCGenでフォームを追加した場合、"Show_<フォーム名>"という関数が生成され、その中に上記のコードが含まれます。雛形の状態では自動的にはフォームが開かれるわけではなく、アドインエントリー関数内から明示的にこの関数を呼ばなくてはなりません。

フォームには、それが表示されている間は他の操作が一切できないモーダルフォームと、そうでないモードレスフォームに分けられます。

"_ok"、"_ok_cancel"といったモーダルフォームの場合、Showフォームメソッドは"OK"や"Cancel"といったボタンが押されるまではブロックし、戻り値は最後に押されたボタンを表します。

"view"、"panel"、"project_pane"といったモードレスフォームの場合は、呼び出してブロックせずにすぐに戻り、戻り値は常に空文字列です。ShowForm後、モーダルフォームはすでに消滅しているので値の取得だけができますが、モードレスフォームの場合は引き続き値の設定もできます。モードレスフォームの右下隅のリビルドボタンを押すことで、現時点のスクリプトを反映したフォームの再構築ができます。また、"project_pane"にはその左隣にクローズボタンがあり、フォームを閉じることができます。

モードレスフォームには"singleton"プロパティがあり、これがTrueの場合、既存のフォームが存在すれば新規のフォームを生成せず、以降は既存フォームへの操作となります。Falseの場合は新規のフォームが作られます。ただし、"project_pane"に限ってはsingletonモードは常にTrueです。

ハンドラには次の5つがあります。

ハンドラ名 説明
*_Initialize( form ) フォームを構築する。引数フォームは対象のフォーム
*_Finish( form, choice) モーダルダイアログでフォームを閉じるためのボタンが押されたときに呼ばれる。引数formは対象のフォーム。引数choiceは"ok"、"cancel"、"yes"、"no"のいずれか。モードレスダイアログでは呼ばれない。フォームの内容が正しくない場合は、戻り値Falseを返すことで、フォームの終了を抑制することができる。ただし"cancel"だけはフォーム終了を抑制できない。
*_Event( form, ctrl, evnt, param ) フォーム上で何かしらのイベントが発生したときに呼ばれる。引数formは対象のフォーム。引数ctrlはイベントが発生したコントロール。引数envtは発生したイベントの名前。引数paramはイベントに付随するパラメタ(ただし現在はまだ使われていない)。イベントを処理したときはTrue、そうでない場合はFalseを返す。
*_Load( form, xmlElem ) プロジェクトがロードされたときに既存のフォームの設定情報をproject.xpsから読み込む。引数formは対象のフォーム。引数xmlElemは設定が保存されているXMLエレメント
*_Save( form, xmlElem ) プロジェクトがセーブされる既存のフォームの設定情報をproject.xpsに書き出す。引数formは対象のフォーム。引数xmlElemは設定を保存するXMLエレメント
                        実際には、*にはSetupメソッドで指定したフォームの名前が入ります。

フォームの構築

フォーム構築時に*_Initializeハンドラが呼ばれます。その中で各コントロールを追加し、その位置関係(レイアウト)、コンテンツ、グルーピングなどを定義します。コントロールが配置されていった結果、フォームの「初期サイズ」が決まります。その時点でのコントロールの配置を「初期レイアウト」と呼びます。

モーダルフォームでは「初期サイズ」と実際のフォームのサイズは一致しますが、モードレスフォームではそのときどきで異なります。これをフォームの「実サイズ」と呼びます。そのギャップを埋めるために各コントロールが移動したり拡大・縮小したりするように設定することができます。その結果としての配置を「動的レイアウト」と呼びます。モーダルフォームか、後述のアンカー指定のあるコントロールがひとつも無いモードレスフォームに限って、初期レイアウトと動的レイアウトは一致します。

行・カーソルモデル

FSFのフォーム構築では基本的には「行・カーソルモデル」になっています。つまりフォームへコントロールを追加していくとカーソル(追加位置)が右方向へずれていき、改行すると1行下の先頭へカーソルが移動します。基本的にはこの流れで初期レイアウトが決まります。

コントロールの追加にはAddControlメソッドを使います。改行はNextRowメソッド(または"next_row"コマンド)です。

form.AddControl "btn1", "button:ボタン1"
form.AddControl "btn2", "button:ボタン2"
form.AddControl "btn3", "button:ボタン3"
form.NextRow
form.AddControl "btn4", "button:ボタン4"
form.AddControl "btn5", "button:ボタン5"

1行目の"btn1"はコントロールを識別するための名前で重複さえなければ自由に指定することができます。名前が重複するコントロールを追加することはできません。後に識別する必要がない場合は空文字列("")を指定することもできます。

なお、ここではコントロールの種類としてbuttonが指定されています。buttonでは拡張オプションとしてキャプション(この例では"ボタン1")を指定することができます。

右のフォームを生成するコードは以下の通りです。

form.AddLabel "数量"
form.AddControl "qty", "edit::50"
form.NextRow
form.AddLabel "日時"
form.AddControl "dt", "datetime"
form.NextRow
form.AddLabel "入荷品目"
set ctrl = form.AddControl( "item", "combo_edit" )
ctrl.Command "add_string", "原料A"
ctrl.Command "add_string", "原料B"
ctrl.Command "add_string", "原料C"
ctrl.Value = "原料A"

combo_editを追加したときの戻り値であるコントロールオブジェクトを変数ctrlに代入し、その後でリスト項目に文字列を追加しています。変数ctrlを使わずに以下のように書くこともできます。意味はまったく同じです。

form.Command "item", "add_string", "原料A"
タブ揃え

上の例では、qty、dt、itemの3つのコントロールの位置が不揃いになっており、格好がよくありません。タブ位置を明示的に与えることで、これを揃えることができます。先頭に

  form.AddTab 80

を挿入するだけで、右のレイアウトになります。これは各行の2個目のコントロールがフォーム左端から80ピクセルの位置に揃うように指示するものです。タブ位置はいくつでも追加することができますので、行の3番目、4番目のコントロールの揃え位置も制御できます。フォーム構築の途中で一旦クリア("clear_tabs"コマンド)して、タブ位置を改めて定義しなおすこともできます。

一時的な下移動とradioコントロールのグループ化

次のコードは下のフォームを構築します。

form.AddLabel "学歴"
form.AddControl "radio1", "radio:中学卒"
form.AddControl "radio2", "radio:高校卒"
form.AddControl "radio3", "radio:大学卒"
form.AddLabel "性別"
form.AddControl "radiom", "radio:男性"
form.AddControl "radiof", "radio:女性"
set ctrl = form.AddControl( "listA", "list:5" )
ctrl.Command "add_string", "項目A"
ctrl.Command "add_string", "項目B"
ctrl.Command "add_string", "項目C"

ratioコントロールが横方向へ並んでしまうために分かりにくくなっています。次のコードではこれらを縦に並べています。また5つのradioからの択一となってしまいますが、最初の3つと後の2つをグループとして分けます。radioコントロールの初期値も設定しています。

form.AddLabel "学歴"
form.AddControl "groupEdu", "radio_group"
form.AddControl "radio1", "radio:中学卒"
form.AddControl "radio2", "radio:高校卒", "down"
form.AddControl "radio3", "radio:大学卒", "down"
form.Value( "groupEdu" ) = "radio1"
form.AddLabel "性別"
form.AddControl "groupSex", "radio_group"
form.AddControl "radiom", "radio:男性"
form.AddControl "radiof", "radio:女性", "down"
form.Value( "radiof" ) = True
set ctrl = form.AddControl( "listA", "list:5" )
ctrl.Command "add_string", "項目A"
ctrl.Command "add_string", "項目B"
ctrl.Command "add_string", "項目C"

コントロール追加時に生成オプション"down"を指定することで、カーソルを移動することなく、直前に追加したコントロールの直下にコントロールが追加されます。

不可視のradio_groupコントロールを追加したあとに追加されるradioコントロールがひとつのグループとみなされます。「学歴」ではradio_groupの値としてradioの名前を設定することでそのradioを選択できる様子を示しています。「性別」の方ではradioコントロールに直接ブール値を設定する様子を示しています。

改行位置の調整とコントロールの右揃え

次に、listコントロールに入力した文字列を追加するフォームを構築してみます。次のコードを実行すると右のフォームになります。

set ctrl = form.AddControl( "listA", "list:5" )
ctrl.Command "add_string", "項目A"
ctrl.Command "add_string", "項目B"
ctrl.Command "add_string", "項目C"
form.NextRow
set ctrl = form.AddControl( "input", "edit" )
ctrl.Value = "ABC"
form.AddControl "btnAdd", "button:追加(&A)"

一行分だけ改行しているので、縦に5行分の大きさのあるlistコントロールと2行目が重なってしまっています。次のようにNextRowメソッドの改行位置(どのコントロールの下へ改行するか)を明示的に指定することで、重ならないように制御することができます。

set ctrl = form.AddControl( "listA", "list:5" )
ctrl.Command "add_string", "項目A"
ctrl.Command "add_string", "項目B"
ctrl.Command "add_string", "項目C"
form.NextRow "listA"
set ctrl = form.AddControl( "input", "edit", "align_right:listA" )
ctrl.Value = "ABC"
form.AddControl "btnAdd", "button:追加(&A)"

この例ではeditコントロールを追加する際に生成オプション"align_right"も指定しています。これは、追加するコントロールの右端をどのコントロールの右端とそろえるかを指定するものです。これによりきれいに整列させることができます。なお、"align_right"指定によりeditコントロールが横方向に伸長していますが、これはコントロールの幅(ピクセル数)が明示的に指定されていないためです。幅が指定されていると、幅を維持しつつ右へ移動して右端を揃えるような挙動になります。

次の例ではボタンの右端をlistコントロールの右端に揃えています。ピクセル数を指定していない生成オプション"width"を付加することで、あたかも明示的に幅指定したかのように横方向への伸長を回避しながらも、自動算出された「"追加(A)"がきっちり収まる幅」を維持しています。

set ctrl = form.AddControl( "listA", "list:5:150" )
ctrl.Command "add_string", "項目A"
ctrl.Command "add_string", "項目B"
ctrl.Command "add_string", "項目C"
form.NextRow "listA"
set ctrl = form.AddControl( "input", "edit" )
ctrl.Value = "ABC"
form.AddControl "btnAdd", "button:追加(&A)", _
  "align_right:listA/width"

コントロールの座標指定

「行・カーソルモデル」とは独立にコントロールの配置位置を座標で指定することもできます。座標指定には、フォームの左上を基準とする絶対座標指定と、直前に追加したコントロールの基準とする相対座標指定とがあります。これらはいずれも生成オプション"x"および"y"により、横方向、縦方向について独立に指定します。X座標とY座標のいずれかが座標指定されていると、生成オプション"update_cursor"を指定しない限りカーソルは移動しません。

次のコードは右のフォームを構築します。btn1はフォーム左上を基準とする絶対座標を指定されています。btn2はbtn1の左上座標からの相対位置です。数値の前の'+'は直前のコントロールの左端および上端を基準とすることを指定します。btn3はbtn2の下端を基準として5ピクセル下へずらしています。'++'は右端および下端を基準とすることを指定します。btn3のX座標はカーソル位置のとおりです。ここまでカーソル位置をずらすようなコントロール追加がなかったので原点のままです。btn4も同様に5ピクセル隙間を空けて下に配置されています。btn4には"update_cursor"が指定されており、カーソル位置がbtn4の位置に従って更新されるため、座標指定の無いbtn5はbtn4の右隣に配置されています。

form.AddControl "btn1", "button:ボタン1", "x:50/y:30"
form.AddControl "btn2", "button:ボタン2", "x:+10/y:+30"
form.AddControl "btn3", "button:ボタン3", "y:++5"
form.AddControl "btn4", "button:ボタン4", "y:++5/update_cursor"
form.AddControl "btn5", "button:ボタン5"

コントロールのアンカリング

マウス操作でモードレスフォーム自体のサイズを変えたときに、フォーム内のコントロールの位置とサイズが連動して変化する仕組みがアンカーです。これは動的レイアウトのための仕組みです。

アンカーは、初期レイアウトの時点でのコントロールの各辺とフォームの各辺からの距離を固定することを意味します。4つの辺にはそれぞれ"l"(左辺)、"t"(上辺)、"r"(右辺)、"b"(下辺)の文字が割り当てられており、これらを組み合わせてアンカーを定義します。例えば"blr"(文字の順序は自由)とすると、下辺、左辺、右辺の距離が固定される指定となります。なお、"ltrb"のかわりに"a"と書くこともできます。

アンカーの設定には、AddControlメソッドの生成オプション"anchor"に書く方法と、"anchor"プロパティ(またはISDLFormControl.Anchorプロパティ)を以下のように利用します。

form.AddControl "btnAdd", "button:追加", "anchor:r"   '生成オプション
set ctrl = form.AddControl "btnDel", "button:削除"
set.Anchor = "r"       'Anchorプロパティ

イベント処理

フォーム上でイベントが発生したときの処理をするイベントハンドラは

Function MyForm_Event( form, ctrl, evnt, param )
  if ctrl = "btn1" then
    if evnt = "clicked" then
      'btn1がクリックされたときの処理
    end if
  else if ctrl = "list1" then
    if evnt = "sel_change" then
      'list1の選択が変わったときの処理
    end if
  end if
End Function

のような構成になります。イベントが発生したコントロールとイベントの種類を判定して、それに応じた処理を記述します。

第2引数のctrlはコントロールのオブジェクト(ISDLFormControl)です。コントロール名を取得するためのNameプロパティはデフォルトプロパティなので、

if ctrl.Name = "btn1" then...

と書く代わりに、上記のように

if ctrl = "btn1" then ...

と書くことができます。

モーダルフォームの終了と設定内容の取得

モーダルフォームを閉じるためのボタン("OK"、"キャンセル"、"はい"、"いいえ")が押されたときにはFinishハンドラが呼ばれます。その第2パラメタchoiceの値は"ok"、"cancel"、"yes"、"no"のいずれかです。これにより動作の場合分けをしてください。

コントロールの状態を参照して取り出す(FLEXSCHEのデータに反映させるなど)処理はFinishハンドラ内で行ってください。Finishハンドラを抜けた後はコントロールを含むモーダルフォーム全体が破棄されるため、コントロールの状態(listの各項目など)も失われてしまいます。ただしValueプロパティの値だけはモーダルフォーム破棄後も維持されるため、ShowFormメソッド呼び出しの直後でも取得することができます。

設定のシリアライズ

モードレスフォームにLoadハンドラとSaveハンドラを実装すると、プロジェクトの読み書きの際にフォーム固有の設定内容を.xpsファイルにシリアライズすることができます。Load/Saveの第2引数としてXMLDOMElementが渡されるので、その下位要素としてデータを読み書きします。下のコードは、コントロールlist1の内容を読み書きしています。

Function MyForm_Load( form, xmlElem )
  list = form.Control( "list1" )
  codeAttrs = xmlElem.selectNodes( "items/item/@name" )
  c = codeAttrs.length;
  for i = 0 to c - 1
    list.Command "add_string", codeAttrs.item( i ).value
  next
End Function

Function MyForm_Save( form, xmlElem )
  doc = xmlElem.ownerDocument
  list = form.Control( "list1" )
  c = list.Property( "count" )
  if c > 0 then
    itemsElem = doc.createElement( "items" )
    xmlElem.appendChild itemsElem
    for i = 0 to c - 1
      itemElem = doc.createElement( "item" )
      itemElem.setAttribute "name", list.Property( "string:" & i )
      itemsElem.appendChild itemElem
    next
  end if
End Function

アドインパラメタとして与えられたデータの受け渡し

FLEXSCHEのプロジェクト(IProject)はShowFormメソッドの引数としてフォームオブジェクトに渡され、Projectプロパティを通して参照することができますが、それ以外のアドインパラメタをフォーム内で利用するためにはFormDataプロパティを介してください。なお、FormDataプロパティはモードレスフォーム内では論理的に役に立たないので、利用すべきではありません。

例えば資源ガントチャートのタスクをダブルクリックしたときに呼ばれるアドイン(アドインキーがFLEXSCHE.AddInKeyEventOnTaskOnResourceGanttChart、サブキーがFLEXSCHE.AddInSubKeyEvent_DoubleClick)では、そのタスクをフォームから参照すると想定されます。そのためにはShowFormメソッドの前にFormDataプロパティにタスク参照を預けておいて、Initializeハンドラ内で取り出します。以下にサンプルコードを示します。雛形の状態に対して、Show_TestFormの引数を増やしてタスクを渡している点にも注目してください。

sub SelfRegistration( addIns )
  set addin = addIns.AddAddIn( "FormData.Test", "FormData.Manager", _
    "Test", FLEXSCHE.AddInKeyEventOnTaskOnResourceGanttChart )
  addin.SubKeyID = FLEXSCHE.AddInSubKeyEvent_DoubleClick
end sub

function Test( keyEntity )
  set timeChart = keyEntity.ParamObject( FLEXSCHE.ParamIDTimeChart )
  set taskRec = keyEntity.ParamObject( FLEXSCHE.ParamIDTaskRec )
  Test = True
  Show_TestForm timeChart.Project, taskRec
end function

sub Show_TestForm( project, taskRec )
  set form = CreateObject( "SDLib.Form" )
  form.Setup "TestForm", "_ok_cancel","FormData.Manager"
  form.FormData( "task" ) = taskRec
  form.ShowForm project
end sub

sub TestForm_Initialize( form )
  set taskRec = form.FormData( "task" )
  form.AddControl "edit1", "edit::100"
  form.Value( "edit1" ) = taskRec.OperationRec.Code
end sub

なお、モードレスフォームでProjectをFormDataに設定するとプロジェクトを閉じる操作に支障をきたすため、設定できないようになっています。

TIPS