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

「次の画像」をとは「現在読み込んでいる画像があるフォルダー内のファイルを名前順に並べたときの次の画像」ということになる。
実現するにはフォルダ内のファイルを列挙する処理、列挙したファイルを名前順にソートする処理が必要になるのでそれらを追加する。
#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;
}
};

さらにキーが押されたときの処理を追加する。キーが押されると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;
}
プロジェクトファイルをダウンロード