C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[4]: IExtractImageによるサムネイルの取得


(過去ログ 12 を表示中)

[トピック内 17 記事 (1 - 17 表示)]  << 0 >>

■3122 / inTopicNo.1)  IExtractImageによるサムネイルの取得
  
□投稿者/ zen (1回)-(2007/04/24(Tue) 09:42:58)

分類:[C# (Windows)] 

エクスプローラーで「表示→縮小版」を選択した際に表示されるサムネイルを取得する
方法として、IExtractImageを用いました。
パワーポイントもエクセルもワードも動画ファイルもエクスプローラで「縮小版」時に
サムネイルが出る物ならなんでもとれるようになった・・・と思ったのですが、
何故かPDFだけ、取得できません。エクスプローラ上ではサムネイルが表示されているのですが・・・
素材の元にさせていただいたVB6のアプリでちゃんとPDFのサムネイルもとれるのですが・・・
(そのVB6のソースをC#に変換したつもりなのですが・・・)
いろいろ調べたつもりなのですが、どうしてもわかりません。

ご教授いただけないでしょうか。よろしくお願いします。

private bool showThumbnail(string fileName)
{
    IShellFolder ishell = null;
    string folder = "";
    System.IntPtr ppidl; 
    uint pdwAttributes = 0;
    uint pchEaten = 0;
    IExtractImage ieimg = null;
    IntPtr phBmpThumbnail = IntPtr.Zero;

    folder = fileName.Substring(0,fileName.LastIndexOf("\\"))+"\\";
    fileName = fileName.Substring(fileName.LastIndexOf("\\")+1);

    ishell = ShellFunctions.GetDesktopFolder();
    ishell.ParseDisplayName(IntPtr.Zero,System.IntPtr.Zero,folder,ref pchEaten ,out ppidl,ref pdwAttributes);

    if (ppidl!=System.IntPtr.Zero)
    {
        mobjDesktop.BindToObject(ppidl,System.IntPtr.Zero,ref rid,ref ishell);
        ShellFunctions.GetMalloc().Free(ppidl);
        ppidl=System.IntPtr.Zero;
    }
    if (ishell==null)
    {
        return false;
    }

    ishell.ParseDisplayName(IntPtr.Zero,IntPtr.Zero,fileName,ref pchEaten,out ppidl,ref pdwAttributes);

    pchEaten = 0;
    if (ppidl!=IntPtr.Zero)
    {
        ishell.GetUIObjectOf(IntPtr.Zero, 1, ref ppidl, ref irid, ref pchEaten, out ieimg);
        
        if (ieimg!=null)
        {
            StringBuilder sb = new StringBuilder(1024);
            SIZE size = new SIZE();
            size.cx = 96;
            size.cy = 96;
            int pdwPriority = 0;
            int pdwFlags = (int)(EIEIFLAG.IEIFLAG_ORIGSIZE|EIEIFLAG.IEIFLAG_SCREEN);;
            ieimg.GetLocation(sb,sb.Capacity,ref pdwPriority,ref size,32,ref pdwFlags);
            this.label1.Text = sb.ToString();
            ieimg.Extract(out phBmpThumbnail);
        }
        ShellFunctions.GetMalloc().Free(ppidl);
    }
    
    if (phBmpThumbnail!=IntPtr.Zero)
    {
        Image img = null;
        if (this.pictureBox1.Image!=null)
        {
            img = this.pictureBox1.Image;
            this.pictureBox1.Image = null;
            img.Dispose();
        }
        img = Image.FromHbitmap(phBmpThumbnail);
        this.pictureBox1.Image = img;
    }

    if (ishell!=null)
    {
        Marshal.ReleaseComObject(ishell);
    }
    if (ieimg!=null)
    {
        Marshal.ReleaseComObject(ieimg);
    }

    return true;
}

引用返信 編集キー/
■3126 / inTopicNo.2)  Re[1]: IExtractImageによるサムネイルの取得
□投稿者/ シャノン (137回)-(2007/04/24(Tue) 12:11:44)
2007/04/24(Tue) 12:58:41 編集(投稿者)

No3122 (zen さん) に返信
> エクスプローラーで「表示→縮小版」を選択した際に表示されるサムネイルを取得する
> 方法として、IExtractImageを用いました。
> パワーポイントもエクセルもワードも動画ファイルもエクスプローラで「縮小版」時に
> サムネイルが出る物ならなんでもとれるようになった・・・と思ったのですが、
> 何故かPDFだけ、取得できません。エクスプローラ上ではサムネイルが表示されているのですが・・・
> 素材の元にさせていただいたVB6のアプリでちゃんとPDFのサムネイルもとれるのですが・・・
> (そのVB6のソースをC#に変換したつもりなのですが・・・)
> いろいろ調べたつもりなのですが、どうしてもわかりません。
>
> ご教授いただけないでしょうか。よろしくお願いします。

まずは、そのVB6アプリのある場所を載せてください。
#VB6を移植しただけだといろいろマズそう…。
引用返信 編集キー/
■3128 / inTopicNo.3)  Re[2]: IExtractImageによるサムネイルの取得
□投稿者/ zen (2回)-(2007/04/24(Tue) 13:04:05)

> まずは、そのVB6アプリのある場所を載せてください。

サンプルにさせていただいたVB6のソースは
http://www.koalanet.ne.jp/~akiya/vbtaste/vbp/
です。
これを元にしてC#にしました。

あとはC#,IExtractImageでググって部品を集めて・・・

引用返信 編集キー/
■3130 / inTopicNo.4)  Re[3]: IExtractImageによるサムネイルの取得
□投稿者/ zen (3回)-(2007/04/24(Tue) 13:08:51)
No3128 (zen さん) に返信
>
>>まずは、そのVB6アプリのある場所を載せてください。
>
> サンプルにさせていただいたVB6のソースは
> http://www.koalanet.ne.jp/~akiya/vbtaste/vbp/
> です。
> これを元にしてC#にしました。
>
> あとはC#,IExtractImageでググって部品を集めて・・・

