第14回 カーソルキーで次の画像を表示する

ImageViewer14_01.gif 今回は画像を表示している状態で[↑][↓][←][→]キーを押したら、次の画像を表示できるようにする。 まずは現在読み込んでいる画像ファイルのパスを保存するように変更する。「ImageViewerView.h」を開いてメンバ変数を1つ増やす。
	CAtlString	_strImageFile;
			_strImageFile = pszFile;
		}
		else
			_strImageFile = _T("");

ImageViewer14_02.gif 「次の画像」をとは「現在読み込んでいる画像があるフォルダー内のファイルを名前順に並べたときの次の画像」ということになる。 実現するにはフォルダ内のファイルを列挙する処理、列挙したファイルを名前順にソートする処理が必要になるのでそれらを追加する。
#include "atlcoll.h"

//
//	フォルダ内のファイル検索
//
//見つかったファイルをpastrFilesに追加する
//nRecursiveは子フォルダの探索数(デフォルトは探索しない)
//
bool	GetFilesInFolder(LPCTSTR pszFolder,CAtlArray<CAtlString>* pastrFiles,int nRecursive=0)
{
	BOOL			bFind;
	HANDLE			hFind;
	WIN32_FIND_DATA	FindFileData;
	CAtlString		strFolder;

	if(pszFolder == NULL || _tcslen(pszFolder) == 0 || pastrFiles == NULL)
		return	false;

	//astrFiles.RemoveAll();

	strFolder = pszFolder;
	if(strFolder.Right(1) != _T('\\') && strFolder.Right(1) != _T('/'))
		strFolder += _T("\\");

	hFind = ::FindFirstFile(strFolder + _T("*.*"),&FindFileData);
	if(hFind == INVALID_HANDLE_VALUE)
		return	false;

	bFind = TRUE;
	while(bFind)
	{
		if(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
		{
			//フォルダなら...
			if(nRecursive > 0 && _tcsncmp(FindFileData.cFileName,_T("."),1) != 0 && _tcsncmp(FindFileData.cFileName,_T(".."),2) != 0 )
			{
				//再起で子フォルダ内を調べる
				GetFilesInFolder(strFolder + FindFileData.cFileName,pastrFiles,nRecursive - 1);
			}
		}
		else
		{
			//ファイルなら...
			pastrFiles->Add(strFolder + FindFileData.cFileName);
		}

		bFind = ::FindNextFile(hFind,&FindFileData);
	}
	::FindClose(hFind);

	return	true;
}



class	CDnpSortString
{
	//比較関数
	static	int	SortStringArrayCompare(void* pContext,const void* pData1,const void* pData2)
	{
		if(pContext == NULL)
			return	0;
		return	((CDnpSortString*)pContext)->SortStringArrayCompare_(pData1,pData2);
	}

	//昇順か降順か
	bool		_bABC;

	//ソート対象
	CAtlArray<CAtlString>*	_pastrText;

public:

	CDnpSortString()
	{
		_bABC = true;
		_pastrText = NULL;
	}

	//比較関数の実体
	//外部からは呼ばないこと!
	int	SortStringArrayCompare_(const void* pData1,const void* pData2)
	{
		size_t	nSize;

		if(_pastrText == NULL)
			return	0;

		nSize = _pastrText->GetCount();
		if(*(size_t*)pData1 >= nSize || *(size_t*)pData2 >= nSize)
			return	0;

		if(_bABC)
			return	::_tcscmp((*_pastrText)[*(size_t*)pData1],(*_pastrText)[*(size_t*)pData2]);
		else
			return	::_tcscmp((*_pastrText)[*(size_t*)pData2],(*_pastrText)[*(size_t*)pData1]);
	}


	//
	//	CStringArrayのソート
	//
	bool	SortStringArray(CAtlArray<CAtlString>& astrText,bool bABC)
	{
		size_t	i;
		size_t	nSize;
		size_t*	pnIndex;
		CAtlArray<CAtlString>	astrTmp;

		nSize = astrText.GetCount();
		if(nSize == 0)
			return	false;

		pnIndex = new size_t[nSize];
		if(pnIndex == NULL)
			return	false;

		astrTmp.SetCount(nSize);
		for(i = 0; i < nSize; i++)
		{
			pnIndex[i] = i;
			astrTmp[i] = astrText[i];
		}

		_bABC = bABC;
		_pastrText = &astrText;
		::qsort_s(pnIndex,nSize,sizeof(size_t),SortStringArrayCompare,this);
		_pastrText = NULL;

		for(i = 0; i < nSize; i++)
			astrText[i] = astrTmp[pnIndex[i]];

		delete	pnIndex;

		return	true;
	}

};

ImageViewer14_03.gif さらにキーが押されたときの処理を追加する。キーが押されるとWM_KEYDOWNが送られるのでそれを利用する。 これで実行し、画像ファイルを読み込んだ後にカーソルキーで次のファイルを表示できるようになった。
		MESSAGE_HANDLER(WM_KEYDOWN, OnKeyDown)
	LRESULT OnKeyDown(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& bHandled)
	{
		bHandled = FALSE;
		if(wParam != VK_UP && wParam != VK_DOWN && wParam != VK_LEFT && wParam != VK_RIGHT)
			return	0;
		if(_pImage == NULL)
			return	0;

		CAtlString				strFolder;
		CDnpSortString			cSort;
		CAtlArray<CAtlString>	astrFiles;

		//現在読み込んでいる画像の存在するフォルダ名を取得
		strFolder = _strImageFile;
		{
			int		nFind;

			strFolder.Replace(_T('/'),_T('\\'));
			nFind = strFolder.ReverseFind(_T('\\'));
			if(nFind < 0)
				return	0;
			strFolder = strFolder.Left(nFind);
		}

		//画像のあるフォルダに存在するファイルを全て取得
		GetFilesInFolder(strFolder,&astrFiles);

		//取得したファイル一覧を名前順にソート
		//[←][↑]の場合は降順、[→][↓]の場合は昇順
		cSort.SortStringArray(astrFiles,(wParam == VK_UP || wParam == VK_LEFT) ? false : true);


		//取得したファイル一覧の中から現在表示している画像のインデックスを取得
		size_t	nIndex;
		size_t	nSize;
		nSize = astrFiles.GetCount();
		{
			CAtlString	strFile;

			strFile = _strImageFile;
			strFile.MakeLower();

			for(nIndex = 0; nIndex < nSize; nIndex++)
			{
				astrFiles[nIndex].MakeLower();
				if(strFile == astrFiles[nIndex])
					break;
			}
		}

		//次のファイルを表示
		{
			bool	ret;
			size_t	nTryCount;

			nTryCount = 0;
			while(1)
			{
				nIndex++;
				if(nIndex >= nSize)
					nIndex = 0;

				ret = LoadImage(astrFiles[nIndex]);
				if(ret)
					break;

				nTryCount++;
				if(nTryCount >= nSize)
					break;
			}
		}

		return	0;
	}

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


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