(仮称)十進BASIC(ver.5.3.5)では,OLEオブジェクトをFull BASICのモジュールに対応させて利用する。
次の条件を満たせば,ActiveXなどのOLEコントロール(OCX)の利用も可能。
非表示(親ウィンドウ不要)
ディスパッチインターフェースに対応している
BASICから直接利用するのが難しいOCXは,自作DLLを使うを参照して,Delphi,VBなどを利用してAPIに変換するDLLを作成してください。
メソッドは,モジュールの外部手続きに割り当てる。手続き名は任意。
結果を返すメソッドは外部関数に割り当て,external function行とend function行の間にOLE METHOD文を書く。
結果を返さないメソッドは外部副プログラムに割り当て,external sub行とend sub行の間にOLE METHOD文を書く。
OLE METHOD文の引数には,引用符で括ってメソッド名を書く。
手続きの引数の個数と型(数値と文字列の別)は,割り当てるメソッドのそれと一致させる。
プロパテイーの設定は外部副プログラムに割り当てる。external sub行とend sub行の間にOLE PROPERTYPUT文を書く。その引数には,引用符で括ってプロパティ名を書く。副プログラムの引数が設定すべき値になる。
プロパティーの読み出しは,外部関数に割り当てる。external function行とend function行の間にOLE PROPERTYGET文を書く。その引数には,引用符で括ってプロパティ名を書く。
真偽値は,数値で代用する。OLEでは,真は-1,偽は0と定義されている。
メソッド名,プロパティー名は翻訳時に検査する。引数の型と個数の誤りは実行時に検出される。
(Note)複素数には対応していない。その他,いくつか対応できないデータ型がある。
値を返すメソッドで引数として書いた変数の値を書き換えるものには対応していない。
配列引数には対応していない。
このOCXの説明書にはProgIDが明示されていないので,OCXファイル名でレジストリ内を検索して探す(キー値がProgIDのエントリーにProgIDが書いてある)。
100 DECLARE EXTERNAL FUNCTION Music.MusicPlay$ 110 PRINT Music.MusicPlay$("E04 U04 P04 G02 ",0,2400) 120 PRINT Music.MusicPlay$("G04 P04 U04 E02 ",0,1600) 130 END 140 150 MODULE Music 160 PUBLIC FUNCTION MusicPlay$ 170 OLE CreateObject "MusicPlayCtrl.Music" 180 EXTERNAL FUNCTION MusicPlay$(s$,Handle,Long) 190 OLE METHOD "MusicPlay" 200 END FUNCTION 210 END MODULEモジュールで定義された外部関数をモジュール外から使うために160行に示すようなPUBLIC FUNCTION文を書く。
戻り値を持つメソッドでも,戻り値が不要なら副プログラムに割り当ててもよい。
100 DECLARE EXTERNAL SUB Music.MusicPlay 110 CALL Music.MusicPlay("E04 U04 P04 G02 ",0,2400) 120 CALL Music.MusicPlay("G04 P04 U04 E02 ",0,1600) 130 END 140 150 MODULE Music 160 PUBLIC SUB MusicPlay 170 OLE CreateObject "MusicPlayCtrl.Music" 180 EXTERNAL SUB MusicPlay(s$,Handle,Long) 190 OLE METHOD "MusicPlay" 200 END SUB 210 END MODULEモジュールで定義された外部手続きをモジュール外から使うために160行に示すようなPUBLIC SUB文を書く。
プロパティの設定は,220行に示すようにモジュールの外部副プログラムに割り当てる。
100 DECLARE EXTERNAL FUNCTION Calc.calc$ 110 DECLARE EXTERNAL SUB Calc.SetFormat 120 CALL SetFormat("#####.##") 130 PRINT calc$("12+3") 140 END 150 MODULE Calc 160 OLE CREATEOBJECT "Hiro_Calc.HiroCalc" 170 PUBLIC FUNCTION calc$ 180 PUBLIC SUB SetFormat 190 EXTERNAL FUNCTION calc$(s$) 200 OLE METHOD "calc" 210 END FUNCTION 220 EXTERNAL SUB SetFormat(s$) 230 OLE PROPERTYPUT "CalcFormat" 240 END SUB 250 END MODULEDECLARE EXTERNAL文で宣言した識別名は,「モジュール名.」を省いて書くことができる。
100 DECLARE EXTERNAL SUB ATLDos.Start, ATLDos.End, ATLDos.SetSync 110 DECLARE EXTERNAL FUNCTION ATLDos.SendCommand$, ATLDos.Sync 120 CALL Start 130 CALL SetSync(-1) ! 同期モードに設定 140 PRINT SendCommand$("ECHO OFF") 150 PRINT SendCommand$("DIR") 180 PRINT "Sync=";Sync ! プロパティ読み出しの実行例 190 CALL End 200 END 210 220 MODULE ATLDos 230 OLE CREATEOBJECT "ATLDos.CmdExec" 240 PUBLIC FUNCTION SendCommand$, Sync 250 PUBLIC SUB Start, End, SetSync 260 270 EXTERNAL SUB Start 280 OLE METHOD "Start" 290 END SUB 300 310 EXTERNAL SUB END 320 OLE METHOD "End" 330 END SUB 340 350 EXTERNAL FUNCTION SendCommand$(s$) 360 OLE METHOD "SendCommand" 370 END FUNCTION 380 390 EXTERNAL SUB SetSync(n) 400 OLE PropertyPut "Sync" 410 END SUB 420 470 EXTERNAL FUNCTION Sync 480 OLE PropertyGet "Sync" 490 END FUNCTION 500 510 END MODULEFull BASICにはプロパティという概念がないので,プロパティへの値の設定,プロパティの値の読み出しは,それぞれ副プログラム,関数の形で利用する。
Full BASICは真偽値をデータとして利用することができない言語であるが,マイクロソフト社のBool型,Boolean型は数値の型の一部なので,-1(あるいは非ゼロ)を真,0を偽として扱えば数値で代用できる。
例4 MusicPlayctrl.ocx を非同期で使う
100 DECLARE EXTERNAL SUB Music.MusicPlay 110 CALL MusicPlay("E04 U04 P04 G02 ",0,2400,-1) 120 WAIT DELAY 3 130 CALL MusicPlay("G04 P04 U04 E02 ",0,1400,-1) 140 PAUSE "終了したらEnterキーを押してください" 150 END 160 170 MODULE Music 180 PUBLIC SUB MusicPlay 190 OLE CreateObject "MusicPlayCtrl.Music" 200 EXTERNAL SUB MusicPlay(s$,Handle,Long,Sync) 210 OLE METHOD "MusicPlay" 220 END SUB 230 END MODULE
CreateObjectが見つからない場合は,レジストリ内を検策して探す。
レジストリエディタは, スタートメニューの「ファイル名を指定して実行」に regedit と入力すれば起動する。
レジストリの編集メニューの検索で,OCXのファイル名を入力して,データの欄にチェックを入れて検索する。
レジストリ内では,HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\以下にProgIDが登録されている。
レジストリを変更してしまうとWindowsの動作に支障がでるので,誤って値を書き換えてしまわないように注意。
ProgIDがないOLEサーバは,1350行に示すようにGUIDを指定して使う。
オブジェクトを動的にモジュールに割り当てるときはOLE CREATEOBJECTの代わりにOLE ASSIGNを使う。
値がオブジェクトであるプロパティの取得を数値関数に割り当てると,この関数を実行したとき,内部的にオブジェクトを一つ作成し,それを参照するための数値を返す。
OLE ASSIGN文の引数には,その値(すなわち,プロパティから取得したオブジェクトへの参照を意味する数値)を指定する。
OLE ASSIGN文は実行文なので,モジュール内の外部手続きで実行することにしてもよい。
1000 DECLARE EXTERNAL FUNCTION TLI.CoClasses, TLI.CoClass 1010 DECLARE EXTERNAL FUNCTION Collection.Count 1020 DECLARE EXTERNAL FUNCTION CoClass.DefaultInterface,CoClass.DefaultEventInterface,CoClass.Name$ 1030 DECLARE EXTERNAL FUNCTION Interface.members,Interface.Name$,Interface.GUID$ 1040 DECLARE EXTERNAL FUNCTION Member.Name$,Member.MemberID 1050 DECLARE EXTERNAL SUB TLI.LoadFromFile, TLI.LoadRegTypeLib 1060 DECLARE EXTERNAL SUB CoClass.SetCoClass 1070 DECLARE EXTERNAL SUB Interface.SetIntf 1080 DECLARE EXTERNAL SUB Member.SetMember 1090 DECLARE NUMERIC i,j 1100 DECLARE STRING FName$ 1110 1120 FILE GetName FName$ 1130 CALL TLI.LoadFromFile(FName$) 1150 FOR i=1 TO Collection.Count(TLI.CoClasses) 1160 CALL CoClass.SetCoClass(TLI.CoClass(i)) 1170 CALL Interface.SetIntf(CoClass.DefaultEventInterface) 1180 PRINT "*DefaultEventInterface*" 1190 WHEN EXCEPTION IN 1200 PRINT CoClass.Name$,Interface.NAME$,Interface.GUID$ 1210 PRINT "** Member **" 1220 FOR j=1 TO Collection.Count(Interface.members) 1230 CALL Member.SetMember(Interface.Member(j)) 1240 PRINT member.NAME$, member.MemberID 1250 NEXT j 1260 USE 1270 PRINT CoClass.name$;" has no DefaultEventInterface" 1280 END WHEN 1290 NEXT i 1300 END 1310 1320 MODULE TLI 1330 PUBLIC FUNCTION CoClasses,CoClass 1340 PUBLIC SUB LoadFromFile, LoadRegTypeLib 1350 OLE CreateObject "{8B217746-717D-11CE-AB5B-D41203C10000}" 1360 EXTERNAL SUB LoadFromFile(s$) 1370 OLE PropertyPut "ContainingFile" 1380 END SUB 1390 EXTERNAL SUB LoadRegTypeLib(GUID$,ma,mi,LCID) 1400 OLE METHOD "LoadRegTypeLib" 1410 END SUB 1420 EXTERNAL FUNCTION CoClasses 1430 OLE PropertyGet "CoClasses" 1440 END FUNCTION 1450 EXTERNAL FUNCTION CoClass(n) 1460 OLE propertyGet "CoClasses" 1470 END FUNCTION 1480 END MODULE 1490 1500 MODULE CoClass 1510 PUBLIC SUB SetCoClass 1520 PUBLIC FUNCTION DefaultInterface,DefaultEventInterface,Name$ 1530 EXTERNAL SUB SetCoClass(n) 1540 OLE ASSIGN n 1550 END SUB 1560 EXTERNAL FUNCTION DefaultInterface 1570 OLE PROPERTYGET "DefaultInterface" 1580 END FUNCTION 1590 EXTERNAL FUNCTION DefaultEventInterface 1600 OLE PROPERTYGET "DefaultEventInterface" 1610 END FUNCTION 1620 EXTERNAL FUNCTION name$ 1630 OLE PROPERTYGET "Name" 1640 END FUNCTION 1650 END MODULE 1660 1670 MODULE Interface 1680 PUBLIC FUNCTION member,Members,Name$,GUID$ 1690 PUBLIC SUB SetIntf 1700 EXTERNAL SUB SetIntf(n) 1710 OLE ASSIGN n 1720 END SUB 1730 EXTERNAL FUNCTION Name$ 1740 OLE PropertyGet "Name" 1750 END FUNCTION 1760 EXTERNAL FUNCTION GUID$ 1770 OLE PropertyGet "GUID" 1780 END FUNCTION 1790 EXTERNAL FUNCTION member(n) 1800 OLE PROPERTYGET "Members" 1810 END FUNCTION 1820 EXTERNAL FUNCTION members 1830 OLE PROPERTYGET "members" 1840 END FUNCTION 1850 END MODULE 1860 1870 MODULE member 1880 PUBLIC FUNCTION Name$,MemberID 1890 PUBLIC SUB setmember 1900 EXTERNAL SUB setmember(n) 1910 OLE ASSIGN n 1920 END SUB 1930 EXTERNAL FUNCTION Name$ 1940 OLE PropertyGet "Name" 1950 END FUNCTION 1960 EXTERNAL FUNCTION MemberID 1970 OLE Propertyget "MemberID" 1980 END FUNCTION 1990 END MODULE 2000 2010 MODULE Collection 2020 ! Countプロパティを持つオブジェクトのCountプロパティを取得する汎用モジュール 2030 PUBLIC FUNCTION Count 2040 SHARE FUNCTION GetCount ! GetCountはモジュール内でのみ使う 2050 EXTERNAL FUNCTION Count(n) 2060 OLE ASSIGN n 2070 LET COUNT=GetCount 2080 END FUNCTION 2090 EXTERNAL FUNCTION GetCount 2100 OLE PROPERTYGET "Count" 2110 END FUNCTION 2120 END MODULE<Note>オブジェクトを取り出すプロパティ取得とOLE ASSIGN文の実行とは一対一に対応しなければならない。
例6 ALTDosを非同期で使う
100 DECLARE EXTERNAL SUB ATLDos.SendCommand,ATLDos.Start, ATLDos.End 110 DECLARE EXTERNAL NUMERIC ATLDos.count 120 CALL ATLDos.Start 130 CALL ATLDos.SendCommand("ECHO OFF") 140 CALL ATLDos.SendCommand("DIR") 150 PAUSE 160 PRINT count; "回呼ばれた" 170 CALL ATLDos.End 180 END 190 200 MODULE ATLDos 210 OLE CREATEOBJECT "ATLDos.CmdExec","{7BD49A5F-DCC2-11D5-86CB-00E0297583A4}" 220 PUBLIC NUMERIC count 230 PUBLIC SUB Start, End, SendCommand 240 LET count=0 250 260 EXTERNAL SUB Start 270 OLE METHOD "Start" 280 END SUB 290 300 EXTERNAL SUB END 310 OLE METHOD "End" 320 END SUB 330 340 EXTERNAL SUB SendCommand(s$) 350 OLE METHOD "SendCommand" 360 END SUB 370 380 EXTERNAL SUB RecvPrompt(s$) ,DispID 1 390 WHEN EXCEPTION IN 400 PRINT s$ 410 LET count=count+1 420 USE 430 440 END WHEN 450 END SUB 460 470 END MODULEOCXから呼ばれる手続きでは,410〜460行に示すように手続き内で例外を処理しておくことが望ましい(十進BASICは未処理の例外があると,呼び出し元に例外を生成すべきことを伝えるが,それ以後は相手しだい)。
<Note>イベント インターフェースのGUIDはWindowsのレジストリから直接に読み取ることはできない。各イベントのDispIDも同様。
したがって,マニュアルに記載がない場合,タイプライブラリを利用することのできるソフト(VC++やDelphiなど)が必要。tlbinf32.dllを入手できれば,(レジストリに登録して)例5のプログラムを実行することで必要な情報は得られる。
なお,見かけ上よく似た文字列がClassID(CLSID),TypeLibを表すためにも用いられるので,混同しないように注意。
たとえば,VB向けのサンプルでobjectに続けて書いてあるGUIDはおそらくTypeLib。
<注意> 複数のスレッドから同時に割り込まれると正常に動作しないので,割り込み元が複数のスレッドに存在するような使い方はしないでください。
SIGNAL シグナル名
シグナル名で識別されるシグナルを発する。
WAIT SIGNAL シグナル名
シグナル名で識別されるシグナルが発せられるまで待機する。
WAIT SIGNAL シグナル名 TIMEOUT 数値式
数値式で指定される時間(秒)が経過するか,またはシグナルを受信するまで待機する。