none
サムネイル表示がVistaでは真っ白 RRS feed

  • 質問

  • 自作のサムネイル表示アプリがあります。下記3種類のファイルをサポート。
    ・JPG(Exif)
    JPG(非Exif)
    ・GIF
    当アプリは、XPでは上記全てのファイルが正常にサムネイル表示できますが、
    Vistaで実行すると、
    JPG(Exif)/GIFだと表示されなくなります(真っ白)。
    JPG(非Exif)では問題なく表示されます。

    画像のサムネイル化は、XPのExplorerの縮小画像機能を利用しています。
    VistaにVC++2005をインストールし、デバッグしたところ、コードの全行
    が正常復帰(エラー無し)し、かつ、最終的にビットマップのハンドルが
    正しく取得されているにも関わらず、です。

    ソースを抜粋します。
    -----------------------------
        //--------------------------------------------------------------------------
        // フォルダのIPDLを取得
        //--------------------------------------------------------------------------
        if( NULL == ( pPIDL_Folder = GetItemIDList(
                        m_pDeskTopFolder, (LPCTSTR)csFolderName, ITEMIDLIST_FOLDER ) ) )
        {    bRet = FALSE; goto FREE_MEMORY; }
        //--------------------------------------------------------------------------
        // 画像ファイルのIPDLを取得
        //--------------------------------------------------------------------------
        if( NULL == ( pPIDL_File = GetItemIDList( m_pShellFolder, (LPCTSTR)csFileName,
                ITEMIDLIST_FILE ) ) )
        {    bRet = FALSE; goto FREE_MEMORY; }
        //--------------------------------------------------------------------------
        // PIDLからLPEXTRACTIMAGEオブジェクトを取得
        //--------------------------------------------------------------------------
        hRet = m_pShellFolder->GetUIObjectOf( NULL, 1, (LPCITEMIDLIST*)&pPIDL_File,
                                 IID_IExtractImage, NULL, (VOID **)&pExtractImage );
        if( FAILED( hRet ) || ( NULL == pExtractImage ) )
        {    bRet = FALSE; goto FREE_MEMORY; }
        //--------------------------------------------------------------------------
        // 縮小画像を取得
        //--------------------------------------------------------------------------
        ::ZeroMemory( wszPathBuff, sizeof( wszPathBuff ) );
        hRet = pExtractImage->GetLocation( wszPathBuff, sizeof( wszPathBuff ),
                                &dwPriority, &size, 32, &dwFlags );
        if( SUCCEEDED( hRet ) )
            hRet = pExtractImage->Extract( phBitmap );      // ←
    !!!! コレ !!!!
        if( FAILED( hRet ) )
            bRet = FALSE;
        else
            bRet = TRUE;

        // 以下、解放処理
    -----------------------------
    最後の方にある
    pExtractImage->Extract( phBitmap );
    は、戻り値は正常かつ、「
    phBitmap」にはハンドルが格納されている
    ことを確認しています。そして、「
    phBitmap」を、イメージリスト
    コントロールに対して、
                                                 
    phBitmap」と同値
                                                     ↓
    int iItem = ImageList_AddMasked( m_hiImageList, hBMP,
                                      RGB( 255, 255, 255 ) );
    し、RedrawItems( iItem, iItem );
        UpdateWindow( );
    してます。

    XP環境上では、上記でJPG(Exif/非Exif)、GIF全て正しく表示されます。
    VistaではNGです。「なぜ」表示されないのか、判りますでしょうか?
    ・Explorerの仕様変更なのか・・・・?
    ・イメージリストコントロールの仕様変更なのか・・・?

    (※)これに関係なく、いい加減労力を増やすだけの仕様変更はやめて欲しい!!
    2006年12月15日 2:28

