Mesoscopic Programming

タコさんプログラミング専門

ウィンドウズプログラミング講座第13回:画像ファイルの表示

概要

画像ファイルの表示に対応しました。
GDI+ を使うと超簡単に処理できます。
でも Windows XP 以降でないと使えないらしいですよ GDI+ って。さすがにいまどき Windows 3.1 を使ってる人はいないだろうが 95 とか 98 とかはいるのかなぁ?
まあそういう人は XP パソコン買って頂戴。中古のノートだと3万円ぐらいっしょ。


ドキュメントビュークラス

バイナリーファイルとイメージファイルに対応しました。
イメージファイルの対応種類は GDI+ の対応するやつに限ります。
とりあえず JPEG と BMP は対応してるようです。
ファイル名によらずイメージオブジェクトを作成して成功ならイメージファイルという認識してるので、ファイル名の拡張子は関係ありません。

メンバ変数と関数
class DocView : public View
{
    enum DocTypeID
    {
        typeNull = -1,
        typeBinary,
        typeImage,
        maxDocType
    };

    ULONG_PTR           gdiToken;
    GdiplusStartupInput gdiSI;
    DocTypeID           type;
    Image               * image;

    VOID DrawImage( HDC hdc, INT x, INT y );
};
解説

gdiToken と gdiSI は GDI+ を使うためのお約束です。
あとはイメージオブジェクトとファイルタイプ関係のやつ。

初期化と終了処理
#include <gdiplus.h>

#pragma comment( lib, "gdiplus.lib" )

BOOL DocView :: Init( Window * parent, UINT id )
{
    GdiplusStartup( & gdiToken, & gdiSI, NULL );

    image = NULL;
}

LRESULT DocView :: OnWmDestroy()
{
    GdiplusShutdown( gdiToken );
}
解説

GdiplusStartup() と GdiplusShutdown() の組み合わせは GDI+ を使うためのお約束なので何も考えず使用。

ロード
BOOL DocView :: Load( LPCTSTR path )
{
    WCHAR wtext[ _MAX_PATH ];

    MultiByteToWideChar( CP_ACP, 0, path, -1, wtext, sizeof wtext / sizeof ( WCHAR ) );

    image = new Image( wtext );

    if ( image != NULL )
    {
        if ( image->GetWidth() == 0 || image->GetHeight() == 0 )
        {
            delete image;

            image = NULL;
        }
        else
        {
            docWidth  = image->GetWidth();
            docHeight = image->GetHeight();
            type      = typeImage;
            result    = TRUE;
        }
    }
}
解説

ファイル名はワイド文字でないとダメらしいので MultiByteToWideChar() 関数で変換してます。
んで、ファイル名もチェックせずに Image( wtext ) でとりあえずイメージオブジェクトを作成します。
しかしテキストファイルでも成功しちゃうので GetWidth() と GetHeight() でサイズチェックしてます。
したがってサイズがゼロの画像ファイルには対応していません。本当はヘッダとかチェックすりゃ良いんだろけど。
サイズがゼロの画像ファイルはバイナリモードで開くので問題なしとする。

描画
VOID DocView :: DrawImage( HDC hdc, INT x, INT y )
{
    Graphics gg( hdc );

    gg.DrawImage( image, x, y );
}
解説

Graphics インタフェースで DrawImage() 関数呼ぶだけですよ。超簡単ですね。


その他

終了時の状態を復帰させるのは順番が微妙でめんどくさい。
今回はツリービューの状態復帰を優先させ、ドキュメントを連動復帰させるように変更しました。


実行画面

実行ファイル
  1. Windows.zip

以上です。