[BlueLeaf1336]> PROBLEMS> DelphiでShellオブジェクトを使う>

Folderオブジェクト

historyTOP

2006/06/01:作成

2006/06/01TOP

Shellオブジェクトを使って、フルパスを指定するか(Shell.NameSpace)、フォルダ選択ダイアログ(Shell.BrowseForFolder)を使うことで、Folderオブジェクトを取得することができます。

今回は、Folderオブジェクトを取り出すのと、取り出したFolderオブジェクトのTitleプロパティ(早い話フォルダ名)と、ParentFolderメソッド(親フォルダのFolderオブジェクト取得)だけを試しています。

にもかかわらず、無駄にコードが長いのは、フォルダ選択ダイアログのための定数宣言のためです。Delphi6のShlObj.pasをusesすればある程度はカバーできているのですが、WindowsXPからと思われる新しい宣言がサポートされていなかったので、Platform SDKのヘッダを変換したためです。

それから、Folderオブジェクトですが、嘘っぱちのパスを指定した場合やフォルダ選択ダイアログでキャンセルをクリックした場合、$00000000という値がOleVariantで宣言した変数に入ります。これが厄介で、Unassignedでもnilでも0でもありません。

あと、ついでだったのと簡単だったので、新しいフォルダを作成する(Folder.NewFolder)も試しています。

    if (FolderObj <> 0) then
    if (not VarIsNull(FolderObj)) then
    if (not VarIsEmpty(FolderObj)) then

そのため、上のような方法でFolderオブジェクトの値を確認すると、例外が発生します。正しい(らしい)判定方法は、Delphi-MLに書いてあった、次のような比較です。実際、この方法では例外が発生せず判定できます。また、このコードが示されたレスの中で、なぜこの方法が正しいと思われるかの説明もしてありました。

    if (IDispatch(Folder) <> nil) then

それはそれとして、Folderオブジェクトには、CopyHere(そのFolderオブジェクトの示すフォルダに、フォルダやファイルをコピーする)、MoveHere(コピーじゃなくて移動)というメソッドもありますが、それを使うにはまだ試していないFolderItemオブジェクトを指定しなくちゃいけないし、邪魔くさそうなので無視する方向で。

Level2.zip(168,214Bytes) ソースコードと実行ファイルです。

コードTOP

uses
    ComObj, Variants;

{$R *.dfm}

//  http://www2.moug.net/bbs/wordvba/20060517000002.htm
//  http://leed.issp.u-tokyo.ac.jp/~takeuchi/delphi/article/043/043760.html
//  http://pc.2ch.net/tech/kako/1019/10196/1019654975.html
//  ms-help://MS.PSDK.1033/shellcc/platform/shell/reference/objects/shell/shell.htm
//  ms-help://MS.PSDK.1033/shellcc/platform/shell/reference/objects/shell/browseforfolder.htm
//  ms-help://MS.PSDK.1033/shellcc/platform/shell/reference/structures/browseinfo.htm
//  Subject: [Delphi:81788] Re: OLE Object  がObject を返す場合の処理

//-----------------------------------------------------------------------------
//  特殊フォルダを列挙
type
    TShellSpecialFolderConstants =
    (
        ssfALTSTARTUP = $1d,
        ssfAPPDATA = $1a,
        ssfBITBUCKET = $a,
        ssfCOMMONALTSTARTUP = $1e,
        ssfCOMMONAPPDATA = $23,
        ssfCOMMONDESKTOPDIR = $19,
        ssfCOMMONFAVORITES = $1f,
        ssfCOMMONPROGRAMS = $17,
        ssfCOMMONSTARTMENU = $16,
        ssfCOMMONSTARTUP = $18,
        ssfCONTROLS = $3,
        ssfCOOKIES = $21,
        ssfDESKTOP = $0,
        ssfDESKTOPDIRECTORY = $10,
        ssfDRIVES = $11,
        ssfFAVORITES = $6,
        ssfFONTS = $14,
        ssfHISTORY = $22,
        ssfINTERNETCACHE = $20,
        ssfLOCALAPPDATA = $1c,
        ssfMYPICTURES = $27,
        ssfNETHOOD = $13,
        ssfNETWORK = $12,
        ssfPERSONAL = $5,
        ssfPRINTERS = $4,
        ssfPRINTHOOD = $1b,
        ssfPROFILE = $28,
        ssfPROGRAMFILES = $26,
        ssfPROGRAMS = $2,
        ssfRECENT = $8,
        ssfSENDTO = $9,
        ssfSTARTMENU = $b,
        ssfSTARTUP = $7,
        ssfSYSTEM = $25,
        ssfTEMPLATES = $15,
        ssfWINDOWS = $24
    );