補足です。
K.J.K様の
http://www.koalanet.ne.jp/~akiya/vbtaste/vbp/
にある「IExtractImageを用いる」と

C#の方の部品は
http://www.vbaccelerator.com/home/NET/Code/Libraries/Shell_Projects/Thumbnail_Extraction/article.asp
等を主に参照してやりました。

その結果が、例に挙げたコードなのですが・・・PDFがとれないのがスゲー悔しいです。





引用返信 編集キー/
■3140 / inTopicNo.5)  Re[4]: IExtractImageによるサムネイルの取得
□投稿者/ Hongliang (130回)-(2007/04/24(Tue) 15:02:04)
Hongliang さんの Web サイト
で、どこで失敗する(null とか IntPtr.Zero とかが返ったりとかメソッドの返値が 0 以外だとか)んですか?
// あー、PreserveSig はしてないみたいだから返値はないか。

それと、FromHbitmap し終わった HBITMAP は DeleteObject しておかないとリークしますよ。
引用返信 編集キー/
■3142 / inTopicNo.6)  Re[5]: IExtractImageによるサムネイルの取得
□投稿者/ zen (4回)-(2007/04/24(Tue) 15:35:32)
No3140 (Hongliang さん) に返信
> で、どこで失敗する(null とか IntPtr.Zero とかが返ったりとかメソッドの返値が 0 以外だとか)んですか?
> // あー、PreserveSig はしてないみたいだから返値はないか。
>

落ちるのはPDFを指定した場合の
ieimg.GetLocation(sb,sb.Capacity,ref pdwPriority,ref size,32,ref pdwFlags);
の部分です。
パワーポイントや動画ファイルやサムネイル付きのエクセルファイルとかだと
問題ないんですけど。

> それと、FromHbitmap し終わった HBITMAP は DeleteObject しておかないとリークしますよ。

勉強になりました。ありがとうございます。

あと、今更ですが、申し訳ありません。
開発環境・使用言語のバージョンを書くように指摘してあるにもかかわらず、
書いてありませんでした。

VS2003とVS2005のC#、Acrobatは7,8のReaderと8のReaderでは無い方(お試し期間品)で
やってみたのですが、上記のメソッドで落ちてしまいます。
VS2003では、何もメッセージがでませんが、VS2005の場合はCOMで初期化に失敗したことを伝える
メッセージが表示されます。


