サイトのトップページへ リンクのページへ ロゴマーク
掲載 2008年01月13日 更新 2010年12月11日 Delphiサンプルプログラム集
816_ファイルのプロパティ
動作確認等 Windows XP(SP2) + Delphi 7 Pro
 816_FileProperty.zip [1,844 KB] 2008年11月29日版(EXE同梱)
[前のページ][次のページ]


■ 00_ファイルのプロパティ
■ 01_DSOFileオブジェクトを使用
■ 02_DSOFileオブジェクトを使用 カスタムプロパティ
■ 03_Shellオブジェクトを使用
■ 04_Shellオブジェクトを使用 構造化ストレージの値
■ 05_構造化ストレージの操作
■ 06_ワードのオブジェクトを使用
■ 07_エクセルのオブジェクトを使用
■ 08_構造化ストレージ操作用定数ユニット





00_ファイルのプロパティ


ファイルのプロパティには,以下のような種類があります.

種類1 NTFSになって導入された構造化ストレージのメインストレージの情報です.
ワードやエクセルのプロパティはこのメインストレージに格納されています.この情報はFATでも取得可能となっています.
種類2 構造化ストレージのサブストレージの情報です.
この情報は揮発性で,ファイルを他の媒体に移動すると失われてしまいます.テキストファイル等のプロパティはこれに該当します.
種類3 ファイルの種類によって決められた形式で格納されている情報です.
マイクロソフトが策定したRIFF(Resource Interchange File Format リソース交換ファイル形式)は,WAV,AVI,MPEGで使用されています.またデジカメの画像にはExifという規格が,MP3はID3というタグ情報を使用しています(MP3にはRIFF形式のものもあります).
ファイルフォーマットについては,ここに詳しい情報がありますが,ソースはCまたはC++です(テキストの説明もあります).


図1〜図3は,エクスプローラのファイル上の右クリックで表示した[プロパティ]ダイアログです.これらはファイルの種類によって異なり,構造化ストレージの情報だけではなく,RIFF情報も一部表示しています.
以下のサンプルプログラム類は,これらのプロパティを操作するサンプルです.ただし,RIFF形式の情報が取得できるのはShellオブジェクトを使用した場合だけです.
Delphi 2010以降,Windows XP以降限定となりますが,[819_フォルダビュー(シェル名前空間)]にもファイルのプロパティ取得のサンプルコードがあります.


 
図1 ワード文書のプロパティ例
  • [概要]の[詳細設定]
  • 構造化ストレージの値が表示される
図2 ワードの[カスタム]プロパティの例
図3 テキストファイルの場合
  • テキストファイル等,サブストレージに格納される情報は,値を設定しても,他の媒体に移動すると消失してしまう
図4 マルチメディア関係のファイルの場合
  • オーディオ,イメージ,ムービー等,マルチメディア関係のファイルではRIFF情報の一部が取得できるが,詳細な内容はファイルによって決められた形式を解析する必要がある

[ 頁先頭 ]



01_DSOFileオブジェクトを使用


マイクロソフトのOfficeチームが開発したDSOFile(Microsoft Developer Support OLE File Property Reader)を利用する方法です.プロパティの取得と設 定もできるようになっています. DSOFileではOfficeアプリケーションを起動するオーバーヘッドがないため,より速く情報を取得することができます.DSOFileは次の様にインストールして使用します.
  1. 下記のサイトから[DsoFileSetup_KB224351_x86.exe パッケージ]をダウンロード
    http://support.microsoft.com/kb/q224351/
  2. ダウンロードしたファイルを実行してインストール
  3. Delphiを起動し,IDEから[プロジェクト][タイプライブラリの取込]で
    [DSO OLE Document Properties Reader 2.1 (Version 2.1)を選択し[イン ストール]
DSOFile利用の欠点は,実行環境にもDLLの登録が必要なことです.


 
図5 設計時画面
  • TOleDocumentPropertiesを配置
  • [btnRead]でファイルを選択
  • [btnSave]で現在表示中の値を保存
  • 日時関係は読出し専用
図6 実行中
  • 添付のワードの文書のプロパティ
  • ワードやエクセル以外でも,サブストレージに読書きできるが,対象ファイルを別の媒体に移動すると消失してしまう

リスト1 
DSOFileを使用したファイルのプロパティ取得
unit FileProperties_DSOFileUnit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, DSOFile_TLB, ExtCtrls, OleServer ,XPMan;

type
  TForm1 = class(TForm)
    btnRead: TButton;
    btnSave: TButton;
    Panel1: TPanel;
    OpenDialog1: TOpenDialog;
    lblEdit01: TLabeledEdit;
    lblEdit02: TLabeledEdit;
    lblEdit03: TLabeledEdit;
    lblEdit04: TLabeledEdit;
    lblEdit05: TLabeledEdit;
    lblEdit06: TLabeledEdit;
    Panel2: TPanel;
    lblEdit11: TLabeledEdit;
    lblEdit12: TLabeledEdit;
    lblEdit13: TLabeledEdit;
    OleDocumentProperties1: TOleDocumentProperties;
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure btnReadClick(Sender: TObject);
    procedure btnSaveClick(Sender: TObject);
  private
    { Private 宣言 }
    BasePath : String;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

uses ComObj;

{$R *.dfm}

//=============================================================================
//  初期設定
//  選択フォルダの初期値を設定
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
    BasePath := ExtractFileDir(Application.ExeName);
    BasePath := ExtractFileDir(BasePath);

    //プロパティ保存ボタンは使用不可に
    //作成日等はDSOFileでは変更不可なのでDisableに
    //作成日等の変更はサンプル[780_ファイル一覧と日時・属性の変更]等を参照
    btnSave.Enabled := False;
    Panel2.Enabled  := False;
end;
//=============================================================================
//  終了処理
//=============================================================================
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
    //現在のドキュメントオブジェクトを閉じる
    try
      OleDocumentProperties1.Close(False);
    except
      //DSOFileがインストールされていないPCでは実行できない
    end;
end;
//=============================================================================
//  ファイルのプロパティを読出して表示
//
//  DSOFileによるプロパティの読書きは,対象ファイルを他で操作している場合は実行
//  できない(例えば対象ワード文書を開いている時等).ロック違反となる.
//
//  DSOFileで読出した日付はワードやエクセルのプロパティ
//  エクスプローラの[プロパティ][概要]タブの原作者のところの日付で,[全般]タブ
//  に表示されている日付ではない.
//  Shellオブジェクトによる日付取得の場合は,[全般]タブの日付となる.
//=============================================================================
procedure TForm1.btnReadClick(Sender: TObject);
var
    DateTime11 : TDateTime;
    DateTime12 : TDateTime;
    DateTime13 : TDateTime;
begin
    OpenDialog1.InitialDir := BasePath;
    if OpenDialog1.Execute then begin
      Update;
      //プロパティを保存しないで現在のドキュメントオブジェクトを閉じる
      try
        OleDocumentProperties1.Close(False);
      except
        //DSOFileがインストールされていないPCでは実行できない
        MessageDlg('DSOFileをインストールしないと利用できません.',
                   mtInformation,[mbOK],0);
        exit;
      end;

      lblEdit01.Text := '';
      lblEdit02.Text := '';
      lblEdit03.Text := '';
      lblEdit04.Text := '';
      lblEdit05.Text := '';
      lblEdit06.Text := '';
      lblEdit11.Text := '';
      lblEdit12.Text := '';
      lblEdit13.Text := '';

      OleDocumentProperties1.Open(OpenDialog1.FileName, //フルパス名
                                  False,                //書込みを行うのでFalse
                                  0);                   //オプション(0はdefault)

      //各コントロール(TLabeledEdit)にプロパティを表示
      Panel1.Caption := ExtractFileName(OpenDialog1.FileName);
      lblEdit01.Text := OleDocumentProperties1.SummaryProperties.Title;
      lblEdit02.Text := OleDocumentProperties1.SummaryProperties.Subject;
      lblEdit03.Text := OleDocumentProperties1.SummaryProperties.Company;
      lblEdit04.Text := OleDocumentProperties1.SummaryProperties.Author;
      lblEdit05.Text := OleDocumentProperties1.SummaryProperties.LastSavedBy;
      lblEdit06.Text := OleDocumentProperties1.SummaryProperties.Comments;

      DateTime11 := OleDocumentProperties1.SummaryProperties.DateCreated;
      DateTime12 := OleDocumentProperties1.SummaryProperties.DateLastSaved;
      DateTime13 := OleDocumentProperties1.SummaryProperties.DateLastPrinted;
      if DateTime11>0 then
        lblEdit11.Text := FormatDateTime('yyyy年mm月dd日 hh時mm分',DateTime11);
      if DateTime12>0 then
        lblEdit12.Text := FormatDateTime('yyyy年mm月dd日 hh時mm分',DateTime12);
      if DateTime13>0 then
        lblEdit13.Text := FormatDateTime('yyyy年mm月dd日 hh時mm分',DateTime13);
       btnSave.Enabled := True;
    end;
end;
//=============================================================================
//  各コントロール(TLabeledEdit)に表示中のプロパティを保存する
//=============================================================================
procedure TForm1.btnSaveClick(Sender: TObject);
begin
    OleDocumentProperties1.SummaryProperties.Title       := lblEdit01.Text;
    OleDocumentProperties1.SummaryProperties.Subject     := lblEdit02.Text;
    OleDocumentProperties1.SummaryProperties.Company     := lblEdit03.Text;
    OleDocumentProperties1.SummaryProperties.Author      := lblEdit04.Text;
    OleDocumentProperties1.SummaryProperties.LastSavedBy := lblEdit05.Text;
    OleDocumentProperties1.SummaryProperties.Comments    := lblEdit06.Text;
    OleDocumentProperties1.Save;
end;

end.

[ 頁先頭 ]



02_DSOFileオブジェクトを使用 カスタムプロパティ


同様にDSOFielを使用した例で,カスタムプロパティの操作を追加しています.


図7 設計時画面
  • 背景色が淡い緑の項目がカスタムプロパティ
  • [btnDelete]はカスタムプロパティの削除
図8 実行中
図9 カスタムプロパティを表示
  • カスタムプロパティを作成すると,エクスプローラの [プロパティ][カスタム]に作成したプロパティが表示される

リスト2 
DSOFileオブジェクトを使用してカスタムプロパティを操作
unit FileProperties_DSOFile_CustomUnit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, DSOFile_TLB, ExtCtrls, ComCtrls, OleServer, XPMan;

type
  TForm1 = class(TForm)
    btnRead: TButton;
    btnSave: TButton;
    Panel1: TPanel;
    OpenDialog1: TOpenDialog;
    lblEdit01: TLabeledEdit;
    lblEdit02: TLabeledEdit;
    lblEdit03: TLabeledEdit;
    lblEdit04: TLabeledEdit;
    lblEdit05: TLabeledEdit;
    lblEdit06: TLabeledEdit;
    FileProp: TOleDocumentProperties;
    btnDelete: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure btnReadClick(Sender: TObject);
    procedure btnSaveClick(Sender: TObject);
    procedure btnDeleteClick(Sender: TObject);
  private
    { Private 宣言 }
    BasePath : String;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//=============================================================================
//  初期設定
//  選択フォルダの初期値を設定
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
    BasePath := ExtractFileDir(Application.ExeName);
    BasePath := ExtractFileDir(BasePath);

    btnSave.Enabled   := False;
    btnDelete.Enabled := False;
end;
//=============================================================================
//  終了処理
//=============================================================================
procedure TForm1.FormDestroy(Sender: TObject);
begin
    //現在のドキュメントオブジェクトを閉じる
    try
      FileProp.Close(False);
    except
      //DSOFileがインストールされていないPCでは実行できない
    end;
end;
//=============================================================================
//  ファイルのプロパティを読出して表示
//=============================================================================
procedure TForm1.btnReadClick(Sender: TObject);
var
    HasCustomProp : Boolean;
    APropName     : OleVariant;
    i             : Integer;
    AValue        : OleVariant;
begin
    OpenDialog1.InitialDir := BasePath;
    if OpenDialog1.Execute then begin
      //プロパティを保存しないで現在のドキュメントオブジェクトを閉じる
      try
        FileProp.Close(False);
      except
        //DSOFileがインストールされていないPCでは実行できない
        MessageDlg('DSOFileをインストールしないと利用できません.',
                   mtInformation,[mbOK],0);
        exit;
      end;

      lblEdit01.Text := '';
      lblEdit02.Text := '';
      lblEdit03.Text := '';
      lblEdit04.Text := '';
      lblEdit05.Text := '';
      lblEdit06.Text := '';
      Update;
      FileProp.Open(OpenDialog1.FileName,   //対象ファイルのフルパス名
                    False,                  //書込みを行うのでFalse
                    0);                     //オプション(0はdefault)

      //各コントロール(TLabeledEdit)にプロパティを表示
      Panel1.Caption := ExtractFileName(OpenDialog1.FileName);
      lblEdit01.Text := FileProp.SummaryProperties.Title;
      lblEdit02.Text := FileProp.SummaryProperties.Subject;
      lblEdit03.Text := FileProp.SummaryProperties.Company;

      //カスタムプロパティの存在を調査してあれば値を表示
      for i:=0 to FileProp.CustomProperties.Count-1 do begin
        APropName := FileProp.CustomProperties.Item[i].Name;
        if APropName='送付先' then begin
          HasCustomProp  := True;
          AValue         := FileProp.CustomProperties.Item[APropName].Get_Value;
          lblEdit04.Text := AValue;
        end else
        if APropName='送付部数' then begin
          HasCustomProp  := True;
          AValue         := FileProp.CustomProperties.Item[APropName].Get_Value;
          if AValue<>0 then lblEdit05.Text := AValue;
        end else
        if APropName='送付日' then begin
          HasCustomProp  := True;
          AValue         := FileProp.CustomProperties.Item[APropName].Get_Value;
          if AValue<>0 then lblEdit06.Text := AValue;
        end;
      end;

      btnSave.Enabled   := True;
      btnDelete.Enabled := HasCustomProp;
    end;
end;
//=============================================================================
//  各コントロール(TLabeledEdit)に表示中のプロパティを保存する
//
//  カスタムプロパティの設定は以下の様に行う
//  CustomProperties.Item[プロパティ名].Set_Value(値);
//  存在しないプロパティに対して実行するとエラー
//  日付型の値は,日付型の書式にしたがってTLabledEditに入力しておく
//  (デフォルトではyyyy/mm/dd)
//  プロパティの型に使用可能なものは以下の通り
//  ----------------------------
//    データ型             値
//  ----------------------------
//    数値型               1
//    ブール型 (Yes/No)    2
//    日付型               3
//    文字列型             4
//=============================================================================
procedure TForm1.btnSaveClick(Sender: TObject);
var
    HasCustomProp   : Boolean;
    PropertyNumber  : OleVariant;
    PropertyBoolean : OleVariant;
    PropertyDate    : OleVariant;
    PropertyString  : OleVariant;
    AName           : OleVariant;
    ACount          : OleVariant;
    ADate           : OleVariant;
    i               : Integer;
    APropName       : OleVariant;
begin
    //カスタムプロパティの定数値
    PropertyNumber  := 1;
    PropertyBoolean := 2;
    PropertyDate    := 3;
    PropertyString  := 4;

    //それらの値
    AName  := lblEdit04.Text;
    ACount := StrToIntDef(lblEdit05.Text,0);
    try
      ADate  := StrToDate(lblEdit06.Text);
    except
      ADate := 0;
    end;

    FileProp.SummaryProperties.Title       := lblEdit01.Text;
    FileProp.SummaryProperties.Subject     := lblEdit02.Text;
    FileProp.SummaryProperties.Company     := lblEdit03.Text;
    FileProp.SummaryProperties.LastSavedBy := 'Mr.XRAY';

    //APropListのカスタムプロパティがなければ作成
    //作成したら保存しないと有効にならない
    HasCustomProp := False;
    for i:=0 to FileProp.CustomProperties.Count-1 do begin
      APropName := FileProp.CustomProperties.Item[i].Name;
      if APropName='送付先' then begin
        HasCustomProp := True;
        break;
      end;
    end;

    //プロパティがない場合
    if HasCustomProp=False then begin
      FileProp.CustomProperties.Add('送付先'  , PropertyString);
      FileProp.CustomProperties.Add('送付部数', PropertyNumber);
      FileProp.CustomProperties.Add('送付日'  , PropertyDate);
      FileProp.Save;
    end;

    //カスタムプロパティの値を設定
    FileProp.CustomProperties.Item['送付先'].  Set_Value(AName);
    FileProp.CustomProperties.Item['送付部数'].Set_Value(ACount);
    FileProp.CustomProperties.Item['送付日'].  Set_Value(ADate);
    FileProp.Save;

    btnDelete.Enabled := HasCustomProp;
end;
//=============================================================================
//  カスタムプロパティを全て削除
//  このコードでは全てのカスタムプロパティを削除してしまうので要注意
//
//  カスタムプロパティの削除は以下の様に行う
//  CustomProperties.Item[プロパティ名].Remove
//  存在しないプロパティに対して実行するとエラー
//  このコードの様にプロパティ名の代わりにプロパティのItem番号でも可能
//=============================================================================
procedure TForm1.btnDeleteClick(Sender: TObject);
var
    i : Integer;
begin
    for i:=FileProp.CustomProperties.Count-1 downto 0 do begin
      FileProp.CustomProperties.Item[i].Remove;
    end;
    FileProp.Save;
end;

end.

[ 頁先頭 ]



03_Shellオブジェクトを使用


Shellオブジェクトをコンポーネントにし,フォーム上に配置して利用しています.プロパティの取得のみ可能です.
Shellオブジェクトでは,RIFF形式の情報の一部も取得できます.Shellオブジェクトをコンポーネントとしてインストールする方法は,[タイプライブラリの取り込み]を参考にして下さい.


図10 設計時画面
図11 実行結果
  • 添付のデジカメの画像ファイルのプロパティ
  • RIFF情報として,カメラのモデルと写真の撮影日が取得されている

リスト3 
Shellオブジェクトを使用したファイルのプロパティ取得
unit FileProperties_ShellUnit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, OleServer, Shell32_TLB, ComCtrls;

type
  TForm1 = class(TForm)
    OpenDialog1: TOpenDialog;
    Shell1: TShell;
    Panel1: TPanel;
    Button1: TButton;
    Panel2: TPanel;
    ListView1: TListView;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
    BasePath : String;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

uses FileCtrl;

{$R *.dfm}

//=============================================================================
//  初期設定
//  選択フォルダの初期値を設定
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
     BasePath := ExtractFileDir(Application.ExeName);
     BasePath := ExtractFileDir(BasePath);
end;
//=============================================================================
//  Form上に配置したコンポーネントは[特別な領域]に記述,保存されるので,解放は
//  不要.[特別な領域]については以下を参照.もちろん解放処理を行ってもよいが,
//  その場合はTForm.Destroyではなく,TForm.Colse等で実行する.Destroyでは既に解
//  放されてしまっている.
//  http://homepage2.nifty.com/Mr_XRAY/Delphi/plSamples/UltraIntro01.htm
//=============================================================================
procedure TForm1.FormDestroy(Sender: TObject);
begin
//
end;
//=============================================================================
//  Folderオブジェクトのプロパティ名とその値をリスト
//  RIFF情報の一部も取得できる
//  プロパティのリストとプロパティ名はPCの環境によって異なる
//
//  Shellオブジェクトで取得するプロパティは取得順番によって種類が決まっている
//  ので,特定のプロパティを何番目かを指定しても取得できる
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
    AFolderPath  : String;
    AFilePath    : String;
    SHFolder     : Shell32_TLB.Folder;
    SHFolderItem : Shell32_TLB.FolderItem;
    i            : Integer;
    AValue       : WideString;
    PropNoList   : TStringList;
begin
     OpenDialog1.InitialDir := BasePath;
     if OpenDialog1.Execute then begin
       ListView1.Items.Clear;
       ListView1.Update;
       ListView1.Items.BeginUpdate;

       PropNoList  := TStringList.Create;
       AFilePath   := OpenDialog1.FileName;
       AFolderPath := ExtractFilePath(AFilePath);
       SHFolder    := Shell1.NameSpace(AFolderPath);

       try
         //SHFolderオブジェクトのプロパティ名リストを取得(Button1Clickと同じ)
         for i:=0 to 50 do begin
           AValue := SHFolder.GetDetailsOf(varNull,i);
           if AValue<>'' then begin
             ListView1.Items.Add.Caption:=FormatFloat('00 ',i)+ AValue;
             PropNoList.Add(IntToStr(i));
           end;
         end;

         //OpenDialogで選択したファイルのFolderItemオブジェクトを取得
         SHFolderItem := SHFolder.ParseName(ExtractFileName(AFilePath));
         //そのFolderItemのプロパティ値を順番に取得
         for i:=0 to PropNoList.Count-1 do begin
           AValue := SHFolder.GetDetailsOf(SHFolderItem,StrToInt(PropNoList[i]));
           ListView1.Items[i].SubItems.Text := AValue;
         end;
       finally
         FreeAndNil(PropNoList);
       end;
       ListView1.Items.EndUpdate;
     end;
end;

end.

[ 頁先頭 ]



04_Shellオブジェクトを使用 構造化ストレージの値


Shellオブジェクトでは,Shellオブジェクトが提供するプロパティ以外にも,構造化ストレージのプロパティ値を取得することができます.添付のplFileInfo_Const.pasを使用します.


図12 設計時画面
図13 実行画面

リスト4 
Shellオブジェクトで構造化ストレージの値を取得
unit ExtendedProperty_ShellUnit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls, OleServer, Shell32_TLB, XPMan;

type
  TForm1 = class(TForm)
    btnRead: TButton;
    Panel1: TPanel;
    OpenDialog1: TOpenDialog;
    Panel2: TPanel;
    lblEdit01: TLabeledEdit;
    lblEdit02: TLabeledEdit;
    lblEdit03: TLabeledEdit;
    lblEdit04: TLabeledEdit;
    lblEdit05: TLabeledEdit;
    lblEdit06: TLabeledEdit;
    lblEdit11: TLabeledEdit;
    lblEdit12: TLabeledEdit;
    lblEdit13: TLabeledEdit;
    Shell1: TShell;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure btnReadClick(Sender: TObject);
  private
    { Private 宣言 }
    BasePath : String;
    function CreatePropStr(GUID: TGUID; ID: Integer): WideString;
    function UTCTimeDateTimeOffset: TDateTime;    
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

//  plFileInot_Constは[プロジェクト][プロジェクトに追加]でプロジェクトに追加し
//  ている.必要に応じて変更のこと

uses plFileInfo_Const;

{$R *.dfm}

//=============================================================================
//  初期設定
//  選択フォルダの初期値を設定
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
    BasePath := ExtractFileDir(Application.ExeName);
    BasePath := ExtractFileDir(BasePath);

    //Shellオブジェクトによるプロパティは読出し専用なのでDisableに
    Panel2.Enabled  := False;
end;
//=============================================================================
//  Form上に配置したコンポーネントは[特別な領域]に記述,保存されるので,解放は
//  不要.[特別な領域]については以下を参照.もちろん解放処理を行ってもよいが,
//  その場合はTForm.Destroyではなく,TForm.Colse等で実行する.Destroyでは既に解
//  放されてしまっている.
//  http://mrxray.on.coocan.jp/Delphi/plSamples/A_UltraIntro01.htm
//=============================================================================
procedure TForm1.FormDestroy(Sender: TObject);
begin
//
end;
//=============================================================================
//  ファイルのプロパティを読出して表示
//  個々ののプロパティを取得するには,FolderItem2オブジェクトのExtendedProperty
//  メソッドを使用する.Extended(拡張)となっているが,このExtendedの意味は不明
//
//  FMTID_XXXXで取得するプロパティ値は構造化ストレージの値なので,対象ファイル
//  が構造化ストレージをサポートしていて,プロパティが格納されていなければ取得
//  できない.つまりRIFF情報は取得できない.
//=============================================================================
procedure TForm1.btnReadClick(Sender: TObject);
var
    AFolderPath   : String;
    AFileName     : String;
    SHFolderItem2 : Shell32_TLB.FolderItem2;
    PropStr       : WideString;
    AValue        : OleVariant;
    ADate         : TDateTime;
begin
    OpenDialog1.InitialDir := BasePath;
    if OpenDialog1.Execute then begin
      lblEdit01.Text := '';
      lblEdit02.Text := '';
      lblEdit03.Text := '';
      lblEdit04.Text := '';
      lblEdit05.Text := '';
      lblEdit06.Text := '';
      lblEdit11.Text := '';
      lblEdit12.Text := '';
      lblEdit13.Text := '';
      Update;

      AFolderPath    := ExtractFilePath(OpenDialog1.FileName);
      AFileName      := ExtractFileName(OpenDialog1.FileName);
      SHFolderItem2  := FolderItem2(Shell1.NameSpace(AFolderPath).
                                     ParseName(AFileName));
      Panel1.Caption := AFileName;

      //タイトル
      PropStr        := CreatePropStr(FMTID_SummaryInfo,PID_TITLE);
      AValue         := SHFolderItem2.ExtendedProperty(PropStr);
      lblEdit01.Text := VarToStr(AValue);

      //サブタイトル
      PropStr        := CreatePropStr(FMTID_SummaryInfo,PID_SUBJECT);
      AValue         := SHFolderItem2.ExtendedProperty(PropStr);
      lblEdit02.Text := VarToStr(AValue);

      //会社名
      PropStr        := CreatePropStr(FMTID_DocSummaryInfo,PID_COMPANY);
      AValue         := SHFolderItem2.ExtendedProperty(PropStr);
      lblEdit03.Text := VarToStr(AValue);

      //作成者
      PropStr        := CreatePropStr(FMTID_SummaryInfo,PID_AUTHOR);
      AValue         := SHFolderItem2.ExtendedProperty(PropStr);
      lblEdit04.Text := VarToStr(AValue);

      //最終保存者
      PropStr        := CreatePropStr(FMTID_SummaryInfo,PID_LASTAUTHOR);
      AValue         := SHFolderItem2.ExtendedProperty(PropStr);
      lblEdit05.Text := VarToStr(AValue);

      //コメント
      PropStr        := CreatePropStr(FMTID_SummaryInfo,PID_COMMENTS);
      AValue         := SHFolderItem2.ExtendedProperty(PropStr);
      lblEdit06.Text := VarToStr(AValue);

      try
        //作成日
        PropStr := CreatePropStr(FMTID_SummaryInfo,PID_CREATE_DTM);
        AValue  := SHFolderItem2.ExtendedProperty(PropStr);
        if not VarIsEmpty(AValue) then begin
          //UTCからローカル時刻に変換
          ADate := AValue+ UTCTimeDateTimeOffset;
          lblEdit11.Text := VarToStr(ADate);
        end;

        //最終更新日
        PropStr := CreatePropStr(FMTID_SummaryInfo,PID_LASTSAVE_DTM);
        AValue  := SHFolderItem2.ExtendedProperty(PropStr);
        if not VarIsEmpty(AValue) then begin
          //UTCからローカル時刻に変換
          ADate := AValue+ UTCTimeDateTimeOffset;
          lblEdit12.Text := VarToStr(ADate);
        end;

        //最終印刷日
        PropStr := CreatePropStr(FMTID_SummaryInfo,PID_LASTPRINTED);
        AValue  := SHFolderItem2.ExtendedProperty(PropStr);
        if not VarIsEmpty(AValue) then begin
          //UTCからローカル時刻に変換
          ADate := AValue+ UTCTimeDateTimeOffset;
          lblEdit13.Text := VarToStr(ADate);
        end;
      except
      end;
    end;
end;
//=============================================================================
//  FolderItem2オブジェクトのExtendedPropertyメソッドの引数を作成.これは
//  プロパティのカテゴリのGUIDの文字列 + プロパティの種類の値
//  という形式となっている(間に半角の空白)
//=============================================================================
function TForm1.CreatePropStr(GUID: TGUID; ID: Integer): WideString;
begin
    Result :=GUIDToString(GUID)+' '+IntToStr(ID);
end;
//=============================================================================
//  FolderItme2オブジェクトのExtenedPropertyので取得する日付はUTC(世界協定時刻)
//  このUTCとローカルとの時刻差を求める関数
//
//  GetTimeZoneInformationでシステムから現在のタイムゾーンパラメータを取得
//  Bias値は世界協定時刻(UTC)時間とローカル時間との分差,つまり分なので,これを
//  TDateTime型に変換して返す
//  日本の場合は常に9:00:00
//=============================================================================
function TForm1.UTCTimeDateTimeOffset: TDateTime;
var
    TZ   : TTimeZoneInformation;
    Hour : Integer;
    Min  : Integer;
begin
    GetTimeZoneInformation(TZ);
    Hour   := ABS(TZ.Bias) div 60;
    Min    := ABS(TZ.Bias) mod 60;
    Result := EncodeTime(Hour,Min,0,0);
end;

end.

[ 頁先頭 ]



05_構造化ストレージの操作


構造化ストレージを操作する例です.添付のplFileInfo_Const.pasを使用します.カスタムプロパティ(ユーザ定義のプロパティ)を利用するには,コードの追加あるいは修正が必要です.


図14 設計時画面
図15 実行画面

リスト5 
構造化ストレージの値を操作
unit FileProperties_StorageUnit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls,ActiveX, XPMan;

type
  TForm1 = class(TForm)
    Bevel1: TBevel;
    OpenDialog1: TOpenDialog;
    btnSave: TButton;
    btnRead: TButton;
    lblEdit01: TLabeledEdit;
    lblEdit02: TLabeledEdit;
    lblEdit03: TLabeledEdit;
    lblEdit04: TLabeledEdit;
    lblEdit05: TLabeledEdit;
    lblEdit06: TLabeledEdit;
    lblEdit11: TLabeledEdit;
    lblEdit12: TLabeledEdit;
    lblEdit13: TLabeledEdit;
    Panel1: TPanel;
    procedure btnReadClick(Sender: TObject);
    procedure btnSaveClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private 宣言 }
    BasePath : String;
    AFileName: string;
    function GetStorage(const FileName: WideString;
        GUID_Type: TGUID; PID_Info: cardinal): string;
    function SetStorage(const FileName: WideString; GUID_Type: TGUID;
        PID_Info: cardinal; InfoStr: string): boolean;
    function SetStorageDate(const FileName: WideString; GUID_Type: TGUID;
        PID_Info: cardinal; ADateTime: TDateTime): boolean;
    function PropertyVariantToString(const Prop: TPropVariant): String;
    function ToDateTime(ATime: TFileTime): TDateTime;
    function ToFileTime(ATime: TDateTime): TFileTime;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

