; ============================================================================= ; AccX [Automation Controller Controller Extended] - rrmod/com/accx.as ; ver 0.01 2001.07.08 by RiffRaff ; ver 3.00 2004.10.25 by ちょくと ; ============================================================================= ; ; ; ----------------------------------------------------------------------------- ; ; ■ デフォルトのスクリプトエンジンを設定 ; ; accengine n1 ; ; n1 : スクリプト言語 [1: VBScript, 2: JScript] ; ; ------------------------------------------------------------------------- ; ; n1 で指定したスクリプトエンジンをデフォルトに設定します。n1 に 1 を指定 ; した場合は VBScript が、2 を指定した場合は JScript がデフォルトのスクリ ; プト言語に設定されます。 ; ; ここで指定されたスクリプトエンジンは、accget や accset 命令などでスクリ ; プトエンジンの指定が省略された場合に有効となります。 必要に応じて何度で ; も変更することが可能です。 ; ; ; ■ スクリプトコードの実行 ; ; vbscript v1 ; vbs s1 ; jscript v1 ; js s1 ; ; v1 : スクリプトコードを格納した文字列型変数 ; s1 : スクリプトコードを表す文字列式 (255 文字まで) ; ; ------------------------------------------------------------------------- ; ; v1 または s1 に指定したスクリプトコードをそれぞれのスクリプトエンジンに ; 渡して実行します。 ; ; vbscript 命令及び vbs 命令は、VBScript 言語で書かれたスクリプトコードを ; VBScript エンジンに渡して実行します。JScript 命令及び js 命令は JScript ; 言語で書かれたスクリプトコードを JScript エンジンに渡して実行します。 ; ; スクリプトコードは vbscript, jscript 命令を用いた "文字列変数渡し" ある ; いは vbs, js 命令を用いた "文字列式渡し" になります。ただし文字列式で渡 ; す場合は展開後の文字数が 255 文字を越えてはいけません。 ; ; ; ■ スクリプトエンジンから変数の値を取得 (1) ; ; accgetvar v1, s2, [n3] ; ; v1 : 取得した値を格納するVARIANT変数 ; s2 : 値を取得する変数名 ; n3 : 取得先スクリプトエンジン [0: default, 1: VBScript, 2: JScript] ; ; ------------------------------------------------------------------------- ; ; スクリプトエンジンで使用されている変数の値を取得します。 ; ; v1 には取得するデータを格納するためのバリアント変数を指定します。この変 ; 数は varinit 命令により初期化されていなければいけません。 ; ; s2 には値を取得する変数名を指定します。 ; ; n3 には s2 で指定した変数名の取得先スクリプトエンジンを指定します。省略 ; 時はデフォルトのスクリプトエンジン (accengine 命令参照) が取得先となり ; ます。システム変数 stat には s2 に指定した変数のデータ型を表す数値 (バ ; リアント型の内部処理形式) が代入されます。 ; ; ; ■ スクリプトエンジンから変数の値を取得 (2) ; ; accget v1, s2, [n3] ; ; v1 : 取得した値を格納する変数 ; s2 : 値を取得する変数名 ; n3 : 取得先スクリプトエンジン [0: default, 1: VBScript, 2: JScript] ; ; ------------------------------------------------------------------------- ; ; スクリプトエンジンで使用されている変数の値を取得します。 ; ; v1 には取得するデータを格納する変数を指定します。格納されるデータの種 ; 類は、スクリプトエンジンで使用されている変数の型や、v1 に渡された変数 ; の型(数値型or文字列型)によって変わります。詳しくは、varget 命令の説 ; 明を参照してください。 ; ; s2 には値を取得する変数名を指定します。 ; ; n3 には s2 で指定した変数名の取得先スクリプトエンジンを指定します。省略 ; 時はデフォルトのスクリプトエンジン (accengine 命令参照) が取得先となり ; ます。システム変数 stat には s2 に指定した変数のデータ型を表す数値 (バ ; リアント型の内部処理形式) が代入されます。 ; ; ------------------------------------------------------------------------- ; ; この命令は accgetvar 命令の直後に varget 命令を実行します。 ; ; v1 に格納されるデータの種類は、スクリプトエンジンで使用されている変数 ; の型や、v1 に渡された変数の型(数値型or文字列型)によって変わります。 ; 詳しくは、varget 命令の説明を参照してください。 ; ; ; ■ スクリプトの変数にデータを代入 (1) ; ; accsetvar s1, v2, [n3] ; ; s1 : 代入先の変数名 ; v2 : 代入するデータを格納したVARIANT変数 ; n3 : 対象スクリプトエンジン [0: default, 1: VBScript, 2: JScript] ; ; ------------------------------------------------------------------------- ; ; HSP のバリアント変数に格納されているデータを直接スクリプトの変数に代入 ; します。 ; ; s1 には代入先の変数名を文字列で指定します。 ; ; v2 には渡すデータが格納されているバリアント変数を指定します。代入先の ; 変数はバリアント変数の型に応じたデータ型となります。 ; ; n3 には代入先変数の対象スクリプトエンジンを指定します。省略時はデフォル ; トのスクリプトエンジン (accengine 命令参照) が対象となります。 ; ; ------------------------------------------------------------------------- ; ; ※ この命令の実行には VBScript 5.0 以上が必要になります。 ; ; ; ■ スクリプトの変数にデータを代入 (2) ; ; accset s1, v2, [n3], [n4] ; accset_s s1, s2, [n3], [n4] ; accset_n s1, n2, [n3], [n4] ; ; s1 : 代入先の変数名 ; v2 : 代入するデータを格納した変数 ; s2 : 代入するデータ(文字列) ; n2 : 代入するデータ(数値) ; n3 : データの型を表わす VARTYPE 値 ; n4 : 対象スクリプトエンジン [0: default, 1: VBScript, 2: JScript] ; ; ------------------------------------------------------------------------- ; ; HSP の変数に格納されているデータを直接スクリプトの変数に代入します。 ; ; s1 には代入先の変数名を文字列で指定します。 ; ; v2 には渡すデータが格納されている変数を指定します。accset_s / accset_n ; 命令では、文字列や数値を直接指定することができます。 ; ; n3 にはデータの型を表わす VARTYPE 値を指定します。省略した場合は v2 の ; 型(文字列型or数値型)によって変わります。詳しくは varset 命令の説明を ; 参照してください。 ; ; n4 には代入先変数の対象スクリプトエンジンを指定します。省略時はデフォル ; トのスクリプトエンジン (accengine 命令参照) が対象となります。 ; ; ------------------------------------------------------------------------- ; ; この命令は varset / varset_s / varset_n 命令の直後に accsetvar 命令を ; 実行します。 ; ; ※ この命令の実行には VBScript 5.0 以上が必要になります。 ; ; ; ■ スクリプトにグローバルオブジェクトを追加 ; ; accaddobj s1, n2, [n3] ; ; s1 : スクリプト内で用いるオブジェクト変数名 ; n2 : インターフェイスポインタ (オートメーション互換) ; n3 : 追加先スクリプトエンジン [0: default, 1: VBScript, 2: JScript] ; ; ------------------------------------------------------------------------- ; ; 外部で取得したインターフェイスをスクリプトエンジンに渡してグローバルオ ; ブジェクトとして利用できるようにします。s1 にはスクリプト内で用いるオブ ; ジェクト変数名を文字列で指定します。n2 には IDispatch::Invoke() による ; メソッドの呼び出しが可能なインターフェイス (オートメーション互換) のポ ; インタを指定します。n3 には追加先スクリプトエンジンを指定します。省略時 ; はデフォルトのスクリプトエンジン (setengine 命令参照) が取得先となりま ; す。 ; ; ------------------------------------------------------------------------- ; ; ※ グローバルオブジェクトとして追加したオブジェクトは AccX を終了するま ; で解放することができません。 ; ; ; ■ 文字列複数行指定における特殊エスケープ ; ; accstresc v1 ; ; v1 : 特殊エスケープされた文字列を格納する変数 ; ; ------------------------------------------------------------------------- ; ; HSP の文字列複数行指定で通常記述することが出来ない文字を特殊エスケープ ; を使って指定出来るようにします。各文字のエスケープは以下の通りです。 ; ; ・コロン 「:」 >> 「':'」 ; ・セミコロン 「;」 >> 「';'」 ; ・シングルクォート 「'」 >> 「'\'」 ; ; v1 に指定した文字列型変数に上記のエスケープ文字が含まれる場合、それらの ; 文字はすべて通常の文字に変換されます。 ; ; ; ------------------------------------------------------------------------- ; ; ※ HSP の仕様変更によりスクリプトに互換性が無くなったり、命令自体の廃止 ; も有り得ることを付け加えておきます。あくまで当面の回避策として使用し ; てください。 ; ; #ifndef DEFINE_LOLLIPOP_ACCX #define global DEFINE_LOLLIPOP_ACCX #ifndef DEFINE_LOLLIPOP_DATACONV #include "rrmod/com/dataconv.as" #endif ; ============================================================================= ; FUNCTION - "AccX" Module ; ============================================================================= #module "AccX" #define Null 0 #define MAX_PATH 260 #define DISPATCH_PROPERTYPUT 4 #define ScriptControl "{0E59F1D5-1FBE-11D0-8FF2-00A0D10038BC}" #define IScriptControl "{0E59F1D3-1FBE-11D0-8FF2-00A0D10038BC}" #define IEnumVARIANT "{00020404-0000-0000-C000-000000000046}" ; ----- AccX モジュールの初期化 ----------------------------------------------- #deffunc _init_module_AccX mref bmscr, 67 dim ppv, 24 dup pSCtrlVB, ppv.1 ; IScriptControl (VBScript Global) dup pSCtrlJ, ppv.2 ; IScriptControl (JScript Global) dup pSErrVB, ppv.3 ; IScriptError (VBScript Global) dup pSErrJ, ppv.4 ; IScriptError (JScript Global) dup pCObjVB, ppv.5 ; VBScriptTypeInfo (VBScript Global) dup pCObjJ, ppv.6 ; JScriptTypeInfo (JScript Global) dup pSModVB, ppv.7 ; IScriptModule (VBScript Global) dup pSModJ, ppv.8 ; IScriptModule (JScript Global) dup pSMods, ppv.9 ; IScriptModuleCollection dup punkMods, ppv.10 ; IUnknown dup pEnumVar, ppv.11 ; IEnumVARIANT dup semv, ppv.12 ; ScriptEngineMajorVersion (VBScript) dup v, ppv.13 dup ps, ppv.14 ; 文字列用共用変数 s のポインタ dup ps1, ppv.15 ; 文字列用共用変数 s1 のポインタ dup bstrv, ppv.16 ; BSTR 用変数 dup errnum, ppv.17 ; エラーナンバー用変数 dup cFetched, ppv.18 ; IEnumVARIANT::Next() 用パラメータ dup bridge, ppv.19 ; bridge クラス dup dispid, ppv.21 ; DISPID dup pdispParams, ppv.22 ; DISPPARAMS 構造体へのポインタ dup rgdispid, ppv.23 ; 名前付き引数のディスパッチID 配列へのポインタ sdim s, 1024 ; 文字列用共用変数 sdim s1, MAX_PATH ; 文字列用共用変数 rr_getptr ps, s rr_getptr ps1, s1 ; VARIANT 構造体 varinit_ var1 ; VARIANT の初期化 rr_getptr rgdispid, dispidNamedArgs dispidNamedArgs = -3 ; DISPPARAMS 構造体 rr_getptr pdispParams, dispParams ; DISPPARAMS 構造体へのポインタ ; dispParams.0 = 0 ; 引数配列へのポインタ (ここではまだNULL) ; dispParams.1 = rgdispid ; 名前付き引数のディスパッチID 配列へのポインタ ; dispParams.2 = 1 ; 引数の数 ; dispParams.3 = 1 ; 名前付き引数の数 dispParams = 0, rgdispid, 1, 1 ; スクリプトエンジンの初期化 (VBScript) s = "VBScript" dup pSCtrl, pSCtrlVB ; IScriptControl dup pSErr, pSErrVB ; IScriptError dup pCObj, pCObjVB ; CodeObject dup pSMod, pSModVB ; IScriptModule gosub *InitEngine ; スクリプトエンジンの初期化 (JScript) s = "JScript" dup pSCtrl, pSCtrlJ ; IScriptControl dup pSErr, pSErrJ ; IScriptError dup pCObj, pCObjJ ; CodeObject dup pSMod, pSModJ ; IScriptModule gosub *InitEngine ; スクリプトエンジンの相互接続 (VBScript) dup pSCtrl, pSCtrlVB dup pCObj, pCObjJ dup pSMod, pSModJ s1 = "jsfunc" s = "Function jsval(x):jsval=["+s1+"].Eval(x):End Function" gosub *ConnectEngine ; JScript エンジンを VBScript に接続 ; スクリプトエンジンの相互接続 (JScript) dup pSCtrl, pSCtrlJ dup pCObj, pCObjVB dup pSMod, pSModVB s1 = "vbsfunc" s = "function vbsval(x){return("+s1+".Eval(x))}" gosub *ConnectEngine ; VBScript エンジンを JScript に接続 dup pSCtrl, pSCtrlVB ; デフォルト言語に VBScript を設定 return ; スクリプトエンジンの初期化 *InitEngine ; IScriptControl の取得 createobj_ pSCtrl, ScriptControl, IScriptControl if pSCtrl == 0 { rr_cmd_error "Script Control オブジェクトを作成できません。\nScript Control がインストールされていない可能性があります。" return } ; 指定言語でスクリプトエンジンを初期化 bstrset_ bstrv, s icall_ pSCtrl, 8, bstrv, 1 ; IScriptControl::Language() bstrfree_ bstrv ; 追加オブジェクトのイベントシンクを有効化 prm = 1 ; Connected icall_ pSCtrl, 10, prm, 1 ; IScriptControl::State() ; UI 要素の表示を有効化 prm = 0xFFFF icall_ pSCtrl, 16, prm, 1 ; IScriptControl::AllowUI() ; UI 要素のウィンドウハンドルを設定 icall_ pSCtrl, 11, bmscr.13, 1 ; IScriptControl::SitehWnd() ; タイムアウトの解除 prm = 0xFFFFFFFF ; NoTimeout icall_ pSCtrl, 14, prm, 1 ; IScriptControl::Timeout() ; IScriptError の取得 ; rr_getptr prm, pSErr ; icall_ pSCtrl, 20, prm, 1 ; IScriptControl::Error() ; IScriptModuleCollection の取得 rr_getptr prm, pSMods icall_ pSCtrl, 19, prm, 1 ; IScriptControl::Modules() ; IUnknown の取得 rr_getptr prm, punkMods icall_ pSMods, 7, prm, 1 ; IScriptModuleCollection::_NewEnum() release_ pSMods : pSMods = 0 ; IScriptModuleCollection の解放 ; IEnumVARIANT の取得 queryinterface_ pEnumVar, punkMods, IEnumVARIANT release_ punkMods : punkMods = 0 rr_setvar cFetched prm = 1, var1, rr_ptr icall_ pEnumVar, 3, prm, 3 ; IEnumVARIANT::Next() release_ pEnumVar : pEnumVar = 0 varget_ pSMod, var1, 1 ; IScriptModule の取得 ; CodeObject の取得 rr_getptr prm, pCObj icall_ pSCtrl, 21, prm, 1 ; IScriptControl::CodeObject() return ; スクリプトエンジンの相互接続 *ConnectEngine ; スクリプトの相互アクセス (_Local) bstrset_s_ bstrv, "_Local" prm = bstrv, pSMod icall_ pSCtrl, 24, prm, 2 ; IScriptControl::AddObject() bstrfree_ bstrv release_ pSMod : pSMod = 0 ; 組み込みオブジェクトの追加 (xxxfunc) bstrset_ bstrv, s1 prm = bstrv, pCObj icall_ pSCtrl, 24, prm, 2 ; IScriptControl::AddObject() bstrfree_ bstrv release_ pCObj : pCObj = 0 ; 組み込み関数の追加 (xxxval) bstrset_ bstrv, s icall_ pSCtrl, 26, bstrv, 1 ; IScriptControl::AddCode() bstrfree_ bstrv return ; ----- VBScript コードの実行 (変数) ------------------------------------------ #define global vbscript(%1) RR_CMDNAME("vbscript") vbscript_ %1 #deffunc vbscript_ val mref p1, 24 bstrset_ bstrv, p1 goto *@f ; ----- VBScript コードの実行 (文字列) ---------------------------------------- #define global vbs(%1) RR_CMDNAME("vbs") vbs_ %1 #deffunc vbs_ str mref p1, 32 bstrset_ bstrv, p1 *@ icall_ pSCtrlVB, 28, bstrv, 1 ; IScriptControl::ExecuteStatement() bstrfree_ bstrv #if LOLLIPOP_ERROR_LEVEL_ >= 3 ppv = pSCtrlVB : gosub *chkerr #endif return ; ----- JScript コードの実行 (変数) ------------------------------------------- #define global jscript(%1) RR_CMDNAME("jscript") jscript_ %1 #deffunc jscript_ val mref p1, 24 bstrset_ bstrv, p1 goto *@f ; ----- JScript コードの実行 (文字列) ----------------------------------------- #define global js(%1) RR_CMDNAME("js") js_ %1 #deffunc js_ str mref p1, 32 bstrset_ bstrv, p1 *@ icall_ pSCtrlJ, 28, bstrv, 1 ; IScriptControl::ExecuteStatement() bstrfree_ bstrv #if LOLLIPOP_ERROR_LEVEL_ >= 3 ppv = pSCtrlJ : gosub *chkerr #endif return #if LOLLIPOP_ERROR_LEVEL_ >= 3 *chkerr ; IScriptError の取得 rr_getptr prm, pSErr icall_ ppv, 20, prm, 1 ; IScriptControl::Error() rr_getptr prm, errnum icall_ pSErr, 7, prm, 1 ; IScriptError::Number() if errnum > 0 { rr_getptr pbstr, bstrv rr_getptr pv, v ; スクリプト icall_ pSErr, 12, pbstr, 1 ; IScriptError::Text() bstrget_ s1, bstrv, 1 s = "スクリプト:\t" + s1 + "\n" ; 行 icall_ pSErr, 13, pv, 1 ; IScriptError::Line() s += "行:\t" + v + "\n" ; 文字 icall_ pSErr, 14, pv, 1 ; IScriptError::Column() s += "文字:\t" + v + "\n" ; エラー prm = pbstr icall_ pSErr, 9, pbstr, 1 ; IScriptError::Description() bstrget_ s1, bstrv, 1 s += "エラー:\t" + s1 + "\n" ; コード s1 = errnum | 0x800A0000 str s1, 24 s += "コード:\t0x" + s1 + "\n" ; ソース icall_ pSErr, 8, pbstr, 1 ; IScriptError::Source() bstrget_ s1, bstrv, 1 s += "ソース:\t" + s1 ; クリア icall_ pSErr, 15 ; IScriptError::Clear() ; エラー表示 rr_cmd_error s } return #endif ; ----- スクリプトエンジンから変数の値を取得 ---------------------------------- #define global accgetvar(%1,%2,%3=NONE@Lollipop) \ RR_CMDNAME("accgetvar") RR_CHKVAR(%1) accgetvar_ %1,%2,%3 #define global accget_(%1,%2,%3=NONE@Lollipop) \ accgetvar_ varPrm1@Lollipop,%2,%3:varget_ %1,varPrm1@Lollipop,1 #define global accget(%1,%2,%3=NONE@Lollipop) \ RR_CMDNAME("accget") accget_ %1,%2,%3 #deffunc accgetvar_ val, str, int mref p1, 16 ; VARIANT 変数 mref p2, 33 mref p3, 2 ppv = pSCtrl if p3 == 1 { ppv = pSCtrlVB } if p3 == 2 { ppv = pSCtrlJ } s = p2 bstrset_ bstrv, s prm = bstrv, p1 icall_ ppv, 27, prm, 2 ; IScriptControl::Eval() bstrfree_ bstrv return ; ----- スクリプトの変数に値を代入 -------------------------------------------- #define global accsetvar(%1,%2,%3=NONE@Lollipop) \ RR_CMDNAME("accsetvar") RR_CHKVAR(%2) accsetvar_ %1,%2,%3 #define global accset_(%1,%2,%3=NONE@Lollipop,%4=NONE@Lollipop) \ varset_ varPrm1@Lollipop,%2,%3:accsetvar_ %1,varPrm1@Lollipop,%4:varclear_ varPrm1@Lollipop #define global accset(%1,%2,%3=NONE@Lollipop,%4=NONE@Lollipop) \ RR_CMDNAME("accset") accset_ %1,%2,%3,%4 #define global accset_s_(%1,%2,%3=NONE@Lollipop,%4=NONE@Lollipop) \ varset_s_ varPrm1@Lollipop,%2,%3:accsetvar_ %1,varPrm1@Lollipop,%4:varclear_ varPrm1@Lollipop #define global accset_s(%1,%2,%3=NONE@Lollipop,%4=NONE@Lollipop) \ RR_CMDNAME("accset_s") accset_s_ %1,%2,%3,%4 #define global accset_n_(%1,%2,%3=NONE@Lollipop,%4=NONE@Lollipop) \ varset_n_ varPrm1@Lollipop,%2,%3:accsetvar_ %1,varPrm1@Lollipop,%4:varclear_ varPrm1@Lollipop #define global accset_n(%1,%2,%3=NONE@Lollipop,%4=NONE@Lollipop) \ RR_CMDNAME("accset_n") accset_n_ %1,%2,%3,%4 #deffunc accsetvar_ str, val, int mref p1, 32 mref p2, 17 ; VARIANT mref p3, 2 if semv < 5 { return } ; スクリプトエンジンのバージョンチェック s1 = p1 ; 変数名の退避 ppv = pSCtrl if p3 == 1 { ppv = pSCtrlVB } if p3 == 2 { ppv = pSCtrlJ } dispParams = p2 prm = dispid, Null, DISPATCH_PROPERTYPUT, pdispParams, Null, Null, Null icall_ bridge, 8, prm, 7 ; IDispatchEx::InvokeEx() if ppv == pSCtrlVB { ; VBScript vbs_ s1 + " = [_bridge].Value" } else { ; JScript js_ s1 + " = _bridge.Value;" ; VBScript の _bridge オブジェクトにグローバルアクセス } return ; ----- スクリプトにグローバルオブジェクトを追加 ------------------------------ #define global accaddobj(%1,%2,%3=NONE@Lollipop) \ RR_CMDNAME("accaddobj") RR_CHKIPTR(%2) accaddobj_ %1,%2,%3 #deffunc accaddobj_ str, int, int mref p1, 32 mref p2, 1 mref p3, 2 ppv = pSCtrl if p3 == 1 { ppv = pSCtrlVB } if p3 == 2 { ppv = pSCtrlJ } bstrset_ bstrv, p1 prm = bstrv, p2, 0xFFFF icall_ ppv, 24, prm, 3 ; IScriptControl::AddObject() bstrfree_ bstrv return ; ----- デフォルトのスクリプトエンジンを設定 ---------------------------------- #deffunc accengine int mref p1 if p1 == 1 : dup pSCtrl, pSCtrlVB if p1 == 2 : dup pSCtrl, pSCtrlJ return ; ----- 終了処理 -------------------------------------------------------------- #define global accfree NONE@Lollipop ; 何もしない (明示的な実行を無視) #deffunc accfree_ onexit vbs_ "Set [_bridge] = Nothing" ; VBscript release_ bridge ; HSP icall_ pSCtrlVB, 25 ; IScriptControl::Reset() icall_ pSCtrlJ, 25 ; IScriptControl::Reset() release_ pSErrJ release_ pSErrVB release_ pSCtrlJ release_ pSCtrlVB return #global ; ============================================================================= #module "AccX2" ; ----- AccX モジュールの初期化 2 ----------------------------------------- #deffunc _init_module_AccX2 dim v, 16 dup pdispid, v.1 ; DISPID のポインタ dup bstrv, v.2 ; BSTR 用変数 s@AccX = {" Class [_MyClass] Private data Public Property Let Value(arg) data = arg End Property Public Property Get Value Value = data End Property End Class Dim [_bridge] Set [_bridge] = New [_MyClass] "} vbscript_ s@AccX accget_ bridge@AccX, "[_bridge]",0 s@AccX = "Value" bstrset_ bstrv, s@AccX rr_getptr pdispid, dispid@AccX prm = bstrv, 0, pdispid icall_ bridge@AccX, 7, prm, 3 ; IDispatchEx::GetDispID() bstrfree_ bstrv return ; ----- 複数行文字列指定における特殊エスケープ -------------------------------- #define global accstresc(%1) \ RR_CMDNAME("accstresc") accstresc_ %1 #deffunc accstresc_ val mref p1, 24 varset_ var1@AccX, p1, VT_BSTR dispParams@AccX = var1@AccX prm = dispid@AccX, Null@AccX, DISPATCH_PROPERTYPUT@AccX, pdispParams@AccX, Null@AccX, Null@AccX, Null@AccX icall_ bridge@AccX, 8, prm, 7 ; IDispatchEx::InvokeEx() varclear_ var1@AccX ; VARIANTARG のクリア accget_ p1, "_bridge.Value.replace(/';'/g, ';').replace(/':'/g, ':').replace(/'\'/g, \"'\")", 2 return #global ; ----------------------------------------------------------------------------- _init_module_AccX accget_ semv@AccX, "ScriptEngineMajorVersion" if (semv@AccX >= 5) { _init_module_AccX2 } #endif ; DEFINE_LOLLIPOP_ACCX ; ============================================================================= ; NOTES by RiffRaff ; ============================================================================= ; ; ■ 終了処理 ; ; accxfree ; ; ------------------------------------------------------------------------- ; ; Script Control を解放して AccX の終了処理を行います。 ; ; ------------------------------------------------------------------------- ; ; ※ AccX の終了処理はHSP のクリーンアップ機能により実行されますので通常 ; 意識する必要はありません。 ; ; (現在ではこの命令は何も行ないません。クリーンアップは終了時に自動的 ; に行なわれます。 by ちょくと) ; ; ; ■ 変数の宣言について ; ; VBScript と JScript で同一の変数名を使用する場合、それぞれのスクリプト ; 空間で変数が宣言されない限りは両者からアクセス可能なグローバルな変数と ; して扱われます。通常、変数の宣言は Dim ステートメント (VBScript) や var ; ステートメント (JScript) を用いて明示的に行いますが、両スクリプト空間に ; おいて一度も使用されていない変数に代入が行われたときにも暗黙の宣言が行 ; われます。以下は何れも変数 a がグローバル変数となる例です。 ; ; vbs "Dim a" ; 明示的な宣言 ; js "a = 3;" ; 宣言なしで使用 ; ; vbs "a = 5" ; 代入による暗黙の宣言 ; js "b = a;" ; 宣言なしで使用 ; ; js "var a = 3;" ; 明示的な宣言 ; vbs "a = 1" ; 宣言なしで使用 ; ; js "a = 3;" ; 代入による暗黙の宣言 ; vbs "b = a" ; 宣言なしで使用 ; ; 同一変数名であってもスクリプト空間ごとに異なるデータを保持したい場合は ; それぞれのスクリプト空間で変数の宣言を行いローカル変数とします。 ; ; vbs "Dim a" ; 明示的な宣言 ; js "var a;" ; 明示的な宣言 ; ; vbs "a = 5" ; 代入による暗黙の宣言 ; js "var a = 1;" ; 明示的な宣言 ; ; js "var a = 3;" ; 明示的な宣言 ; vbs "Dim a" ; 明示的な宣言 ; ; js "a = 3;" ; 代入による暗黙の宣言 ; vbs "Dim a" ; 明示的な宣言 ; ; つまり一方で既に宣言されている変数をもう一方が宣言をしないで使用した場 ; 合はグローバル変数となり、明示的に宣言した場合はローカル変数となります。 ; つまり変数は先に宣言されたスクリプト空間のものであり、後から使用するス ; クリプト空間では単にその変数にリンクしているだけと考えることができます。 ; 自身のスクリプト空間に変数を存在させるには変数の宣言が必要になるという ; ことです。 ; ; ; ■ 関数の定義について ; ; 基本的な考え方は変数の宣言と同様です。一方のスクリプト空間で定義された ; 関数はもう一方のスクリプト空間において同一名の関数の定義や変数の宣言が ; 行われていない限りグローバル関数として呼び出すことができます ; ; ; ■ AccX と HTML ; ; AccX における VBScript と JScript の関係は HTML ドキュメント上で動作す ; る VBScript と JScript の関係に非常によく似ています。例えば前述の変数の ; 宣言や関数の定義についても同様の解釈が行われるようです 。 ; ; (1) AccX の場合 ; ; vbs {" ; Dim a ; a = 5 ; Function Popup(msg) ; MsgBox msg ; End Function ; "} ; js {" ; var a; ; a = "Hot Soup Editor"; ; "} ; vbs {" ; Popup a ; "} ; js {" ; Popup(a); ; "} ; ; (2) HTML の場合 ; ; ; ; ; ; ; このように比較してみるとスクリプトの記述方法はほとんど同じであることが ; わかります。AccX ではスクリプト実行命令を使い HTML では SCRIPT タグを ; 使うだけの違いです。ですから AccX の概念は HTML でスクリプトを記述した ; ことがある方なら簡単に理解していただけるでしょう。仮にそうでない方も、 ; いつでも HTML に応用できるのですから覚えておいて損はありません。 ; ; ; ■ 効率的なスクリプトの記述方法 ; ; 複数のステートメントを連続して実行する場合、1 ステートメント毎にスクリ ; プト実行命令を呼び出すような記述をする方もいると思います。 ; ; vbs "Dim a, b" ; vbs "a = 2000" ; vbs "b = \"Hot Soup Editor\"" ; ; js "var a, b;" ; js "a = 2000;" ; js "b = 'Hot Soup Editor';" ; ; 文法的に間違いはありませんが、このような書き方をした場合、スクリプト実 ; 行命令を呼び出すための処理時間が全体の処理時間に少なからず影響してきま ; す。ですから HSP に制御を戻す必要が無い限りはスクリプトをまとめて実行す ; るべきです。スクリプト実行命令を呼び出す回数を減らすことで全体の処理速 ; 度を向上させることができます。複数のステートメントをまとめて実行するに ; は各スクリプト言語のマルチステートメントを利用する方法と HSP の "文字列 ; 複数行指定" を利用する方法があります。まずマルチステートメントを利用し ; た例を紹介します。 ; ; vbs "Dim a, b: a = 2000: b = \"Hot Soup Editor\"" ; ; js "var a, b; a = 2000; b = 'Hot Soup Editor';" ; ; VBScript では ":" (コロン)、JScript では ";" (セミコロン) を使って各ス ; テートメントを連結します。ただしあまり長くなると見づらくなるので注意し ; てください。作者としては次に紹介する "文字列複数行指定" をお勧めします。 ; 現状では幾つかの問題点もありますが非常にすっきりとしたスクリプトが書け ; ることが利点です。 ; ; vbs {" ; Dim a, b ; a = 2000 ; b = "Hot Soup Editor" ; "} ; ; js {" ; var a, b; ; a = 2000; ; b = "Hot Soup Editor"; ; "} ; ; スクリプトのサイズが 255 バイトを超える場合は変数を経由する必要がありま ; すから vbscript 命令や jscript 命令を使って以下のように記述します。 ; ; dim s, 1024 ; s = {" ; Dim a, b ; a = 2000 ; b = "Hot Soup Editor" ; "} ; vbscript s ; ; dim s, 1024 ; s = {" ; var a, b; ; a = 2000; ; b = "Hot Soup Editor"; ; "} ; jscript s ; ; "文字列複数行指定" の最大の利点は各言語のスクリプトコードとほぼ同じ記述 ; 方法が出来るという点にあります。しかし完全に同じではありません。これは ; HSP の "文字列複数行指定" に注意しなければならない仕様 (私はバグだと思 ; います) があるためです。私自身が調べた範囲では {" と "} に囲まれた行に ; おいても通常のスクリプト行と同じパース (解釈) が行われてしまうようです。 ; 以下はその一部です。 ; ; (a) ";" (セミコロン) 以降はコメント扱いとなる ; (b) ":" (コロン) は改行扱いとなる ; (c) "'" (シングルクォート) で挟まれた文字列は先頭文字だけが返される ; (d) 「"」 (ダブルクォート) で挟まれた文字列は (a)〜(c) が適用されない ; ; ですから実際は上記の JScript のコードにおいてステートメントの終わりに記 ; 述されている ";" は JScript エンジンに渡される前に HSP 側でコメント扱い ; となってしまいます。では何故意味の無い ";" を記述しているかといいますと ; JScript が ";" を用いてステートメントの終わりを明示的に記述することを推 ; 奨しているため "文字列複数行指定" の仕様が修正された場合に備えてのこと ; です。現段階では ";" を記述すること自体で直接的な問題は発生しません。唯 ; 一の欠点は ";" を使ったマルチステートメントが記述できないということだけ ; です (通常の文字列指定では問題ありません)。同様に VBScript のコードにお ; いてもマルチステートメント記号の ":" は改行と解釈されてしまいます。ただ ; しスクリプトが改行するだけなので偶然にも正常に動作します。 ; ; vbs {" ; Dim a, b: a = 2000 ' 正常に動作 ; b = "Hot Soup Editor" ; "} ; ; js {" ; var a, b; a = 2000; // a = 2000; はコメント扱い ; b = "Hot Soup Editor"; ; "} ; ; (c) でも書きましたが JScript の "複数行指定" では文字列を "'" で囲むこ ; とができなくなる点にも注意してください ; ; js {" ; a = 'Hot Soup Editor'; // × ; b = "Hot Soup Editor"; // ○ ; "} ; ; ; ■ スクリプトのコメントについて ; ; コメントには HSP のコメント記号である ";" と各スクリプト言語のコメント ; 記号の両方を用いることができます。前者は HSP がコメントとして認識するの ; でスクリプトエンジンには文字列は渡されません。後者は HSP ではコメントと ; 解釈されないので文字列はスクリプトエンジンに渡されます。コメントの解釈 ; は各スクリプトエンジンにより行われます。 ; ; vbs {" ; Dim a, b ; a = 1 ; これは HSP によりコメント化されます ; b = 2 ' これは VBScript によりコメント化されます ; "} ; ; js {" ; var a, b; ; a = 1; ; これは HSP によりコメント化されます ; b = 2; // 現在はこれも HSP によりコメント化されます ; "} ; ; 作者としては各スクリプト言語のコメント記号を使用することをお勧めします。 ; HSP のコメント記号では "複数行指定" の仕様変更があった場合にスクリプト ; の書き直しを余儀なくされます。 ; ; ; ■ ローカル変数やローカル関数へのアクセス ; ; (1) 変数や関数のローカル化 ; ; 前述しましたがそれぞれのスクリプト空間で変数の宣言を行うと変数はローカ ; ル化します。 ; ; vbs "Dim a: a = 256" ; js "var a = 'telephone';" ; ; retval s1, "a", 1 ; retval s2, "a", 2 ; ; mes s1 ; mes s2 ; ; 変数 a のデータが互いに干渉し合わないことがお分かりになると思います。こ ; れは関数についても全く同様です。 ; ; vbs {" ; Dim a ; Function func ; func = 256 ; End Function ; a = func ; "} ; ; js {" ; var a; ; function func() { ; return("telephone"); ; } ; a = func(); ; "} ; ; retval s1, "a", 1 ; retval s2, "a", 2 ; ; mes s1 ; mes s2 ; ; ; (2) ローカルな変数や関数への相互アクセス ; ; 変数や関数は一旦ローカル化させてしまうと相互にアクセスすることは出来な ; くなります。敢えてローカル化した変数や関数に再びアクセスする必要性が生 ; じるかはわかりませんが AccX ではこのような場合でも相手のスクリプト空間 ; のローカル変数やローカル関数にアクセスする機能を実装しています。前者は ; 組み込み関数、後者は組み込みオブジェクトという形で提供されます。 ; ; 他方のローカル変数にアクセスするには VBScript では jsval 関数、JScript ; では vbsval 関数を使います。vbsval 関数では引数に VBScript 空間で使用さ ; れている変数名を指定します。反対に jsval 関数では引数に JScript 空間で ; 使用されている変数名を指定します。 ; ; vbs {" ; Dim a, b ; a = 256 ; "} ; ; js {" ; var x, y; ; x = "telephone"; ; "} ; ; vbs "b = jsval(\"x\")" ; js "y = vbsval('a');" ; ; retval s1, "b", 1 ; retval s2, "y", 2 ; ; mes s1 ; mes s2 ; ; 他方のローカル関数にアクセスするには VBScript では jsfunc オブジェクト、 ; JScript では vbsfunc オブジェクトを使います。これらのオブジェクトは自身 ; のスクリプト空間で定義されたすべての関数をメンバとして持っています。基 ; 本的には組み込みオブジェクトのメソッドとして呼び出すだけであり、引数の ; 指定なども「関数」と同様に行うことが出来ます。ただし jsfunc オブジェク ; トを使う場合、一つだけ注意点があります。通常 VBScript では引数のない関 ; 数やメソッドを呼び出すときには引数を括る括弧を省略しますが jsfunc オブ ; ジェクトではメソッド名の後に必ず () が必要になります。これを省略してメ ; ソッド名だけで呼び出すと... (興味のある方は試してくださいね)。 ; ; vbs {" ; Dim a ; Function func(arg) ; func = arg * 100 ; End Function ; "} ; ; js {" ; var a; ; function func() { ; return("telephone"); ; } ; "} ; ; vbs "a = jsfunc.func()" ; 引数がなくても () が必要! ; js "a = vbsfunc.func(256);" ; ; retval s1, "a", 1 ; retval s2, "a", 2 ; ; mes s1 ; mes s2 ; ; ; ■ その他の注意事項 ; ; (1) VBScript の For...Each ステートメントにおける制限事項 ; ; AccX では変数や関数の共用を実現するために VBScript 空間と JScript 空間 ; が特殊な位置関係にあります。これは HTML で VBScript と JScript を併用し ; たときの関係と同様であることは前述した通りです。変数や関数がグローバル ; になるかローカルになるかはどのように宣言または定義するかによって決まり ; ますが、以下のよう特殊なケースもありますす。 ; ; js "var i = 10;" ; vbs {" ; For i = 1 To 5 ; MsgBox i ; Next ; "} ; ; 上記のスクリプトを実行するとエラーが発生します。For...Next ステートメン ; トではカウンタに使用する変数に制限があるようです (VBScript のヘルプでは ; この変数に「ユーザ定義型要素は指定できない」と書かれていますが、これが ; 関係しているのでしょうか)。次のように書き換えることでスクリプトは正常に ; 動作するようになります。 ; ; js {" ; var i = 10; ' 暗黙の宣言 ; "} ; vbs {" ; Dim i ' 明示的に宣言する ; For i = 1 To 5 ; MsgBox i ; Next ; "} ; ; vbs "i = 0" ' VBScript 側で先に宣言しておく ; js "i = 10;" ; vbs {" ; For i = 1 To 5 ; MsgBox i ; Next ; "} ; ; つまりカウンタに使用する変数は VBScript 側で先に宣言 (明示的な宣言、暗 ; 黙の宣言を問わず) しているか、既に JScript で使用されている変数であれば ; 明示的に宣言を行いローカル変数とする必要があります。言い換えれば変数が ; リンクではなく VBScript 空間に存在していなければならないということにな ; ります。またこれは HTML 上でも同様の現象が発生しますから AccX 側の問題 ; ではなくVBScript 固有の仕様と言えるでしょう (JScript の for ステートメ ; ントではこのような問題はありません)。 ; ; ; ; ; ; (2) JScript の for ステートメントにおける記述制限 ; ; JScript の for ステートメントでは VBScript の For...Each ステートメント ; のような変数制限はないものの構文そのものに ";" を使用する必要性が出てく ; るため "文字列複数行指定" のときに記述できないという制限が発生します。 ; ; js {" ; for (i=0; i<5; i++) { ; a = i * 2; ; b = i * 3; ; } ; "} ; ; この場合、i=0 の後に続く ";" が以降をコメント化してしまいます。これらの ; 引数は ";" でつなぐ必要があるため省略することは不可能です。for ステート ; メント内の処理が短いのであれば 1行にまとめて指定することでこれを回避し ; ます。 ; ; js "for (i=0; i<5; i++) { a = i * 2; b = i * 3; }" ; ; 処理内容が長い場合は文字列変数を経由するしかありません。 ; ; sdim s, 1024 ; s = "for (i=0; i<5; i++) { \n" ; s += " a = i * 2; \n" ; s += " b = i * 3; \n" ; s += "} \n" ; jscript s ; ; for ステートメントでは閉じカッコまでが一つのステートメントですので以下 ; のように記述することは出来ないことに注意してください。 ; ; js "for (i=0; i<5; i++) {" ; js " // 処理コード" ; js "}" ; ; 以下のような指定方法を行えば強引に "文字列複数行指定" で実行することが ; 出来ますが今後の互換性の問題を考えると避けておいたほうが無難です。これ ; はユーザ定義命令と同一行にある文字列は通常のパースが行われることを逆手 ; に取った方法です。 ; ; js {"for (i=0; i<5; i++) { ; a = i * 2; ; b = i * 3; ; } ; "} ; ; CLSID_VBScript "{B54F3741-5B07-11cf-A4B0-00AA004A55E8}" ; CLSID_JScript "{f414c260-6ac0-11cf-b6d1-00aa00bbbb58}"