引用返信 編集キー/
■3143 / inTopicNo.7)  Re[1]: IExtractImageによるサムネイルの取得
□投稿者/ シャノン (139回)-(2007/04/24(Tue) 15:42:30)
No3122 (zen さん) に返信
> エクスプローラーで「表示→縮小版」を選択した際に表示されるサムネイルを取得する
> 方法として、IExtractImageを用いました。
> パワーポイントもエクセルもワードも動画ファイルもエクスプローラで「縮小版」時に
> サムネイルが出る物ならなんでもとれるようになった・・・と思ったのですが、
> 何故かPDFだけ、取得できません。エクスプローラ上ではサムネイルが表示されているのですが・・・
> 素材の元にさせていただいたVB6のアプリでちゃんとPDFのサムネイルもとれるのですが・・・
> (そのVB6のソースをC#に変換したつもりなのですが・・・)
> いろいろ調べたつもりなのですが、どうしてもわかりません。

まだ元になったVB6のソースを見てないのですが…
IPersistFile を QueryInterface して、Load してやってはどうでしょうか?
引用返信 編集キー/
■3147 / inTopicNo.8)  Re[2]: IExtractImageによるサムネイルの取得
□投稿者/ シャノン (140回)-(2007/04/24(Tue) 18:44:34)
No3143 (シャノン さん) に返信

> まだ元になったVB6のソースを見てないのですが…
> IPersistFile を QueryInterface して、Load してやってはどうでしょうか?

C# で QueryInterface ってどうやるんだorz
引用返信 編集キー/
■3148 / inTopicNo.9)  Re[3]: IExtractImageによるサムネイルの取得
□投稿者/ シャノン (141回)-(2007/04/24(Tue) 19:07:07)
No3147 (シャノン さん) に返信
> ■No3143 (シャノン さん) に返信
>
>>まだ元になったVB6のソースを見てないのですが…
>>IPersistFile を QueryInterface して、Load してやってはどうでしょうか?
>
> C# で QueryInterface ってどうやるんだorz

ボケてた。キャストでいいのか。
引用返信 編集キー/
■3149 / inTopicNo.10)  Re[3]: IExtractImageによるサムネイルの取得
□投稿者/ Hongliang (131回)-(2007/04/24(Tue) 19:08:32)
Hongliang さんの Web サイト
> C# で QueryInterface ってどうやるんだorz

RCW 使う限り、単にキャストすれば良いです。キャスト先のインターフェイスに GuidAttribute 属性が付いていることが必要ですが。
.NET 2.0 なら System.Runtime.InteropServices.ComTypes に IPersistFile の定義もありますね。

// 素のポインタを使うなら Marshal.QueryInterface が存在しますが。
引用返信 編集キー/
■3150 / inTopicNo.11)  Re[6]: IExtractImageによるサムネイルの取得
□投稿者/ シャノン (142回)-(2007/04/24(Tue) 19:14:39)
No3142 (zen さん) に返信
> ■No3140 (Hongliang さん) に返信
>>で、どこで失敗する(null とか IntPtr.Zero とかが返ったりとかメソッドの返値が 0 以外だとか)んですか?
>>// あー、PreserveSig はしてないみたいだから返値はないか。
>>
>
> 落ちるのはPDFを指定した場合の
> ieimg.GetLocation(sb,sb.Capacity,ref pdwPriority,ref size,32,ref pdwFlags);
> の部分です。

落ちる?
例外が発生するんですか? そのメッセージは?

俺の環境で試したら、GetLocation が E_PENDING を返してきました。
この場合、IRunnableTask を使ってごにょごにょするんだと思うんですが、IRunnableTask へのキャストが成功しません。
どーしよー。
引用返信 編集キー/
■3151 / inTopicNo.12)  Re[7]: IExtractImageによるサムネイルの取得
□投稿者/ シャノン (143回)-(2007/04/24(Tue) 19:29:19)
No3150 (シャノン さん) に返信
> 俺の環境で試したら、GetLocation が E_PENDING を返してきました。
> この場合、IRunnableTask を使ってごにょごにょするんだと思うんですが、IRunnableTask へのキャストが成功しません。
> どーしよー。

わけわかんねぇ。
依然として GetLocation が E_PENDING を返すくせに、IRunnableTask にキャストできないのは変わらず。
が、要求するサイズ(GetLocation の 第4引数)を 96 x 96 にしたら、Extract が成功した。
640 x 480 で試したら、Extract は E_FAIL を返してきやがった。

ちなみに俺の環境は、WinXP Pro SP2 + Adobe Reader 8。
引用返信 編集キー/
■3152 / inTopicNo.13)  Re[8]: IExtractImageによるサムネイルの取得
□投稿者/ zen (5回)-(2007/04/24(Tue) 20:04:00)
No3151 (シャノン さん) に返信
> ■No3150 (シャノン さん) に返信
>>俺の環境で試したら、GetLocation が E_PENDING を返してきました。
>>この場合、IRunnableTask を使ってごにょごにょするんだと思うんですが、IRunnableTask へのキャストが成功しません。
>>どーしよー。
>
> わけわかんねぇ。
> 依然として GetLocation が E_PENDING を返すくせに、IRunnableTask にキャストできないのは変わらず。
> が、要求するサイズ(GetLocation の 第4引数)を 96 x 96 にしたら、Extract が成功した。
> 640 x 480 で試したら、Extract は E_FAIL を返してきやがった。
>
> ちなみに俺の環境は、WinXP Pro SP2 + Adobe Reader 8。

