スタレビライブ2005年10月11日 23時52分52秒

先日(10/09)日比谷で行われたスタレビライブに いって来た。今年初めてのライブだ。 セットリスト等は、別のサイトを見て頂くとして 感想と気になった点を少し。

ど素人が書くのもおこがましいとは思いますが ライブの完成度・楽しさ・観客に対するサービス というのは相変わらずすばらしく、そこには 何時ものスタレビがあったと思う。 しかし、ライブの迫力というか・よい意味での 期待外しというのか今ひとつもの足りないような 気がした。 また2時間半のライブでは時間的にちょっと 足りない気が・・・(これをスタレビライブ症候群 と勝手にいっていますが・・・)

気になったのは、ライブ中での要さんの発言。 はっきりとは覚えていないのですが、 「このメンバーでの野外のライブは今年が最後」か 「このメンバーでの野外のライブは今年は最後」 のような発言があったこと。 後者の発言であれば、正式な発表はないので なんとも言えないのですが岡崎さんか添田さんの どちらかがサポートを卒業するのかな? 岡崎さん添田さんはいずれサポートを卒業される とは思いますがもう少し今の体制のスタレビを 見ていたいので前者の発言であって欲しいなあ と思います。

VBACollection2005年10月12日 00時28分14秒

Delphiを使ってVBA Collection(IEnumVariant)の実装例です。 インターネットを探しても良い例がなかったので作ってみました。

ポイントは、コレクションのアイテムをTStringListで保持し IEnumVariantインターフェイスを使って操作することです。

以下に例です。

先ずは、コレクションのアイテムの実装から ソース中のTEST_TLBは、Delphiのタイプライブラリエディタが 生成したソースです。 個々のアイテムを操作するインターフェイスの実装です。 DelphiのCom関係のClassから派生したClassを定義します。

unit PVData;

{$WARN SYMBOL_PLATFORM OFF}

interface

uses

 ComObj, ActiveX, TEST_TLB, StdVcl;

type

 TPVData = class(TAutoObject, IPVData)

private

   FTagName : WideString;
   FValue   : Single;
   FStatus  : Integer;
   FEnabled : WordBool;
   FService : Integer;
 protected
   function Get_Enabled: WordBool; safecall;
   function Get_Service: Integer; safecall;
   function Get_Status: Integer; safecall;
   function Get_TagName: WideString; safecall;
   function Get_Value: Single; safecall;
   procedure Set_Enabled(Value: WordBool); safecall;
   procedure Set_Service(Value: Integer); safecall;
   procedure Set_Status(Value: Integer); safecall;
   procedure Set_TagName(const Value: WideString); safecall;
   procedure Set_Value(Value: Single); safecall;
 end;

implementation

uses ComServ;

function TPVData.Get_Enabled: WordBool; begin Result := FEnabled; end;

function TPVData.Get_Service: Integer; begin Result := FService; end;

function TPVData.Get_Status: Integer; begin Result := FStatus; end;

function TPVData.Get_TagName: WideString; begin Result := FTagName; end;

function TPVData.Get_Value: Single; begin Result := FValue; end;

procedure TPVData.Set_Enabled(Value: WordBool); begin FEnabled := Value; end;

procedure TPVData.Set_Service(Value: Integer); begin FService := Value; end;

procedure TPVData.Set_Status(Value: Integer); begin FStatus := Value; end;

procedure TPVData.Set_TagName(const Value: WideString); begin FTagName := Value; end;

procedure TPVData.Set_Value(Value: Single); begin FValue := Value; end;

initialization

 TAutoObjectFactory.Create(ComServer, TPVData, Class_PVData,
   ciMultiInstance, tmApartment);

end.

次にコレクションの実装です。 アイテムがDelphiのクラスであれば、TObjectにキャスト することでTStringListに登録が可能です。 アイテムの操作時はTObjectから所定のインターフェイス (この場合はIPVData)にキャストします。

unit PVList;

{$WARN SYMBOL_PLATFORM OFF}

interface

uses

 //ShareMem,
 ComObj, ActiveX, TEST_TLB, StdVcl,Classes;

type

 TPVList = class(TAutoObject, IPVList, IEnumVARIANT)
 private
 	FPVList : TStringList;
   FIndex  : Integer;
   procedure InitList;
 protected
   {IEnumVARIANT インターフェイス}
   function Clone(out ppenum: IEnumVARIANT): HResult; stdcall;
   function Next(celt: LongWord; var rgvar: OleVariant;
     out pceltFetched: LongWord): HResult; stdcall;
   function Reset: HResult; stdcall;
   function Skip(celt: LongWord): HResult; stdcall;
   {IPVLIST インターフェイス}
   function _NewEnum: IUnknown; safecall;
   function Item(Index: OleVariant): IPVData; safecall;
   function Count: Integer; safecall;
   function Add(const KeyStr: WideString): IPVData; safecall;
   procedure Remove(Index: OleVariant); safecall;
   procedure RemoveAll; safecall;
 public
 	//constructor Create;
   procedure AfterConstruction; override;
   procedure BeforeDestruction; override;
   //destructor Destroy; override;
 end;

 function GetListIndex(SL : TStrings; Index : OleVariant) : Integer;

implementation

uses ComServ, Variants,

 IniFiles,
 SysUtils,
 PVData, TL2WUTIL,Forms;
 //Forms, TL2WUTIL;

const PVMAX = 64;

 SECTIONNAME = 'PVTAG';

function GetListIndex(SL : TStrings; Index : OleVariant) : Integer; var CheckIdx : Integer; begin Result := -1;