//  plFileInot_Constは[プロジェクト][プロジェクトに追加]でプロジェクトに追加し
//  ている.必要に応じて変更のこと

uses plFileInfo_Const;

{$R *.dfm}

//=============================================================================
//  初期設定
//  選択フォルダの初期値を設定
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
    BasePath := ExtractFileDir(Application.ExeName);
    BasePath := ExtractFileDir(BasePath);
end;
//=============================================================================
//  プロパティ読出しボタン
//
//  FMTID_XXXXで取得するプロパティ値は構造化ストレージの値なので,対象ファイル
//  が構造化ストレージをサポートしてなければ取得できない.
//  ただし,サブストリーム(揮発性情報)に書込まれた内容は表示可能
//
//  MP3のID3タグ,デジカメのフォーマット形式であるExif,またマイクロソフトが定
//  めたRIFF形式(AVI,WAV,MID,ビットマップのDIB等)は独自の形式でプロパティ値を格
//  納しているため取得できない.
//  エクスプローラの[プロパティ][概要]タブにはこれらの値の一部が表示されるよう
//  になっている.またShellオブジェクトでもこれらの一部を取得できる.
//=============================================================================
procedure TForm1.btnReadClick(Sender: TObject);
begin
    OpenDialog1.InitialDir := BasePath;
    if OpenDialog1.Execute then begin
      lblEdit01.Text := '';
      lblEdit02.Text := '';
      lblEdit03.Text := '';
      lblEdit04.Text := '';
      lblEdit05.Text := '';
      lblEdit06.Text := '';
      lblEdit11.Text := '';
      lblEdit12.Text := '';
      lblEdit13.Text := '';
      Update;

      AFileName := OpenDialog1.FileName;
      Panel1.Caption := ExtractFileName(AFileName);

      lblEdit01.Text:=GetStorage(AFileName,FMTID_SummaryInfo,   PID_TITLE);
      lblEdit02.Text:=GetStorage(AFileName,FMTID_SummaryInfo,   PID_SUBJECT);
      lblEdit03.Text:=GetStorage(AFileName,FMTID_DocSummaryInfo,PID_COMPANY);
      lblEdit04.Text:=GetStorage(AFileName,FMTID_SummaryInfo,   PID_AUTHOR);
      lblEdit05.Text:=GetStorage(AFileName,FMTID_SummaryInfo,   PID_LASTAUTHOR);
      lblEdit06.Text:=GetStorage(AFileName,FMTID_SummaryInfo,   PID_COMMENTS);
      lblEdit11.Text:=GetStorage(AFileName,FMTID_SummaryInfo,   PID_CREATE_DTM);
      lblEdit12.Text:=GetStorage(AFileName,FMTID_SummaryInfo,   PID_LASTSAVE_DTM);
      lblEdit13.Text:=GetStorage(AFileName,FMTID_SummaryInfo,   PID_LASTPRINTED);
    end;