こっちの環境もWinXP pro SP2 + Adobe Reader 8ですが、サイズを96×96でやってもダメでした。

それ以前に、GetLocation等の定義が違っているのでしょうか。
戻りをvoidにしてしまっているのでGetLocationで何も返ってきません。
また、VS2005ではGetLocationでエラーになり
System.Runtime.InteropServices.COMException' の初回例外が WindowsApplication1.exe で発生しました。
と表示されます。パワーポイントなどでは問題なくサムネイルがとれるのですが・・・

以下にIExtractImage等の定義を書くので間違いを指摘して頂けないでしょうか。
いろいろなサイトから切り貼りして持ってきており、意味を理解せずに
やっています。

[ComImportAttribute()]
[GuidAttribute("BB2E617C-0920-11d1-9A0B-00C04FC2D6C1")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface IExtractImage
{
int GetLocation(
[Out, MarshalAs(UnmanagedType.LPWStr)]
StringBuilder pszPathBuffer,
int cch,
ref int pdwPriority,
ref SIZE prgSize,
int dwRecClrDepth,
ref int pdwFlags);

void Extract(
out IntPtr phBmpThumbnail);
}

[StructLayoutAttribute(LayoutKind.Sequential)]
public struct SIZE
{
public int cx;
public int cy;
}






引用返信 編集キー/
■3153 / inTopicNo.14)  Re[9]: IExtractImageによるサムネイルの取得
□投稿者/ シャノン (145回)-(2007/04/24(Tue) 20:13:50)
No3152 (zen さん) に返信
> 戻りをvoidにしてしまっているのでGetLocationで何も返ってきません。

て言ってるのに、

> int GetLocation(

int ですけど。どっち?

> また、VS2005ではGetLocationでエラーになり
> System.Runtime.InteropServices.COMException' の初回例外が WindowsApplication1.exe で発生しました。

その時の ErrorCode は何ですか?
引用返信 編集キー/
■3154 / inTopicNo.15)  Re[9]: IExtractImageによるサムネイルの取得
□投稿者/ シャノン (146回)-(2007/04/24(Tue) 20:14:40)
No3152 (zen さん) に返信

俺の IExtractImage の定義

        public static Guid IID_IExtractImage = new Guid( "BB2E617C-0920-11d1-9A0B-00C04FC2D6C1" );

        [ComImportAttribute()]
        [GuidAttribute( "BB2E617C-0920-11d1-9A0B-00C04FC2D6C1" )]
        [InterfaceTypeAttribute( ComInterfaceType.InterfaceIsIUnknown )]
        public interface IExtractImage
        {
            [PreserveSig]
            int GetLocation(
                [Out, MarshalAs( UnmanagedType.LPWStr )] StringBuilder pszPathBuffer,
                int cch,
                ref int pdwPriority,
                ref SIZE prgSize,
                int dwRecClrDepth,
                ref int pdwFlags
                );

            [PreserveSig]
            int Extract(
                out IntPtr phBmpThumbnail
                );
        }

基本的に同じはず。

引用返信 編集キー/
■3157 / inTopicNo.16)  Re[10]: IExtractImageによるサムネイルの取得
□投稿者/ zen (6回)-(2007/04/24(Tue) 20:27:27)
>> int GetLocation(

>int ですけど。どっち?

ああ、すいません。たった今試しに変えてみたんです。
それをコピペしてしまいました。

で、教えて頂いたとおりにIExtractImage の定義
を変えたら・・・・

動きました!!!

決め手は[PreserveSig]でしょうか。
[PreserveSig]の意味自体はまだ理解していませんが、
これから勉強します。

マジでありがとうございます。
スゲーうれしいです。
引用返信 編集キー/
■3158 / inTopicNo.17)  Re[4]: IExtractImageによるサムネイルの取得
□投稿者/ zen (7回)-(2007/04/24(Tue) 20:44:35)
いろいろ、わからないことだらけですが、
動くことがわかったので、これで解決積み
とします。
あとは、自力でできる限り調べてみようと思います。

シャノン様、Hongliang様、このトピに関心を持ってくれた
人に心より感謝します。

ありがとうございました。


解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -