ウィンドウズプログラミング講座第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() 関数呼ぶだけですよ。超簡単ですね。
その他
終了時の状態を復帰させるのは順番が微妙でめんどくさい。
今回はツリービューの状態復帰を優先させ、ドキュメントを連動復帰させるように変更しました。