回答

  • >そのままImageList_AddMaskd( )すると駄目なので、
    >直前にCreateIconIndirect( )を使用してBMP→ICON
    >にし、代わりにImageList_AddIcon( )すると、
    >XP/Vistaの両方でも表示できるようになりました。

    ということは

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/imagelist/functions/imagelist_addmasked.asp
    >Bitmaps with color depth greater than 8bpp are not supported.

    おそらくはこの制限に引っかかったんでしょうね。
    また、そうであるならばいったんアイコンに変換しなくても
    ImageList_Add を利用することでいけそうですね。

    てか、↓ここの 32 を 8 にすれば元のままのコードでもいけそうな気が。(^^;

    >    hRet = pExtractImage->GetLocation( wszPathBuff, sizeof( wszPathBuff ),
    >                            &dwPriority, &size, 32, &dwFlags );

    # calligrapher は、ここの値を無視しちゃってますけど。

     

    >ただ、コードは同じなのに、上記新対処の場合でも、
    >100×100(コードでサムネイルサイズ指定)より小さい
    >画像がある場合、
    >XP:オリジナルのサイズそのまま表示
    >Vista:勝手に100×100に拡大して表示・・・(なので汚くなる)。

    IExtractImage::GetLocation の pdwFlags 引数で IEIFLAG_ORIGSIZE や
    IEIFLAG_QUALITY あたりのフラグ指定を加えたり除去したりしても駄目ですか?

    2006年12月18日 10:44

すべての返信

  • 私も原因はわかりませんが、サムネイルを作成する側のプログラムをソースコード付きで
    (手前味噌でなんですが)公開してるんでよかったら原因究明に利用してみてください。
    ( Vista で動作することは確認済み )

     http://tricklib.com/cxx/ex/calligrapher/

    この calligrp.dll が作成したサムネイルを表示できるようでしたら、問題となっている
    ビットマップハンドルは内部表現形式がいままでと異なるビットマップのハンドルなのかも
    しれませんね。

    2006年12月15日 15:24
  • 道化師さん

    迅速な返事どうもありがとうございます!!

    ありがたくご参考にさせて頂きます。

    早速Vista環境上で実験し、後ほど結果を報告します。

    2006年12月15日 16:36
  • ウーン、駄目でした・・・。
    どうやら、エクスプローラの仕様変更か、あるいはバグ
    みたいです。

    最初に投稿したコードにて、得たphBitmapを
    そのままImageList_AddMaskd( )すると駄目なので、
    直前にCreateIconIndirect( )を使用してBMP→ICON
    にし、代わりに
    ImageList_AddIcon( )すると、
    XP/Vistaの両方でも表示できるようになりました。

    ただ、コードは同じなのに、上記新対処の場合でも、
    100×100(コードでサムネイルサイズ指定)より小さい
    画像がある場合、
    XP:オリジナルのサイズそのまま表示
    Vista
    勝手に100×100に拡大して表示・・・(なので汚くなる)。

    現在、有効な別手段が見つかっていません。
    (今更イチからシコシコ作りたくないので)
    2006年12月18日 6:49
  • >そのままImageList_AddMaskd( )すると駄目なので、
    >直前にCreateIconIndirect( )を使用してBMP→ICON
    >にし、代わりにImageList_AddIcon( )すると、
    >XP/Vistaの両方でも表示できるようになりました。

    ということは

    http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/commctls/imagelist/functions/imagelist_addmasked.asp
    >Bitmaps with color depth greater than 8bpp are not supported.

    おそらくはこの制限に引っかかったんでしょうね。
    また、そうであるならばいったんアイコンに変換しなくても
    ImageList_Add を利用することでいけそうですね。

    てか、↓ここの 32 を 8 にすれば元のままのコードでもいけそうな気が。(^^;

    >    hRet = pExtractImage->GetLocation( wszPathBuff, sizeof( wszPathBuff ),
    >                            &dwPriority, &size, 32, &dwFlags );

    # calligrapher は、ここの値を無視しちゃってますけど。

     

    >ただ、コードは同じなのに、上記新対処の場合でも、
    >100×100(コードでサムネイルサイズ指定)より小さい
    >画像がある場合、
    >XP:オリジナルのサイズそのまま表示
    >Vista:勝手に100×100に拡大して表示・・・(なので汚くなる)。

    IExtractImage::GetLocation の pdwFlags 引数で IEIFLAG_ORIGSIZE や
    IEIFLAG_QUALITY あたりのフラグ指定を加えたり除去したりしても駄目ですか?

    2006年12月18日 10:44
  • 道化師さん、返信ありがとうございます。返信が遅くなり、

    申し訳ありませんでした。GDI+など色々な手法で試したりしてて、遅くなりました。

    (それだけ長く悩みましたがね。)

    さて、上記のExplorer依存機能については、道化師さんのおっしゃる通り

    色々試してみたのですが、NGでした・・・。

    ついに、MSに連絡するに至りましたが、ダンマリ中です。

    なので、自力でサムネイルを生成・描画することで解決に至りました。

    2007年1月12日 1:30