全然更新しないブログ
HSPメモ帳
ファイルハンドルからファイル名を取得
GetNameFromHandle
URLObtaining a File Name From a File Handle
GetNameFromHandle.hsp
#include "kernel32.as" #uselib "psapi.dll" #func global GetMappedFileName "GetMappedFileNameA" int, int, int, int #module #defcfunc GetFileNameFromHandle int hFile hMap = 0 : pMem = 0 sdim szFileName, 260 GetFileSize hFile, 0 : size = stat if ( size == -1 ){ return szFileName } CreateFileMapping hFile, 0, 0x02, 0, 1, 0 : hMap = stat if ( hMap ){ MapViewOfFile hMap, 0x04, 0, 0, 1 : pMem = stat if ( pMem ){ GetCurrentProcess GetMappedFileName stat, pMem, varptr(szFileName), 260 if ( stat ){ sdim szTmp, 512 GetLogicalDriveStrings 511, varptr(szTmp) if ( stat ){ driveLen = 0 : szDrive = " :" : sdim szName, 260 repeat poke szDrive, 0, peek(szTmp, driveLen) if ( szDrive == "" ){ break } QueryDosDevice varptr(szDrive), varptr(szName), 260 if ( stat ){ if ( instr(szFileName, 0, szName ) == 0 ){ lstrlen varptr(szName) nameLen = stat if ( strmid(szFileName, nameLen, 1 ) == "\\" ){ getstr szName, szFileName, nameLen, '\0', 260 szFileName = szDrive + szName break } } } lstrlen varptr(szTmp) + driveLen : driveLen += stat + 1 loop } } UnmapViewOfFile pMem } CloseHandle hMap } return szFileName #global dialog "*", 16 if ( stat == 0 ){ end } fileName = refstr CreateFile fileName, 0x80000000, 1, 0, 3 , 0, 0 hFile = stat if ( hFile != -1 ){ mes GetFileNameFromHandle(hFile) CloseHandle hFile } else { mes "error" }
コメント ( 0 ) | Trackback ( 0 )
COMオブジェクト
COMオブジェクト型変数作成命令
axobjとnewcomは、COMオブジェクトを作成します。querycomとcomeventは、既に存在するCOMオブジェクト型変数からオブジェクト型変数を作成します。
命令 | 概要 |
---|---|
axobj | ActiveXコントロールを作成 |
newcom | COMオブジェクトを作成 |
querycom | インターフェイスを取得 |
comevent | イベント用のインターフェイスを取得 |
newcom 作成モード:-1 | 外部関数などから得たインターフェイスポインタからオブジェクト型変数を作成 |
COM系命令の引数の種類
表2は、各命令で使用できる引数の種類について。oは命令が成功、xは失敗した時。
progidについては、
URLprogid - MSDN を参照。
CLSIDは、オブジェクトを作成する時、IIDはインターフェイスを取得する時に使用。CLSIDとIIDは、GUIDでありHSPでは文字列として扱う。また、ole32.dllのProgIDFromCLSIDやCLSIDFromProgIDで、ProgIDとCLSIDは変換可能。
GUIDについては、
URLGUID - Wikipedia を参照。
#usecomは、IIDとCLSIDまたはIIDからインターフェイス名の定義を行う。
ProgID記述例
ProgID = "Shell.Explorer.2"
guid文字列記述例
guid = "{00000000-0000-0000-C000-000000000046}"
#usecom定義例 - HSP HELPより引用
#define CLSID_ShellLink "{00021401-0000-0000-C000-000000000046}" #define IID_IShellLinkA "{000214EE-0000-0000-C000-000000000046}" #usecom IShellLinkA IID_IShellLinkA CLSID_ShellLink
ProgID | CLSID 文字列 | IID 文字列 | #usecom IIDとCLSID | #usecom IID | |
---|---|---|---|---|---|
axobj | o | o | x *1 | o | x *4 |
newcom | o | o | x *2 | o | x *4 |
querycom | x *5 | x *3 | o | o | o |
comevent | x *5 | x *6 | o | x *7 | x *7 |
newcom (-1) | o | o | o | o | x *4 |
*1 stat:-1
*2 stat:1
*3 stat:0
*4 #Error 30 無効な名前がパラメーターに指定されています
*5 #Error 3 パラメータの値が異常です
*6 #Error 39 外部オブジェクトの呼び出しに失敗しました
*7 #Error 32 関数のパラメーター記述が不正です
?newcom(-1)の*4について。作成モード-1でも、newcomの仕様なのかクラスを登録しないとエラーとなる。とりあえず適当なクラスを指定する場合は、"{}"を指定する。以下参照(4行)。空文字列("")を指定した場合はエラー(30)となる。
無名クラス指定
#include "ole32.as" #include "shell32.as" #define IID_IShellFolder "{000214E6-0000-0000-C000-000000000046}" #usecom IShellFolder IID_IShellFolder "{}" #comfunc ISF_ParseDisplayName 3 int,int,wstr,int,var,int shf = 0 SHGetDesktopFolder varptr(shf) if ( stat == 0 ){ newcom shell, IShellFolder, -1, shf dispName = dirinfo(0x10000) ISF_ParseDisplayName shell, 0, 0, dispName, 0, item, 0 if ( stat == 0 ){ mes "S_OK" CoTaskMemFree item } } stop
COMオブジェクトの破棄
COMオブジェクト型変数の破棄は、delcom命令を使用します。
delcom - HSP HELPより引用 |
---|
delcom命令は、初期化されたCOMオブジェクトの参照カウントを減らし、変数に設定されているインスタンスを無効にします。 通常、生成されたCOMオブジェクトのインスタンスはHSP内部で自動的に破棄されるため、特にdelcom命令で明示的に破棄する必要はありません。 一度破棄されたCOMオブジェクト型の変数は、再度newcom命令により初期化されるまでは使用することができません。 |
COMオブジェクトと参照カウント
code1.hspを実行すると、代入時には参照カウントが増え、delcomで減ることがわかります。
最初のxml1の参照カウントが3になっているのは、おそらく内部でカウントが+2された後にXML_Releaseが呼び出された結果であり、その後-2されているはずなので実際のカウントは1。よって正しい参照カウントは結果から-2したものとなります。また、代入以外でもquerycomやnewcom(3番目の引数に-2を指定)した時もカウント+1されます。
code1.hsp
#define global CLSID_XMLDOMDocument "{F6D90F11-9C73-11D3-B32E-00C04F990BB4}" #define global IID_IXMLDOMDocument "{2933BF81-7B36-11D2-B20E-00C04F983E60}" #usecom global XMLDOMDocument IID_IXMLDOMDocument CLSID_XMLDOMDocument #comfunc global XML_QueryInterface 0 int,int #comfunc global XML_AddRef 1 #comfunc global XML_Release 2 #module #defcfunc GetRef var v XML_AddRef v XML_Release v return stat #global newcom xml1, XMLDOMDocument mes "newcom xml1, XMLDOMDocument" mes "// xml1の参照カウント:" + GetRef(xml1) xml2 = xml1 mes "xml2 = xml1" mes "// xml1の参照カウント:" + GetRef(xml1) mes "// xml2の参照カウント:" + GetRef(xml2) delcom xml2 mes "delcom xml2" mes "// xml1の参照カウント:" + GetRef(xml1) stop
code1.hspの実行結果 |
---|
newcom xml1, XMLDOMDocument // xml1の参照カウント:3 xml2 = xml1 // xml1の参照カウント:4 // xml2の参照カウント:4 delcom xml2 // xml1の参照カウント:3 |
COMオブジェクトと配列
COMオブジェクト型変数を配列へ「=」を使った代入はできない。命令の引数に配列を指定することで代入は可能。しかし、配列要素の自動確保は行われない。下記、テストコード。エラーが出るので注意。
code2.hspは、初期化していないxml2を配列変数として代入しています。実行結果は「#Error 7 配列の要素が無効です」となります。
code3.hspは、dimtypeでxml3をCOMオブジェクト型変数(タイプ6)を要素4個の配列として初期化した後に、代入しています。実行結果は「#Error 39 外部オブジェクトの呼び出しに失敗しました」となります。
code4.hspは、dimtypeで配列を確保した後newcom命令で作成しています。1回目のnewcomは成功します。2回目のnewcomは、確保した以上の要素数を指定していますが自動確保されないのでエラーが発生します。エラー内容は、「#Error 7 配列の要素が無効です」。
COMオブジェクト型変数をモジュール変数として配列を扱う方法。
code5.hspは、エラーを出すことなく自動拡張を可能とした配列の例。
?しかし、(2)のように一度モジュール変数にCOMオブジェクト型変数を代入した後に、その変数を別の変数に代入しようとすると「#Error 1 システムエラーが発生しました」となるので注意。
code2.hsp
newcom xml1, "Microsoft.XMLDOM" xml2(0) = xml1
code3.hsp
newcom xml1, "Microsoft.XMLDOM" dimtype xml3, 6, 4 xml3(0) = xml1
code4.hsp
dimtype xml4, 6, 4 newcom xml4(0), "Microsoft.XMLDOM" newcom xml4(4), "Microsoft.XMLDOM"
COMオブジェクト型変数をモジュール変数として配列を扱う方法。
code5.hspは、エラーを出すことなく自動拡張を可能とした配列の例。
?しかし、(2)のように一度モジュール変数にCOMオブジェクト型変数を代入した後に、その変数を別の変数に代入しようとすると「#Error 1 システムエラーが発生しました」となるので注意。
code5.hsp
#module mod_XML mXML #modinit var v, int c mXML = v // (1) // tmp = mXML // (2) mXML->"LoadXML" "<cnt>" + c + "</cnt>" return #modfunc XMLPrint mes mXML("xml") return #global repeat 4 newcom xmlTmp, "Microsoft.XMLDOM" newmod modXML, mod_XML, xmlTmp, cnt loop xmlTmp = 0 repeat 4 XMLPrint modXML(cnt) loop stop
コメント ( 0 ) | Trackback ( 0 )