//-----------------------------------------------------------------------------
//  フォルダの選択ダイアログのための定数宣言
const
    //  (多分)普通のフォルダ以外は選択できない
    BIF_RETURNONLYFSDIRS   = $0001;

    //  (多分)コンピュータの検索で、共有フォルダはだめ
    BIF_DONTGOBELOWDOMAIN  = $0002;

    //  ステータステキストをつけられる。(多分)いろいろする必要あり
    BIF_STATUSTEXT         = $0004;
    
    //  (多分)指定したルートフォルダ直下のサブフォルダだけ選択できる
    BIF_RETURNFSANCESTORS  = $0008;

    //  Version 4.71. 選択ダイアログにエディットボックスをつけられる
    BIF_EDITBOX            = $0010;

    //  Version 4.71. エディットボックスに変な内容が入力されたときに判断できる
    BIF_VALIDATE           = $0020;

    //  Version 5.0. 新しいタイプのダイアログ
    BIF_NEWDIALOGSTYLE     = $0040;

    //  Version 5.0. エディットボックスありの新しいタイプのダイアログ
    BIF_USENEWUI           = (BIF_NEWDIALOGSTYLE or BIF_EDITBOX);

    //  Version 5.0. いろいろ条件付でURLを表示・選択できる。BIF_USENEWUI必須
    BIF_BROWSEINCLUDEURLS  = $0080;

    //  Version 6.0. エディットボックスにヒントを出せる。BIF_NEWDIALOGSTYLE必須
    BIF_UAHINT             = $0100;

    //  Version 6.0. 「新しいフォルダ」ボタンなし。BIF_NEWDIALOGSTYLE必須
    BIF_NONEWFOLDERBUTTON  = $0200;

    //  Version 6.0. ショートカット自体を選択できる
    BIF_NOTRANSLATETARGETS = $0400;

    //  コンピュータだけを選択できる
    BIF_BROWSEFORCOMPUTER  = $1000;

    //  プリンタだけを選択できる
    BIF_BROWSEFORPRINTER   = $2000;

    //  Version 4.71. ファイルも表示
    BIF_BROWSEINCLUDEFILES = $4000;

    //  Version 5.0. 共有フォルダも選択できる。BIF_NEWDIALOGSTYLE 必須
    BIF_SHAREABLE          = $8000;

//-----------------------------------------------------------------------------
//  Shell.NameSpace / Folder.Title / Folder.ParentFolder  
procedure TForm1.Button1Click(Sender: TObject);
var
    Shell: OleVariant;
    Path: String;
    Title: String;
    Folder: OleVariant;
begin
    Shell := CreateOleObject('Shell.Application');

    //  Folderオブジェクトとして扱うフォルダのパス
    Path := ExtractFilePath(ParamStr(0));

    //-------------------------------------------------------------------------
    //  指定したパスのFolderオブジェクト取得
    Folder := Shell.NameSpace(OleVariant(Path));
    //  Folderオブジェクトのタイトル取得
    Title := Folder.Title;

    LblPath.Caption := Path;
    LblTitle.Caption := Title;

    //-------------------------------------------------------------------------
    //  親フォルダ取り出し
    Folder := Folder.ParentFolder;
    //  Folderオブジェクトのタイトル取得
    Title := Folder.Title;

    LblParentTitle.Caption := Title;

    //-------------------------------------------------------------------------
    //  特殊フォルダのFolderオブジェクト取得
    Folder := Shell.NameSpace(Integer(ssfMYPICTURES));
    //  Folderオブジェクトのタイトル取得
    Title := Folder.Title;

    LblSpecialPath.Caption := 'ssfMYPICTURES';
    LblSpecialTitle.Caption := Title;

    Folder := Unassigned;
    Shell := Unassigned;