end;
//=============================================================================
//  プロパティ書込みボタン
//  文字列型と日付型で処理分岐(TDateTimePickerを使用した方がいいかも)
//  各テキストの日付書式を変更しないこと
//
//  FMTID_XXXXで操作するプロパティ値は構造化ストレージの値なので,対象ファイル
//  が構造化ストレージをサポートしてなければ操作できない.
//  ただし,サブストリーム(揮発性情報)には書込みができる.たとえばテキストファ
//  イルにもこのbtnSaveClick内で指定する値を書込めるが,FindFirst等で取得する
//  値とは全く別の(構造化ストレージの性質)情報となる.またこの揮発性の情報は,
//  対象ファイルを他の記憶媒体に移動すると消えてしまう.
//=============================================================================
procedure TForm1.btnSaveClick(Sender: TObject);
var
    ADate1 : TDateTime;
    ADate2 : TDateTime;
    ADate3 : TDateTime;
begin
    if FileExists(AFileName) then begin
      //文字列関係
      SetStorage(AFileName, FMTID_SummaryInfo,   PID_TITLE,     lblEdit01.Text);
      SetStorage(AFileName, FMTID_SummaryInfo,   PID_SUBJECT,   lblEdit02.Text);
      SetStorage(AFileName, FMTID_DocSummaryInfo,PID_COMPANY,   lblEdit03.Text);
      SetStorage(AFileName, FMTID_SummaryInfo,   PID_AUTHOR,    lblEdit04.Text);
      SetStorage(AFileName, FMTID_SummaryInfo,   PID_LASTAUTHOR,lblEdit05.Text);
      SetStorage(AFileName, FMTID_SummaryInfo,   PID_COMMENTS,  lblEdit06.Text);

      //日付型
      try
        //作成日
        ADate1 := StrToDateTime(lblEdit11.Text);
        SetStorageDate(AFileName, FMTID_SummaryInfo,PID_CREATE_DTM,  ADate1);
        //最終更新日
        ADate2 := StrToDateTime(lblEdit12.Text);
        SetStorageDate(AFileName, FMTID_SummaryInfo,PID_LASTSAVE_DTM,ADate2);
        //最終印刷日
        ADate3 := StrToDateTime(lblEdit13.Text);
        SetStorageDate(AFileName, FMTID_SummaryInfo,PID_LASTPRINTED, ADate3);
      except
      end;
    end;
end;
//=============================================================================
//  プロパティセットを読出す実際の関数
//
//  同じGUID_Typeのプロパティであれば,Enumメソッドを使用して列挙可能であるが,
//  ここでは使用していない.
//  一つのファイルに対してプロパティを列挙するのではなく,同じプロパティ値のフ
//  ァイルを選択するなどの目的を想定しているので.
//
//  IPropertySetStorage.Open
//  第1引数 開くプロパティセットの(通常FMTIDの識別子を使用)
//  第2引数 開くプロパティセットのモード
//  第3引数 IPropertyStorageインタフェースの受取り値へのポインタ
//
//  IPropertyStorage.ReadMultiple
//  第1引数 読取るプロパティの数
//  第2引数 読取るプロパティの配列
//  第3引数 読取ったプロパティ値が格納されているPROPVARIANT値の配列
//          (プロパティの型,実際の値)
//=============================================================================
function TForm1.GetStorage(const FileName: WideString;
  GUID_Type: TGUID; PID_Info: cardinal): string;
var
    hr          : HRESULT;
    Stg         : IStorage;
    PropSetStg  : IPropertySetStorage;
    PropStg     : IPropertyStorage;
    PropSpec    : TPropSpec;
    PropVariant : TPropVariant;
