第10回 「ファイルを開く」ダイアログを利用して画像を読み込む

ImageViewer10_01.gif
今回は自由に画像ファイルを読み込めるようにする。まず「ImageViewerView.h」を開く。

ImageViewer10_02.gif そしてインクルードファイルとして「atlstr.h」を追加する。
#include "atlstr.h"

ImageViewer10_03.gif 次に画像読み込み用の関数LoadImageを追加、それに合わせてOnEraseBkgndとOnCreateをそれぞれ変更する。 LoadImage内ではすでに画像が読み込まれていた場合はそれを解放してから新しい画像ファイルを読み込み、画面表示を更新する。 OnEraseBkgndは今までは何もしなかったが、画像が読み込まれていないときは背景を描画するように変更する。
	//画像の読み込み
	bool	LoadImage(LPCTSTR pszFile)
	{
		//画像が既に読み込まれているならそれを開放
		if(_pImage)
			delete	_pImage;

		//画像読み込み
		_pImage = Bitmap::FromFile((CAtlStringW)pszFile,TRUE);

		//ウインドウ再描画
		Invalidate();

		return	_pImage ? true : false;
	}

	//背景描画
	LRESULT OnEraseBkgnd(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& bHandled)
	{
		//画像が読み込まれているときは背景を描画しない
		if(_pImage)
			return	0;

		//画像が読み込まれていないときは背景を描画する
		bHandled = FALSE;
		return	0;
	}

	//ウインドウ生成時処理
	LRESULT OnCreate(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
	{
		return	0;
	}

ImageViewer10_04.gif
次に新しくソースコードファイルを作る。ソリューションエクスプローラの「Header Files」を右クリックして現れたメニューの「追加」から「新しい項目」を選択する。

ImageViewer10_05.gif
ここではhファイルを追加したいので、カテゴリから「コード」、テンプレートから「ヘッダーファイル」を選択する。ファイル名は「ShowFileOpenSaveDialog」とした。

ImageViewer10_06.gif
これでプロジェクトにヘッダーファイルが新しく追加された。

ImageViewer10_07.gif このヘッダーファイル内に「ファイルを開く」ダイアログを利用するための関数を定義する。ここでは以前紹介した「ファイルを開く/保存するダイアログを表示する」をそのまま利用している。
#pragma	once


#include "commdlg.h"


//
//	ファイルを開く/保存するダイアログ表示
//
//bSaveDialog==trueで保存用、falseで開くためのダイアログを表示
//pszInitFolerで初期選択フォルダ指定(ex._T("d:\\"))
//pszFilterExt、pszFilterNameでファイルの拡張子指定(ex.pszFilterExt=_T("*.txt")、pszFilterName=_T("テキストファイル"))
//bUseAllFilter==trueで全てのファイル(*.*)を使うかどうかの指定
//pszTitleでダイアログタイトルの指定
//
//
//■使用例
//	#include "atlstr.h"
//	void	Test(void)
//	{
//		bool		ret;
//		CAtlString	strFile;
//		ret = ShowFileOpenSaveDialog(NULL,&strFile,true,_T("d:"),_T("*.txt"),_T("テキストファイル"));
//		if(ret)
//			::MessageBox(NULL,strFile,_T(""),MB_OK);
//	}
//
//
bool	ShowFileOpenSaveDialog(HWND hParentWnd,CAtlString* pstrFileName,bool bSaveDialog,LPCTSTR pszInitFoler=NULL,LPCTSTR pszFilterExt=NULL,LPCTSTR pszFilterName=NULL,bool bUseAllFilter=true,LPCTSTR pszTitle=NULL)
{
	BOOL			ret;
	TCHAR			pszName[2048];
	TCHAR			pszFilter[2048];
	OPENFILENAME	sOpenFileName;

	if(pstrFileName == NULL)
		return	false;
	*pstrFileName = _T("");

	/////////////////////////////////
	//フィルター作成
	//

	//\0の代わりに\1を使っていることに注意!
	pszFilter[0] = NULL;
	if(pszFilterExt && pszFilterName)
		::_stprintf_s(pszFilter,2048 * sizeof(TCHAR),_T("%s\1%s\1"),pszFilterName,pszFilterExt);
	else if(pszFilterExt)
		::_stprintf_s(pszFilter,2048 * sizeof(TCHAR),_T("%s\1%s\1"),pszFilterExt,pszFilterExt);
	else if(bUseAllFilter == false)
		return	false;

	if(bUseAllFilter)
	{
		if(pszFilter[0])
			::_tcscat_s(pszFilter,2048 * sizeof(TCHAR),_T("All file\1*.*\1"));
		else
			::_stprintf_s(pszFilter,2048 * sizeof(TCHAR),_T("All file\1*.*\1"));
	}
	else
		::_tcscat_s(pszFilter,2048 * sizeof(TCHAR),_T("\1"));

	//\1を\0に置換
	{
		size_t	i;
		size_t	nSize;

		nSize = ::_tcslen(pszFilter);
		for(i = 0; i < nSize; i++)
		{
			if(pszFilter[i] == '\1')
				pszFilter[i] = '\0';
		}
	}

	/////////////////////////////////
	//パラメータ初期化
	//
	pszName[0] = NULL;
	::ZeroMemory(&sOpenFileName,sizeof(OPENFILENAME));
	sOpenFileName.lStructSize	= sizeof(OPENFILENAME);
	sOpenFileName.hwndOwner		= hParentWnd;
	sOpenFileName.lpstrFile		= pszName;
	sOpenFileName.nMaxFile		= 2048;
	sOpenFileName.lpstrFilter	= pszFilter;
	sOpenFileName.nFilterIndex	= 1;
	sOpenFileName.lpstrTitle	= pszTitle;
	sOpenFileName.nMaxFileTitle	= pszTitle ? (DWORD)::_tcslen(pszTitle) : 0;
	sOpenFileName.lpstrInitialDir = pszInitFoler;
	sOpenFileName.Flags			= OFN_PATHMUSTEXIST | OFN_DONTADDTORECENT | OFN_EXPLORER | (bSaveDialog ? OFN_OVERWRITEPROMPT : OFN_FILEMUSTEXIST);


	/////////////////////////////////
	//ダイアログ表示
	//
	if(bSaveDialog)
		ret = ::GetSaveFileName(&sOpenFileName);
	else
		ret = ::GetOpenFileName(&sOpenFileName);

	if(ret == FALSE)
		return	false;

	*pstrFileName = pszName;

	return	true;
}

ImageViewer10_08.gif
次に「ファイルを開く」ダイアログを利用するコードを追加するため、「MainFrm.h」を開く。

ImageViewer10_09.gif そして先ほど作成したヘッダーファイルのインクルード宣言を追加する。
#include "ShowFileOpenSaveDialog.h"

ImageViewer10_10.gif 「ファイルを開く」ダイアログが「ファイル」メニューの「開く」を選択したときに表示されるようにメッセージハンドラを追加する。ファイルを開くではWM_COMMANDがID_FILE_OPENで呼ばれる。 今回の画像表示で利用してるGDI+は画像ファイルとしてJPEG以外にPNGやGIFなどにも対応している。しかしここでは拡張子JPGのみ指定した。
		COMMAND_ID_HANDLER(ID_FILE_OPEN,OnFileOpen)
	//ファイルを開くダイアログ表示
	LRESULT OnFileOpen(WORD /*wNotifyCode*/, WORD /*wID*/, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
	{
		bool		ret;
		CAtlString	strFile;

		ret = ShowFileOpenSaveDialog(NULL,&strFile,false,_T(""),_T("*.jpg"),_T("JPEGファイル"));
		if(ret)
			m_view.LoadImage(strFile);

		return	0;
	}

ImageViewer10_11.gif
これで実行した。
起動時には画像は表示されず背景は真白。

ImageViewer10_12.gif
「ファイル」メニューの「開く」を選択する。

ImageViewer10_13.gif
するとファイルを選択するためのダイアログが開く。ここで画像ファイルを指定して「開く」ボタンを押す。

ImageViewer10_14.gif
すると画像が表示された。

ImageViewer10_15.gif
さらにほかの画像に切り替えることもできる。ここまで実装を進めるとよやく画像表示ソフトっぽくなってきた。

プロジェクトファイルをダウンロード


カテゴリー「画像表示ソフトを作る」 のエントリー