end;

//-----------------------------------------------------------------------------
//  Folder.NewFolder
procedure TForm1.Button2Click(Sender: TObject);
var
    Shell: OleVariant;
    Path: String;
    Folder: OleVariant;
begin
    Shell := CreateOleObject('Shell.Application');
    Path := ExtractFilePath(ParamStr(0));
    Folder := Shell.NameSpace(OleVariant(Path));

    //  適当な名前のフォルダを作成する
    Path := CreateClassID();
    LblNewFolderPath.Caption := Path;

    //  フォルダ作成実行
    Folder.NewFolder(Path);

    Folder := Unassigned;
    Shell := Unassigned;
end;

//-----------------------------------------------------------------------------
//  Shell.BrowseForFolder
procedure TForm1.Button3Click(Sender: TObject);
var
    Shell: OleVariant;
    Path: String;
    Title: String;
    Folder: OleVariant;
    Flags: UINT;
begin
    Shell := CreateOleObject('Shell.Application');
    Path := ExtractFilePath(ParamStr(0));

    //  フラグ設定
    Flags := 0
         //or BIF_RETURNONLYFSDIRS      //  (多分)普通のフォルダ以外は選択不可
         //or BIF_DONTGOBELOWDOMAIN     //  (多分)コンピュータの検索で、共有フォルダ不可
         //or BIF_STATUSTEXT            //  ステータステキストをつけられる
         //or BIF_RETURNFSANCESTORS     //  (多分)ルートフォルダ直下のサブフォルダだけ
         //or BIF_EDITBOX               //  エディットボックスをつけられる
         //or BIF_VALIDATE              //  エディットボックスの入力チェック
         //or BIF_NEWDIALOGSTYLE        //  新しいタイプのダイアログ
         or BIF_USENEWUI                //  エディットボックスありの新しいタイプのダイアログ
         //or BIF_BROWSEINCLUDEURLS or BIF_USENEWUI //  いろいろ条件付でURLを表示・選択できる。
         //or BIF_UAHINT or BIF_NEWDIALOGSTYLE      //  エディットボックスにヒントを出せる。
         //or BIF_NONEWFOLDERBUTTON or BIF_NEWDIALOGSTYLE   //  「新しいフォルダ」ボタンなし。
         //or BIF_NOTRANSLATETARGETS                //  ショートカット自体を選択できる
         //or BIF_BROWSEFORCOMPUTER                 //  コンピュータだけ
         //or BIF_BROWSEFORPRINTER                  //  プリンタだけ
         //or BIF_BROWSEINCLUDEFILES                //  ファイルも表示
         //or BIF_SHAREABLE or BIF_NEWDIALOGSTYLE   //  共有フォルダも
         ;

    //-------------------------------------------------------------------------
    //  フォルダ選択ダイアログ
    Folder := Shell.BrowseForFolder(
        0,
        'ルートフォルダに ssfDESKTOP を指定',
        Flags,
        ssfDESKTOP
        );

    //  そのフォルダのタイトル取得
    if (IDispatch(Folder) <> nil) then
    begin
        Title := Folder.Title;
        LblSelectedTitle.Caption := Title;
    end;

    //-------------------------------------------------------------------------
    //  フォルダ選択ダイアログ
    Folder := Shell.BrowseForFolder(
        0,
        'ルートフォルダに C:\Windows\ を指定',
        Flags,
        'C:\Windows\'
        );

    //  そのフォルダのタイトル取得
    if (IDispatch(Folder) <> nil) then
    begin
        Title := Folder.Title;
        LblSelectedTitle2.Caption := Title;
    end;

    Folder := Unassigned;
    Shell := Unassigned;
end;

EOFTOP