begin
    Result := '';

    //既存のストレージオブジェクトを開く
    hr := StgOpenStorageEx(pwidechar(FileName),
                               STGM_READ or STGM_SHARE_DENY_WRITE,STGFMT_ANY,
                               0,
                               nil,
                               nil,
                               @IID_IPropertySetStorage,
                               Stg);

    //GUID_Typeで指定するプロパティセットを読出しモードで開く
    //条件文は,if hr<>S_FALSEても可.Succeeded(hr)やnot Failed(hr)でもよい
    if (hr=S_OK) then begin
      PropSetStg := Stg as IPropertySetStorage;
      hr := PropSetStg.Open(GUID_Type,
                            STGM_READ or STGM_SHARE_EXCLUSIVE,
                            PropStg);
      if (hr=S_OK) then begin
        PropSpec.ulKind := PRSPEC_PROPID;
        PropSpec.propid := PID_Info;
        if (PropStg.ReadMultiple(1,@PropSpec,@PropVariant)=S_OK) then begin
          if (PropVariant.pszVal<>nilthen begin
            Result := PropertyVariantToString(PropVariant);
          end;
        end;
      end;
    end;
end;
//=============================================================================
//  プロパティセットを書込む実際の関数(文字列型専用)
//  単一プロパティの値のみを書込む仕様としている.理由はGetStorageと同じ
//
//  IPropertySetStorage.Open
//  第1引数 開くプロパティセットの(通常FMTIDの識別子を使用)
//  第2引数 開くプロパティセットのモード
//  第3引数 IPropertyStorageインタフェースの受取り値へのポインタ
//
//  IPropertyStorage.WriteMultiple
//  第1引数 設定するプロパティの数
//  第2引数 プロパティ識別子(PIDXXX)
//  第3引数 PROPVARIANT値の配列(プロパティの型,実際の値)
//  第4引数 割り当てられているプロパティ識別子の最小値 
//=============================================================================
function TForm1.SetStorage(const FileName: WideString;
  GUID_Type: TGUID; PID_Info: Cardinal; InfoStr: string): boolean;
var
    hr          : HRESULT;
    Stg         : IStorage;
    PropSetStg  : IPropertySetStorage;
    PropStg     : IPropertyStorage;
    PropSpec    : TPropSpec;
    PropVariant : TPropVariant;
begin
    Result := False;

    //既存のストレージオブジェクトを開く
    hr := StgOpenStorageEx(pwidechar(FileName),
                           STGM_SHARE_EXCLUSIVE or STGM_READWRITE,
                           STGFMT_ANY,
                           0,
                           nil,
                           nil,
                           @IID_IPropertySetStorage,
                           Stg);

    //GUID_Typeで指定するプロパティセットを読書き両用モードで開く
    if (hr=S_OK) then begin
      PropSetStg := Stg as IPropertySetStorage;
      hr  := PropSetStg.Open(GUID_Type,
                             STGM_READWRITE or STGM_SHARE_EXCLUSIVE,
                             PropStg);

      //新しいプロパティセットの作成
      //[詳細]タブに項目があってもストレージがあるとは限らないので作成
      if (hr<>S_OK) then begin
        hr := PropSetStg.Create(GUID_Type,GUID_Type,
                         PROPSETFLAG_DEFAULT,STGM_CREATE or STGM_READWRITE or
                         STGM_SHARE_EXCLUSIVE,
                         PropStg);
      end;

      //新しいプロパティ値を書込む
      if (hr=S_OK) then begin
        PropSpec.ulKind    := PRSPEC_PROPID;
        PropSpec.propid    := PID_Info;
        PropVariant.vt     := VT_LPSTR;
        PropVariant.pszVal := pchar(InfoStr);
        if (PropStg.WriteMultiple(1,@PropSpec,@PropVariant,2)=S_OK) then begin
          Result := (PropStg.Commit(STGC_DEFAULT)=S_OK);
        end;
      end;
    end;
end;
//=============================================================================
//  プロパティセットを書込む実際の関数(日付型専用)
//
//  上の関数との違いは,最後の引数がTDateTime型なので(1)(2)の部分を変更
//  必要であれば,SetFtorage関数の引数を変更して汎用的にしてもいいかも知れない
//=============================================================================
function TForm1.SetStorageDate(const FileName: WideString;
  GUID_Type: TGUID; PID_Info: cardinal; ADateTime: TDateTime): boolean;
var
    hr          : HRESULT;
    Stg         : IStorage;
    PropSetStg  : IPropertySetStorage;
    PropStg     : IPropertyStorage;
    PropSpec    : TPropSpec;
    PropVariant : TPropVariant;
begin
    Result := False;

    //既存のストレージオブジェクトを開く
    hr := StgOpenStorageEx(pwidechar(FileName),
                           STGM_SHARE_EXCLUSIVE or STGM_READWRITE,
                           STGFMT_ANY,
                           0,
                           nil,
                           nil,
                           @IID_IPropertySetStorage,
                           Stg);

    //GUID_Typeで指定するプロパティセットを読書き両用モードで開く
    if (hr=S_OK) then begin
      PropSetStg := Stg as IPropertySetStorage;
      hr  := PropSetStg.Open(GUID_Type,
                             STGM_READWRITE or STGM_SHARE_EXCLUSIVE,
                             PropStg);

      //新しいプロパティセットの作成
      //[詳細]タブに項目があってもストレージがあるとは限らないので作成
      if (hr<>S_OK) then begin
        hr := PropSetStg.Create(GUID_Type,GUID_Type,
                         PROPSETFLAG_DEFAULT,STGM_CREATE or STGM_READWRITE or
                         STGM_SHARE_EXCLUSIVE,
                         PropStg);
     end;

      //新しいプロパティ値を書込む
      if (hr=S_OK) then begin
        PropSpec.ulKind      := PRSPEC_PROPID;
        PropSpec.propid      := PID_Info;
        PropVariant.vt       := VT_FILETIME;           //(1)
        PropVariant.filetime := ToFileTime(ADateTime); //(2)
        if (PropStg.WriteMultiple(1,@PropSpec,@PropVariant,2)=S_OK) then begin
          Result := (PropStg.Commit(STGC_DEFAULT)=S_OK);
        end;
      end;
    end;
end;
//=============================================================================
//  プロパティ値をその値に応じて文字列に変換
//  プロパティ書込みの際は,この逆の変換が必要であるが,このサンプルプログラム
//  では文字列と日付のみを扱っているので省略し,文字列型と日付型の設定を別関数
//  とした.
//=============================================================================
function TForm1.PropertyVariantToString(const Prop: TPropVariant): String;
begin
    case Prop.vt of
      VT_EMPTY    : Result := '';
      VT_NULL     : Result := '';
      VT_VOID     : Result := '';
      VT_I2       : Result := IntToStr(Prop.iVal);
      VT_I4       : Result := IntToStr(Prop.lVal);
      VT_INT      : Result := IntToStr(Prop.lVal);
      VT_R4       : Result := FloatToStr(Prop.fltVal);
      VT_R8       : Result := FloatToStr(Prop.dblVal);
      VT_BSTR     : Result := Prop.bstrVal;
      VT_UI1      : Result := IntToStr(Prop.bVal);
      VT_UI2      : Result := IntToStr(Prop.uiVal);
      VT_UI4      : Result := IntToStr(Prop.ulVal);
      VT_UINT     : Result := IntToStr(Prop.ulVal);
      VT_I8       : Result := IntToStr(Int64(Prop.hVal));
      VT_UI8      : Result := IntToStr(Int64(Prop.uhVal));
      VT_LPSTR    : Result := Prop.pszVal;
      VT_LPWSTR   : Result := Prop.pwszVal;
      VT_ERROR    : Result := 'ERROR : ' + IntToStr(Prop.sCode);
      VT_BOOL     : if Prop.boolVal=False then Result:='0' else Result:='1';
      VT_CLSID    : if Prop.puuid<>nil then Result:=GuidToString(Prop.puuid^);
      VT_FILETIME : Result := DateTimeToStr(ToDateTime(Prop.filetime));
    else
      Result := '';
    end;
end;
//=============================================================================
//  TFileTime型の値をDelphiのTDateTime型に変換する関数
//=============================================================================
function TForm1.ToDateTime(ATime: TFileTime): TDateTime;
var
    SystemTime : TSystemTime;
    TempTime   : TFileTime;
begin
    try
      //FileTime形式(世界協定時刻)を地域にあわせる
      FileTimeToLocalFileTime(ATime, TempTime);
      //FileTime形式をSystemTime形式にする
      FileTimeToSystemTime(TempTime, SystemTime);
      //SystemTime形式をDelphiのTDateTime形式に変換
      Result:=SystemTimeToDateTime(SystemTime);
    except
      Result:=0;
    end;
end;
//=============================================================================
//  DelphiのTDateTime型の値をTFileTime型に変換する関数
//=============================================================================
function TForm1.ToFileTime(ATime: TDateTime): TFileTime;
var
    SystemTime    : TSystemTime;
    LocalFileTime : TFileTime;
begin
    try
      //TFileTimeをSystemTimeに変換
      DateTimeToSystemTime(ATime, SystemTime);
      //SystemTimeをローカルのFileTimeに変換
      SystemTimeToFileTime(SystemTime, LocalFileTime);
      //最後にローカルの日時をGMT(世界協定時刻)に変換
      LocalFileTimeToFileTime(LocalFileTime,Result);
    except
      Result.dwLowDateTime  := 0;
      Result.dwHighDateTime := 0;
    end;
end;

end.

[ 頁先頭 ]



06_ワードのオブジェクトを使用


ワードのオブジェクトを生成して,それを操作してプロパティを取得設定する例です.右のListViewには,ワードで取得可能なプロパティを一覧表示します.また送付先はカスタムプロパティです.
[btnDelete]はカスタムプロパティの定義そのものを削除します.


  • 図16 
  • 設計時画面
  • 送付先はカスタムプロパティ

  • 図17 
  • 実行画面

リスト6 
ワードのオブジェクトを使用したプロパティの取得
unit FileProperties_WordObjectUnit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Grids, ExtCtrls, ComCtrls, XPMan;

type
  TForm1 = class(TForm)
    Bevel1: TBevel;
    btnSave: TButton;
    btnRead: TButton;
    lblEdit01: TLabeledEdit;
    lblEdit02: TLabeledEdit;
    lblEdit03: TLabeledEdit;
    lblEdit04: TLabeledEdit;
    lblEdit05: TLabeledEdit;
    lblEdit06: TLabeledEdit;
    lblEdit07: TLabeledEdit;
    Panel1: TPanel;
    Panel2: TPanel;
    OpenDialog1: TOpenDialog;
    ListView1: TListView;
    lblEdit11: TLabeledEdit;
    lblEdit12: TLabeledEdit;
    lblEdit13: TLabeledEdit;
    btnDelete: TButton;
    procedure FormCreate(Sender: TObject);
    procedure btnReadClick(Sender: TObject);
    procedure btnSaveClick(Sender: TObject);
    procedure btnDeleteClick(Sender: TObject);
  private
    { Private 宣言 }
    BasePath : String;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

uses ComObj,Word2000,Office2000;

{$R *.dfm}

//=============================================================================
//  初期設定
//  選択フォルダの初期値を設定
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
    BasePath := ExtractFileDir(Application.ExeName);
    BasePath := ExtractFileDir(BasePath);

    btnSave.Enabled   := False;
    btnDelete.Enabled := False;
    Panel2.Enabled    := False;
end;
//=============================================================================
//  プロパティ読出しボタン
//
//  ワードのオブジェクトを作成し,文書を開いて(非表示)から操作するため,その分
//  のオーバヘッドがある.これはプロパティの書込みも同じ
//=============================================================================
procedure TForm1.btnReadClick(Sender: TObject);
var
    WordApp      : OleVariant;
    WordDocu     : OleVariant;
    i            : Integer;
    Properties   : OleVariant;
    DocuProperty : OleVariant;
    Value        : OleVariant;
    AItem        : TListItem;
begin
    OpenDialog1.InitialDir := BasePath;
    OpenDialog1.Filter := 'Word Document(*.doc)|*.doc';

    if OpenDialog1.Execute then begin
      lblEdit01.Text := '';
      lblEdit02.Text := '';
      lblEdit03.Text := '';
      lblEdit04.Text := '';
      lblEdit05.Text := '';
      lblEdit06.Text := '';
      lblEdit07.Text := '';
      lblEdit11.Text := '';
      lblEdit12.Text := '';
      lblEdit13.Text := '';
      Update;
      ListView1.Items.Clear;
      ListView1.Update;
      ListView1.Items.BeginUpdate;

      WordApp := CreateOleObject('Word.Application');
      WordApp.Documents.Open(OpenDialog1.FileName);
      try
        //ワードに組込み済みのプロパティ(BuiltInDocumentPropertie)のリスト作成
        Properties := WordApp.ActiveDocument.BuiltInDocumentProperties;

        for i := 1 to Properties.Count do begin
          DocuProperty := Properties.Item[i];
          try
            Value := DocuProperty.Value;
          except
            Value := '[Empty]';
          end;
          AItem := ListView1.Items.Add;
          AItem.Caption := DocuProperty.Name;
          AItem.SubItems.Add(Value);
        end;

        //ユーザ定義のプロパティ(CustomDocumentPropertie)があればリストに追加
        Properties := WordApp.ActiveDocument.CustomDocumentProperties;
        for i := 1 to Properties.Count do begin
          DocuProperty := Properties.Item[i];
          try
            Value := DocuProperty.Value;
          except
            Value := '[Empty]';
          end;
          AItem := ListView1.Items.Add;
          AItem.Caption := DocuProperty.Name;
          AItem.SubItems.Add(Value);
        end;
        ListView1.Items.EndUpdate;

        //左側の項目別プロパティの取得
        Panel1.Caption := OpenDialog1.FileName;
        WordDocu := WordApp.ActiveDocument;
        try
          //タイトル
          Value := WordDocu.BuiltInDocumentProperties[wdPropertyTitle];
          lblEdit01.Text := Value;
          //サブタイトル
          Value := WordDocu.BuiltInDocumentProperties[wdPropertySubject];
          lblEdit02.Text := Value;
          //会社名
          Value := WordDocu.BuiltInDocumentProperties[wdPropertyCompany];
          lblEdit03.Text := Value;
          //作成者
          Value := WordDocu.BuiltInDocumentProperties[wdPropertyAuthor];
          lblEdit04.Text := Value;
          //最終保存者
          Value := WordDocu.BuiltInDocumentProperties[wdPropertyLastAuthor];
          lblEdit05.Text := Value;
          //コメント
          Value := WordDocu.BuiltInDocumentProperties[wdPropertyComments];
          lblEdit06.Text := Value;

          //日付の場合,空であるとエラーになるのでtry〜exceptで処理
          try
            //作成日
            Value := WordDocu.BuiltInDocumentProperties[wdPropertyTimeCreated];
            lblEdit11.Text := Value;
            //最終更新日
            Value := WordDocu.BuiltInDocumentProperties[wdPropertyTimeLastSaved];
            lblEdit12.Text := Value;
            //最終印刷日付
            Value := WordDocu.BuiltInDocumentProperties[wdPropertyTimeLastPrinted];
            lblEdit13.Text := Value;
          except
          end; 

          //ユーザ定義プロパティ
          try
            Value := WordDocu.CustomDocumentProperties['送付先'];
            lblEdit07.Text := Value;
          except
            //このプロパティが存在しないと例外発生
          end;

          btnSave.Enabled   := True;
          btnDelete.Enabled := True;
        except
        end;
      finally
        //保存なしでワード終了
        WordApp.Quit(wdDoNotSaveChanges);
      end;
    end;
end;
//=============================================================================
//  プロパティ値の書込み
//  左側に表示しているプロパティとユーザ定義プロパティを定義して値をセット
//  ユーザ定義プロパティで使用可能なプロパティの種類は以下の通り
//  (Office2000.pas内での定義)
//  msoPropertyTypeBoolean   論理型
//  msoPropertyTypeDate      日付型
//  msoPropertyTypeFloat     実数型
//  msoPropertyTypeNumber    整数型
//  msoPropertyTypeString    文字列型
//=============================================================================
procedure TForm1.btnSaveClick(Sender: TObject);
var
    WordApp  : OleVariant;
    WordDocu : OleVariant;
    Value    : OleVariant;
begin
    WordApp := CreateOleObject('Word.Application');
    WordApp.Documents.Open(OpenDialog1.FileName);
    try
      WordDocu := WordApp.ActiveDocument;
      //タイトル
      Value := lblEdit01.Text;
      WordDocu.BuiltInDocumentProperties[wdPropertyTitle].Value := Value;
      //サブタイトル
      Value := lblEdit02.Text;
      WordDocu.BuiltInDocumentProperties[wdPropertySubject].Value := Value;
      //会社名
      Value := lblEdit03.Text;
      WordDocu.BuiltInDocumentProperties[wdPropertyCompany].Value := Value;
      //作成者
      Value := lblEdit04.Text;
      WordDocu.BuiltInDocumentProperties[wdPropertyAuthor].Value := Value;
      //最終保存者
      //実際には編集内容は変更されない.最終保存者はWordApp.Quitの時にワードが
      //が判断して更新する.DSOFile.dllとストレージによる操作であれば更新できる
      Value := lblEdit05.Text;
      WordDocu.BuiltInDocumentProperties[wdPropertyLastAuthor].Value := Value;
      //コメント
      Value := lblEdit06.Text;
      WordDocu.BuiltInDocumentProperties[wdPropertyComments].Value := Value;

      //プロパティを追加
      //値を設定しようとして例外発生ならプロパティなしと勝手に判断
      try
        WordDocu.CustomDocumentProperties['送付先'].Value := lblEdit07.Text;
      except
        WordDocu.CustomDocumentProperties.Add('送付先',
                                              False,
                                              msoPropertyTypeString,
                                              lblEdit07.Text,
                                              EmptyParam);
      end;
    finally
      //ワード文書を保存して終了
      WordApp.Quit(wdSaveChanges);
    end;
end;
//=============================================================================
//  ユーザ定義プロパティの削除
//
//  VBAのヘルプではDeleteメソッドなのであるが,何故かこのコードでは削除されない
//=============================================================================
procedure TForm1.btnDeleteClick(Sender: TObject);
var
    WordApp  : OleVariant;
    WordDocu : OleVariant;
begin
    WordApp := CreateOleObject('Word.Application');
    WordApp.Documents.Open(OpenDialog1.FileName);
    try
      WordDocu := WordApp.ActiveDocument;
      try
        WordDocu.CustomDocumentProperties['送付先'].Delete;
      except
        //該当プロパティが存在しない場合は例外発生
      end;
    finally
      //ワード文書を保存して終了
      WordDocu.Save;
      WordApp.Quit(wdSaveChanges);
    end;
end;

end.

[ 頁先頭 ]



07_エクセルのオブジェクトを使用


エクセルのオブジェクトを生成して,それを操作してプロパティを取得設定する例です.右のListViewには,カスタムプロパティを表示します.送付先がカスタムプロパティですが,他のサンプルプログラムでカスタムプロパティを作成している場合は,右のListViewに表示します.
[btnDelete]はカスタムプロパティの定義そのものを削除します.


  • 図18 
  • 設計時画面
  • [送付先]はカスタムプロパティ

  • 図19 
  • 右側のListViewにはカスタムプロパティのみを表示
  • 送付先以外は,他のサンプルプログラムで設定したもの

リスト7 
エクセルのオブジェクトを使用したプロパティの取得
unit FileProperties_ExcelObjectUnit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, Grids, ExtCtrls, ComCtrls, XPMan;

type
  TForm1 = class(TForm)
    Bevel1: TBevel;
    btnSave: TButton;
    btnRead: TButton;
    lblEdit01: TLabeledEdit;
    lblEdit02: TLabeledEdit;
    lblEdit03: TLabeledEdit;
    lblEdit04: TLabeledEdit;
    lblEdit05: TLabeledEdit;
    lblEdit06: TLabeledEdit;
    lblEdit07: TLabeledEdit;
    Panel1: TPanel;
    Panel2: TPanel;
    OpenDialog1: TOpenDialog;
    ListView1: TListView;
    lblEdit11: TLabeledEdit;
    lblEdit12: TLabeledEdit;
    lblEdit13: TLabeledEdit;
    btnDelete: TButton;
    procedure FormCreate(Sender: TObject);
    procedure btnReadClick(Sender: TObject);
    procedure btnSaveClick(Sender: TObject);
    procedure btnDeleteClick(Sender: TObject);
  private
    { Private 宣言 }
    BasePath : String;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

uses ComObj, Office2000;

{$R *.dfm}

//=============================================================================
//  初期設定
//  選択フォルダの初期値を設定
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
     BasePath := ExtractFileDir(Application.ExeName);
     BasePath := ExtractFileDir(BasePath);

     btnSave.Enabled   := False;
     btnDelete.Enabled := False;
     Panel2.Enabled    := False;
end;
//=============================================================================
//  プロパティ読出しボタン
//
//  エクセルのオブジェクトを作成し,文書を開いて(非表示)から操作するため,その
//  分のオーバヘッドがある.これはプロパティの書込みも同じ
//=============================================================================
procedure TForm1.btnReadClick(Sender: TObject);
var
    ExcelApp     : OleVariant;
    ExcelBook    : OleVariant;
    i            : Integer;
    Properties   : OleVariant;
    DocuProperty : OleVariant;
    Value        : OleVariant;
    AItem        : TListItem;
begin
    OpenDialog1.InitialDir := BasePath;
    OpenDialog1.Filter := 'Excel Book(*.xls)|*.xls';

    if OpenDialog1.Execute then begin
      lblEdit01.Text := '';
      lblEdit02.Text := '';
      lblEdit03.Text := '';
      lblEdit04.Text := '';
      lblEdit05.Text := '';
      lblEdit06.Text := '';
      lblEdit07.Text := '';
      lblEdit11.Text := '';
      lblEdit12.Text := '';
      lblEdit13.Text := '';
      Update;
      ListView1.Items.Clear;
      ListView1.Update;
      ListView1.Items.BeginUpdate;

      ExcelApp  := CreateOleObject('Excel.Application');
      ExcelBook := ExcelApp.Workbooks.Open(OpenDialog1.FileName);
      try
        //ユーザ定義のプロパティ(CustomDocumentPropertie)があればリストに追加
        Properties := ExcelBook.CustomDocumentProperties;
        for i := 1 to Properties.Count do begin
          DocuProperty := Properties.Item[i];
          try
            Value := DocuProperty.Value;
          except
            Value := '[Empty]';
          end;
          AItem := ListView1.Items.Add;
          AItem.Caption := DocuProperty.Name;
          AItem.SubItems.Add(Value);
        end;
        ListView1.Items.EndUpdate;

        //左側の項目別プロパティの取得
        Panel1.Caption := OpenDialog1.FileName;
        try
          //タイトル
          Value := ExcelBook.BuiltinDocumentProperties['Title'];
          lblEdit01.Text := Value;
          //サブタイトル
          Value := ExcelBook.BuiltInDocumentProperties['Subject'];
          lblEdit02.Text := Value;
          //会社名
          Value := ExcelBook.BuiltInDocumentProperties['Company'];
          lblEdit03.Text := Value;
          //作成者
          Value := ExcelBook.BuiltInDocumentProperties['Author'];
          lblEdit04.Text := Value;
          //最終保存者
          Value := ExcelBook.BuiltInDocumentProperties['Last Author'];
          lblEdit05.Text := Value;
          //コメント
          Value := ExcelBook.BuiltInDocumentProperties['Comments'];
          lblEdit06.Text := Value;

          //日付の場合,空であるとエラーになるのでtry〜exceptで処理
          try
            //作成日
            Value := ExcelBook.BuiltInDocumentProperties['Creation Date'];
            lblEdit11.Text := Value;
            //最終更新日
            Value := ExcelBook.BuiltInDocumentProperties['Last Save Time'];
            lblEdit12.Text := Value;
            //最終印刷日付
            Value := ExcelBook.BuiltInDocumentProperties['Last Print Date'];
            lblEdit13.Text := Value;
          except
          end;

          //ユーザ定義プロパティ
          try
            Value := ExcelBook.CustomDocumentProperties['送付先'];
            lblEdit07.Text := Value;
          except
            //このプロパティが存在しないと例外発生
          end;

          btnSave.Enabled   := True;
          btnDelete.Enabled := True;
        except
          raise;
        end;
      finally
        //保存なしエクセル終了
        ExcelApp.Quit;
      end;
    end;
end;
//=============================================================================
//  プロパティ値の書込み
//  左側に表示しているプロパティとユーザ定義プロパティを定義して値をセット
//  ユーザ定義プロパティで使用可能なプロパティの種類は以下の通り
//  (Office2000.pas内での定義)
//  msoPropertyTypeBoolean   論理型
//  msoPropertyTypeDate      日付型
//  msoPropertyTypeFloat     実数型
//  msoPropertyTypeNumber    整数型
//  msoPropertyTypeString    文字列型
//=============================================================================
procedure TForm1.btnSaveClick(Sender: TObject);
var
    ExcelApp  : OleVariant;
    ExcelBook : OleVariant;
    Value     : OleVariant;
begin
    ExcelApp  := CreateOleObject('Excel.Application');
    ExcelBook := ExcelApp.Workbooks.Open(OpenDialog1.FileName);
    //保存確認のダイアログを表示させない
    ExcelApp.DisplayAlerts:=False;

    try
      //タイトル
      Value := lblEdit01.Text;
      ExcelBook.BuiltInDocumentProperties['Title'].Value := Value;
      //サブタイトル
      Value := lblEdit02.Text;
      ExcelBook.BuiltInDocumentProperties['Subject'].Value := Value;
      //会社名
      Value := lblEdit03.Text;
      ExcelBook.BuiltInDocumentProperties['Company'].Value := Value;
      //作成者
      Value := lblEdit04.Text;
      ExcelBook.BuiltInDocumentProperties['Author'].Value := Value;
      //最終保存者
      //実際には編集内容は変更されない.最終保存者はExcelBook.Saveの時にエクセ
      //ルが判断して更新する.DSOFile.dllとストレージによる操作であれば更新できる
      Value := lblEdit05.Text;
      ExcelBook.BuiltInDocumentProperties['Last Author'].Value := Value;
      //コメント
      Value := lblEdit06.Text;
      ExcelBook.BuiltInDocumentProperties['Comments'].Value := Value;

      //プロパティを追加
      //値を設定しようとして例外発生ならプロパティなしと勝手に判断
      try
        ExcelBook.CustomDocumentProperties['送付先'].Value := lblEdit07.Text;
      except
        ExcelBook.CustomDocumentProperties.Add('送付先',
                                              False,
                                              msoPropertyTypeString,
                                              lblEdit07.Text,
                                              EmptyParam);
      end;
    finally
      //エクセルのブックを保存してエクセル終了
      ExcelBook.Save;
      ExcelApp.Quit;
    end;
end;
//=============================================================================
//  ユーザ定義プロパティの削除
//=============================================================================
procedure TForm1.btnDeleteClick(Sender: TObject);
var
    ExcelApp  : OleVariant;
    ExcelBook : OleVariant;
begin
    ExcelApp  := CreateOleObject('Excel.Application');
    ExcelBook := ExcelApp.Workbooks.Open(OpenDialog1.FileName);
    //保存確認のダイアログを表示させない
    ExcelApp.DisplayAlerts:=False;

    try
      try
        ExcelBook.CustomDocumentProperties['送付先'].Delete;
      except
      end;
    finally
      //エクセルのブックを保存してエクセル終了
      ExcelBook.Save;
      ExcelApp.Quit;
    end;
end;

end.

[ 頁先頭 ]



08_構造化ストレージ操作用定数ユニット


このぺージのサンプルプログラムで使用しているファイルです.共通に使用するために,このサンプルプログラムのルートに収めてあります.このコードを使用しているサンプルプログラムのプロジェクトに追加しています.


リスト8 
リスト10
のplFileInfo_Const.pasはプロジェクトに追加されているので注意
program FileProperties_Storage;

uses
  Forms,
  FileProperties_StorageUnit in 'FileProperties_StorageUnit.pas' {Form1},
  plFileInfo_Const in '..\plFileInfo_Const.pas';

{$R *.res}

begin
  Application.Initialize;
  //Delphi2007以上
  {$IF CompilerVersion > 18.49}
  Application.MainFormOnTaskbar := True;
  {$IFEND}
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.


リスト9 
構造化ストレージ用のコード
unit plFileInfo_Const;

interface

uses Windows, ComObj,ActiveX, Classes;

const
//-----------------------------------------------------------------------------
//  プロパティセットのカテゴリのGUID
//  直接GUIDで指定しないでここでは定数名で使用するために定義
//  どのGUIDがどんなファイルに対応するか正確には不明
//
//  これらのGUIDは全てが,また全ての環境で(レジストリに)登録されているわけでは
//  ない.オーディオ関係のアプリがインストールされていなければ,該当する情報は
//  レジストリに登録されないので使用できない.
//  つまり,どのような機能がそのPCにインストールされているかによる.
//
//  FMTID_SummaryInfo
//     ファイルのプロパティで概要タブで扱うプロパティセット
//  FMTID_DocSummaryInfo
//     主にワード等が使用するプロパティセット
//  FMTID_UserDefinedProperties
//     [ファイル][プロパティ]のカスタムタブで扱うプロパティセット
//  FMTID_ImageSummaryInfo
//     イメージファイル関係
//  FMTID_MusicFileInfo
//     音楽ファイル関係
//  FMTID_AudioFileInfo
//     オーディオファイル関係
//  FMTID_VideoFileInfo
//     ビデオファイル関係
//  FMTID_MediaFileInfo
//     メディアファイル関係
//
//  実際のプロパティの値は,このGUIDと下の[各プロパティ変数]の組合わせを使用する
//-----------------------------------------------------------------------------

  FMTID_SummaryInfo           : TGUID='{F29F85E0-4FF9-1068-AB91-08002B27B3D9}';
  FMTID_DocSummaryInfo        : TGUID='{D5CDD502-2E9C-101B-9397-08002B2CF9AE}';
  FMTID_DiscardableInfo       : TGUID='{D725EBB0-C9B8-11D1-89BC-0000F804B057}';
  FMTID_UserDefinedProperties : TGUID='{D5CDD505-2E9C-101B-9397-08002B2CF9AE}';
  FMTID_ImageSummaryInfo      : TGUID='{6444048F-4C8B-11D1-8B70-080036B11A03}';
  FMTID_MusicFileInfo         : TGUID='{56A3372E-CE9C-11D2-9F0E-006097C686F6}';
  FMTID_AudioFileInfo         : TGUID='{64440490-4C8B-11D1-8B70-080036B11A03}';
  FMTID_VideoFileInfo         : TGUID='{64440491-4C8B-11D1-8B70-080036B11A03}';
  FMTID_MediaFileInfo         : TGUID='{64440492-4C8B-11D1-8B70-080036B11A03}';

//-----------------------------------------------------------------------------
//  IPropertySetStorageのGUID
//-----------------------------------------------------------------------------

  IID_IPropertySetStorage: TGUID ='{0000013A-0000-0000-C000-000000000046}';

//-----------------------------------------------------------------------------
//  各プロパティのID値の定義
//  FMTID_Summary Informationの定義はActiveX.pasで定義されているが再定義
//  (ActiveX.pas内での定数名はPIDSI_XXXXX)
//  定数名は,極力,ネット上にある参考コードと同じになるようにしているが,.NET
//  では,これらの定数名の定義が設定されているようである
//  正確な日本語表記名は不明
//  説明の参考リンク
//  http://msdn2.microsoft.com/en-us/library/ms690941.aspx
//
//  VT_XXXは変数の型.記載がないのは不明.変数の型には以下もあり
//  VT_EMPTY,VT_NULL,VT_VOID  空またはプロパティがない?
//  VT_R4,VT_R8               実数値
//  VT_ERROR                  エラー値(整数)
//-----------------------------------------------------------------------------

  // Summary Info用
  PID_TITLE            = 2;  // VT_LPSTR,タイトル
  PID_SUBJECT          = 3;  // VT_LPSTR,サブタイトル,表題
  PID_AUTHOR           = 4;  // VT_LPSTR,作成者,著作
  PID_KEYWORDS         = 5;  // VT_LPSTR,キーワード
  PID_COMMENTS         = 6;  // VT_LPSTR,コメント
  PID_TEMPLATE         = 7;  // VT_LPSTR,テンプレート
  PID_LASTAUTHOR       = 8;  // VT_LPSTR,前回保存者
  PID_REVNUMBER        = 9;  // 改定番号
  PID_EDITTIME         = 10// VT_FILETIME(UTC),編集時間
  PID_LASTPRINTED      = 11// VT_FILETIME(UTC),最終印刷日時
  PID_CREATE_DTM       = 12// VT_FILETIME(UTC),作成日時
  PID_LASTSAVE_DTM     = 13// VT_FILETIME(UTC),最終保存日時
  PID_PAGECOUNT        = 14// VT_I4,頁数
  PID_WORDCOUNT        = 15// VT_I4,単語数
  PID_CHARCOUNT        = 16// VT_I4,文字数
  PID_THUMBNAIL        = 17// VT_CF,サムネイル
  PID_APPNAME          = 18// VT_LPSTR,アプリケーション名
  PID_SECURITY         = 19// VT_I4,セキュリティ

  // Document Summary Info用
  PID_CATEGORY         = 2;  // VT_LPSTR,カテゴリ
  PID_PRESFORMAT       = 3;  // VT_LPSTR
  PID_BYTECOUNT        = 4;  // VT_I4
  PID_LINECOUNT        = 5;  // VT_I4,行数
  PID_PARCOUNT         = 6;  // VT_I4 
  PID_SLIDECOUNT       = 7;  // VT_I4,スライド数
  PID_NOTECOUNT        = 8;  // VT_I4
  PID_HIDDENCOUNT      = 9;  // VT_I4
  PID_MMCLIPCOUNT      = 10// VT_I4
  PID_SCALE            = 11// VT_BOOL
  PID_HEADINGPAIR      = 12// VT_VARIANT or VT_VECTOR
  PID_DOCPARTS         = 13// VT_LPSTR or VT_VECTOR
  PID_MANAGER          = 14// VT_LPSTR
  PID_COMPANY          = 15// VT_LPSTR,会社名
  PID_LINKSDIRTY       = 16// VT_BOOL,未更新のリンクオブジェクト
  PID_CHARCOUNT2       = 17//

  // FMTID_ImageSummaryInfo用
  PIDISI_FILETYPE      = 2;  // VT_LPWSTR,ファイルの種類
  PIDISI_CX            = 3;  // VT_UI4,幅
  PIDISI_CY            = 4;  // VT_UI4,高さ
  PIDISI_RESOLUTIONX   = 5;  // VT_UI4,水平方向の解像度
  PIDISI_RESOLUTIONY   = 6;  // VT_UI4.垂直方向の解像度
  PIDISI_BITDEPTH      = 7;  // VT_UI4,ビットの深さ
  PIDISI_COLORSPACE    = 8;  // VT_LPWSTR
  PIDISI_COMPRESSION   = 9;  // VT_LPWSTR,圧縮の有無
  PIDISI_TRANSPARENCY  = 10// VT_UI4
  PIDISI_GAMMAVALUE    = 11// VT_UI4,ガンマ値
  PIDISI_FRAMECOUNT    = 12// VT_UI4,フレーム数
  PIDISI_DIMENSIONS    = 13// VT_LPWSTR

  // FMTID_MusicFileInfo用
  // 3はhttp://msdn2.microsoft.com/en-us/library/ms690941.aspxには定義なし
  PIDSI_ARTIST         = 2;  // アーチストの名前
  PIDSI_SONGTITLE      = 3;  // 定義なし?
  PIDSI_ALBUM          = 4;  // アルバム名
  PIDSI_YEAR           = 5;  // アルバムが記録された年
  PIDSI_COMMENT        = 6;  // コメント
  PIDSI_TRACK          = 7;  // アルパムのトラック番号
  PIDSI_GENRE          = 11// アルバムのジャンル
  PIDSI_LYRICS         = 12// 音楽ファイルの歌詞

  // FMTID_VideoFileInfo用
  PIDVSI_STREAM_NAME   = 2;  // VT_LPWSTR,ビデオの名前,StreamName
  PIDVSI_FRAME_WIDTH   = 3;  // VT_UI4,幅,FrameWidth
  PIDVSI_FRAME_HEIGHT  = 4;  // VT_UI4,高さ,FrameHeight
  PIDVSI_TIMELENGTH    = 7;  // VT_UI4,長さ,TimeLength (milliseconds)
  PIDVSI_FRAME_COUNT   = 5;  // VT_UI4,フレーム数,FrameCount
  PIDVSI_FRAME_RATE    = 6;  // VT_UI4,フレーム率,FrameRate (frames/millisecond)
  PIDVSI_DATA_RATE     = 8;  // VT_UI4,ビットレート,DataRate (bps,bytes/second)
  PIDVSI_SAMPLE_SIZE   = 9;  // VT_UI4,SampleSize
  PIDVSI_COMPRESSION   = 10// VT_LPWSTR,圧縮レベル,Compression
  PIDVSI_STREAM_NUMBER = 11// VT_UI2,StreamNumber

  // FMTID_AudioFileInfo用
  PIDASI_FORMAT        = 2;  // VT_BSTR
  PIDASI_TIMELENGTH    = 3;  // VT_UI4,(milliseconds)
  PIDASI_AVG_DATA_RATE = 4;  // VT_UI4,(Hz)
  PIDASI_SAMPLE_RATE   = 5;  // VT_UI4,(bits)
  PIDASI_SAMPLE_SIZE   = 6;  // VT_UI4,(bits)
  PIDASI_CHANNEL_COUNT = 7;  // VT_UI4
  PIDASI_STREAM_NUMBER = 8;  // VT_UI2
  PIDASI_STREAM_NAME   = 9;  // VT_LPWSTR
  PIDASI_COMPRESSION   = 10// VT_LPWSTR

  //FMTID_MediaFileInfo用
  PIDMSI_EDITOR        = 2;  // VT_LPWSTR
  PIDMSI_SUPPLIER      = 3;  // VT_LPWSTR
  PIDMSI_SOURCE        = 4;  // VT_LPWSTR
  PIDMSI_SEQUENCE_NO   = 5;  // VT_LPWSTR
  PIDMSI_PROJECT       = 6;  // VT_LPWSTR
  PIDMSI_STATUS        = 7;  // VT_UI4
  PIDMSI_OWNER         = 8;  // VT_LPWSTR
  PIDMSI_RATING        = 9;  // VT_LPWSTR
  PIDMSI_PRODUCTION    = 10// VT_FILETIME(UTC)
  PIDMSI_COPYRIGHT     = 11// VT_LPWSTR 

//-----------------------------------------------------------------------------
//  StgOpenStorageEx関数の第3引数.ストレージファイルのフォーマット
//
//  STGFMT_STORAGE  必ずワード等の複合ファイルである
//  STGFMT_FILE     必ずしも複合ファイルではないことを指定.現在未サポート 
//  STGFMT_ANY      ファイル形式をシステムが決定し,適当な構造化ストレージやプ
//                  ロパティセットの実装を使用
//  STGFMT_DOCFILE  STGFMT_STORAGE同様にファイルが必ず複合ファイルであることを
//                  指定.古い形式の複合ファイル用か?
//-----------------------------------------------------------------------------

  STGFMT_STORAGE = 0;
  STGFMT_FILE    = 3;
  STGFMT_ANY     = 4;
  STGFMT_DOCFILE = 5;

//-----------------------------------------------------------------------------
//  ファイルシステム上の既存のストレージオブジェクトを開く関数
//  ワード等の複合ファイルを開くためにも,通常のファイルを開くためにも使用可能
//  ActiveX.pasにはこの関数がないため,定義して使用.
//  (Delphi7の場合,StgOpenStorage関数はあるが,MicrosoftではWindows2000以降の
//  アプリはこのStgOpenStorageEx関数を使うべきとしている.
//
//  pwcsName    : フルパスで指定.文字数はMAX_PATHを越えてはいけない
//  grfMode     : このオブジェクトのアクセスモード.各グループから一つ指定
//                Access group
//                STGM_READ      読取専用
//                STGM_WRITE     現在未サポート
//                STGM_READWRITE 読書き両用
//                Sharing group
//                STGM_SHARE_DENY_NONE  後発のオブジェクト読み書きアクセスを拒否
//                                      しない 
//                STGM_SHARE_DENY_READ  後発のSTGM_READモードの取得を阻止する
//                                      通常ストレージオブジェクトに使用
//                STGM_SHARE_DENY_WRITE 後発のSTGM_WRITE,STGM_READWRITEアクセス
//                                      モードでのオブジェクトの取得を阻止する
//                                      複数のユーザによる操作禁止に使用される
//                STGM_SHARE_EXCLUSIVE  STGM_SHARE_DENY_READと
//                                      STGM_SHARE_DENY_WRITEとの組合わせ
//                                      後発のあらゆるアクセスモードでのオブジェ
//                                      クトの取得を阻止する
//                STGM_PRIORITY         排他アクセスで開く指定
//                Direct SWMR and Simple group
//                STGM_SIMPLE           複合ファイルのより高速な実装を提供.
//                                      よく使用される(制限があるらしい)
//  stgfmt      : ストレージファイルフォーマット.通常0で可
//  grfAttrs    : 予約.0を指定
//  pStgOptions : STGOPTIONS ポインタのアドレス.通常nil
//  reserved2   : 予約.nilを指定
//  riid        : インタフェースポインタのGUID
//                通常はID IPropertySetStorageでよい
//  stgOpen     : インタフェースポインタのアドレス
//                開かれたストレージオブジェクトのインタフェースポインタを受け
//                取るポインタ変数のアドレス.
//                オープンに失敗すると0を返す
//
//  戻値
//  正常終了の場合はS_OKを返す
//  STG_E_INVALIDPOINTER  stgOpenパラメータのポインタが無効
//  STG_E_INVALIDPOINTER  pStgOptionsパラメータのポインタが無効
//  E_NOINTERFACE         指定されたインタフェースはサポートされていない
//  STG_E_INVALIDFLAG     grfMode ポインタのフラグの組み合わせが無効
//  STG_E_INVALIDNAME     pwcsName パラメータの名前が無効
//  STG_E_LOCKVIOLATION   ファイルが開かれロックしているためアクセス拒否  
//  STG_E_SHAREVIOLATION  同上
//  STG_E_INCOMPLETE      高度に隠れているデバイス(?)のためファイルが開けない
//  STG_E_ACCESSDENIED   ユーザアクセスを許可していないためファイルが開けない
//
//  [参考]
//  新しいストレージファイルの作成はStgCreateStorageEx関数
//-----------------------------------------------------------------------------
function StgOpenStorageEx (
         const pwcsName : POleStr;
         grfMode : LongInt;
         stgfmt : DWORD;
         grfAttrs : DWORD;
         pStgOptions : Pointer;
         reserved2 : Pointer;
         riid : PGUID;
         out stgOpen : IStorage) : HResult; stdcall; external 'ole32.dll';

implementation

end.




[ 頁先頭 ] [前のページ][次のページ]