goo

ファイルハンドルからファイル名を取得

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オブジェクト型変数からオブジェクト型変数を作成します。
表1COMオブジェクト型変数作成命令
命令概要
axobjActiveXコントロールを作成
newcomCOMオブジェクトを作成
querycomインターフェイスを取得
comeventイベント用のインターフェイスを取得
newcom
作成モード:-1
外部関数などから得たインターフェイスポインタからオブジェクト型変数を作成
COM系命令の引数の種類
表2は、各命令で使用できる引数の種類について。oは命令が成功、xは失敗した時。 progidについては、 URLprogid - MSDN を参照。
ProgID記述例
ProgID = "Shell.Explorer.2"
CLSIDは、オブジェクトを作成する時、IIDはインターフェイスを取得する時に使用。CLSIDとIIDは、GUIDでありHSPでは文字列として扱う。また、ole32.dllのProgIDFromCLSIDやCLSIDFromProgIDで、ProgIDとCLSIDは変換可能。
guid文字列記述例
guid = "{00000000-0000-0000-C000-000000000046}"
GUIDについては、 URLGUID - Wikipedia を参照。 #usecomは、IIDとCLSIDまたはIIDからインターフェイス名の定義を行う。
#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
表2各命令に使用できる引数のテスト

ProgIDCLSID
文字列
IID
文字列
#usecom
IIDとCLSID
#usecom
IID
axobjoox
*1
ox
*4
newcomoox
*2
ox
*4
querycomx
*5
x
*3
ooo
comeventx
*5
x
*6
ox
*7
x
*7
newcom
(-1)
oooox
*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
newcom xml1, "Microsoft.XMLDOM"
xml2(0) = xml1
code2.hspは、初期化していないxml2を配列変数として代入しています。実行結果は「#Error 7 配列の要素が無効です」となります。
code3.hsp
newcom xml1, "Microsoft.XMLDOM"
dimtype xml3, 6, 4
xml3(0) = xml1
code3.hspは、dimtypeでxml3をCOMオブジェクト型変数(タイプ6)を要素4個の配列として初期化した後に、代入しています。実行結果は「#Error 39 外部オブジェクトの呼び出しに失敗しました」となります。
code4.hsp
dimtype xml4, 6, 4
newcom xml4(0), "Microsoft.XMLDOM"
newcom xml4(4), "Microsoft.XMLDOM"
code4.hspは、dimtypeで配列を確保した後newcom命令で作成しています。1回目のnewcomは成功します。2回目のnewcomは、確保した以上の要素数を指定していますが自動確保されないのでエラーが発生します。エラー内容は、「#Error 7 配列の要素が無効です」。

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 )