if Assigned(SL) then begin

   CheckIdx := -1;

if VarIsNumeric(Index) then begin

   	CheckIdx := Integer(Index);

end else begin if VarIsStr(Index) then begin CheckIdx := SL.IndexOf(VarToStr(Index)); end; end;

   If (CheckIdx < SL.Count) then begin
   	Result := CheckIdx;
   end;

end; end;

function TPVList.Clone(out ppenum: IEnumVARIANT): HResult; var PVList : TPVList; begin

PVList := TPVList.Create; try

 	ppenum := PVList As IEnumVARIANT;
   Result := S_OK;
 except

Result := S_FALSE;

 end;

end;

function TPVList.Next(celt: LongWord; var rgvar: OleVariant;

 out pceltFetched: LongWord): HResult;

type TVariantList = array[0..0] of Olevariant; var I : LongWord; begin I := 0;

 while (I < celt) and (FIndex < FPVLIST.Count) do begin
   TVariantList(rgvar)[i] := Self.Item(Integer(I) + FIndex);
   Inc(I);
   Inc(FIndex);
 end;

if (@pceltFetched <> nil) then begin

 	pceltFetched := I;

end;

if (I = celt) then begin Result := S_OK; end else begin Result := S_FALSE; end;

end;

function TPVList.Reset: HResult; begin FIndex := 0;

 Result := S_OK

end;

function TPVList.Skip(celt: LongWord): HResult; begin

if FIndex + Integer(celt = FPVLIST.Count) then begin

 	Inc(FIndex,celt);

Result := S_OK; end else begin FIndex := FPVLIST.Count; Result := S_FALSE;

 end;

end;

function TPVList._NewEnum: IUnknown; begin Result := Self As IEnumVariant; end;

function TPVList.Item(Index: OleVariant): IPVData; var ListIndex : Integer; begin

Result := nil; ListIndex := GetListIndex(FPVLIST,Index);

 If ListIndex <> -1 then begin
 	Result := TPVData(FPVLIST.Objects[ListIndex]) As IPVData;
 end;

end;

function TPVList.Count: Integer; begin Result := 0;

 //Result := 4;

if Assigned(FPVLIST) then begin

 	Result := FPVLIST.Count;
 end;

end;

{ constructor TPVList.Create; begin //inherited Create(Comserver.TypeLib,IPVList);

 //inherited Create;

FPVLIST := TStringList.Create; end; }

function TPVList.Add(const KeyStr: WideString): IPVData; var PVData : TPVData;

 Index : Integer;

begin

 //Application.MessageBox(PChar(AnsiString(KeyStr)),'PVAdd',0);

Result := Nil; try

 	PVData := TPVData.Create;

Index := FPVLIST.AddObject(AnsiString(KeyStr),TObject(PVData));

 	//FPVLIST.Objects[Index] := TObject(PVData);
 	Result := PVData As IPVData;
   //AddRefしておくのを忘れずに実施する
   Result._AddRef;
 except
 	;
 end;

end;

procedure TPVList.Remove(Index: OleVariant); var ListIndex : Integer; RmPV : IPVData; begin

ListIndex := TL2WUTIL.GetListIndex(FPVLIST, Index); If ListIndex <> -1 then begin

 	RmPV := TPVData(FPVLIST.Objects[Index]) As IPVData;
   RmPV._Release;
   FPVLIST.Delete(Index);
 end;

end;

procedure TPVList.RemoveAll; var RmPV : IPVData;

 i : Integer;

begin

with FPVLIST do begin

 	For i := 0 to Count -1 do begin
     RmPV := TPVData(Objects[i]) As IPVData;
     RmPV._Release;
     Objects[i] := nil;
   end;
   Clear;

end;

 FPVLIST.Clear;
 

end;

procedure TPVList.InitList; begin

FPVLIST := TStringList.Create;

 //重複を不可(大文字・小文字の区別なしにします。
 FPVLIST.Sorted := true;
 FPVLIST.CaseSensitive := false;
 //重複時は、最初に書いたものを優先とします。
 FPVLIST.Duplicates := dupError;

end;

{destructor TPVList.Destroy; begin

if Assigned(FPVLIST) then begin

 	RemoveAll;
 	FPVLIST.Free;
 end;
 inherited;

end; }

procedure TPVList.AfterConstruction; begin

 inherited;
 FIndex := 0;

InitList; end;

procedure TPVList.BeforeDestruction; begin

 if Assigned(FPVLIST) then begin
 	RemoveAll;
 	FPVLIST.Free;
 end;
 inherited;

end;

initialization

 TAutoObjectFactory.Create(ComServer, TPVList, Class_PVList,
   ciMultiInstance, tmApartment);

end.

[参考文献] Delphi 5 Developer’s Guide Chapter 23 -- COM-Based Technologies

ボーランドさんがんばって2005年10月12日 20時39分54秒

本国のボーランドサイトにNew Versionのアナウンスが あった。しかし、この時期にアップするのに、dotNet 2.0対応ではない。genericsなどの2.0の機能は 次のバージョンまでおあずけ。

確かに、MSちゃんのフレームワークリリースと 同時に対応は、MSちゃん以外のベンダーには 難しいことだと思う。

でも、もう少しボーランドさんにがんばってもらいたい のですよ。無理やりスケジュールに合わせるのでは なく、たとえば新バージョンの出荷を3ヶ月 遅らせれば新しいフレームワークに対応できる のであればそれでも良いと思うのですが・・・

と云いつつバージョンアップしちゃうのだろうな。