「C言語/C++/ImgView3」の編集履歴(バックアップ)一覧はこちら

C言語/C++/ImgView3」(2014/03/14 (金) 21:03:39) の最新版変更点

追加された行は緑色になります。

削除された行は赤色になります。

|開発環境|Microsoft Visual C++ 2013| |実行環境|Microsoft Windows 8.1 (64bit)| |プロジェクトの種類|Win32 プロジェクト| |プロジェクト名|ImgView3| |アプリケーションの種類|Windows アプリケーション| |追加のオプション|空のプロジェクト, SDLチェック| 作りかけ エクスプローラーの並び順の取得は別途研究 ImgView3.cpp #highlight(cpp){{ #include <Windows.h> #include <CommCtrl.h> #include <shimgdata.h> #include <stdio.h> #include <string> #include <vector> #include "resource.h" using namespace std; #define WIDTH(rect) ((rect).right - (rect).left) #define HEIGHT(rect) ((rect).bottom - (rect).top) #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } #define APP_NAME TEXT("ImgView3") typedef vector<wstring> VecStr; // 関数プロトタイプ宣言 void CreateFileList(LPCTSTR pszPath); BOOL IsImgFile(LPCTSTR pszPath); LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); BOOL OnCommand(HWND hWnd, WPARAM wParam); void OnDelete(HWND hWnd); void OnDropFiles(HWND hWnd, WPARAM wParam); void OnSizeNormal(HWND hWnd); void OnSizeAdjust(HWND hWnd); void OnExecute(void); void OnPaint(HWND hWnd); void GetImage(HWND hWnd); BOOL MyGetFileTime(LPSYSTEMTIME pSystemTime, LPCTSTR pszFileName); // 外部変数構造体 static struct { TCHAR szBaseDir[MAX_PATH]; // 基準ディレクトリ VecStr vsFileName; // ファイル名配列 VecStr::size_type idxCurr; // 現在の位置 IShellImageDataFactory *pImgDatFac; // 画像データファクトリ IShellImageData *pImgDat; // 画像データ SIZE sizeImg; // 画像サイズ SIZE sizeDst; // 出力サイズ HWND hListView; // エクスプローラのリストビュー } g; //============================================================================== int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow) { // プログラム引数 LPTSTR pszCmdLine = GetCommandLine(); int argc; LPTSTR *argv = CommandLineToArgvW(pszCmdLine, &argc); if (2 <= argc) { CreateFileList(argv[1]); } // ウィンドウクラスの登録 WNDCLASSEX wcx; ZeroMemory(&wcx, sizeof wcx); wcx.cbSize = sizeof wcx; wcx.style = CS_HREDRAW | CS_VREDRAW; wcx.lpfnWndProc = WndProc; wcx.hInstance = hInstance; wcx.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW)); wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wcx.lpszClassName = APP_NAME; if (RegisterClassEx(&wcx) == 0) { return 0; } // ウィンドウの作成 HWND hWnd = CreateWindowEx( WS_EX_ACCEPTFILES, APP_NAME, APP_NAME, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (hWnd == NULL) { return 0; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); // メッセージループ MSG msg; HACCEL hAccTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_MAIN)); while (GetMessage(&msg, NULL, 0, 0)) { if (TranslateAccelerator(msg.hwnd, hAccTable, &msg) == 0) { TranslateMessage(&msg); DispatchMessage(&msg); } } return msg.wParam; } //------------------------------------------------------------------------------ void CreateFileList(LPCTSTR pszPath) { TCHAR szDrive[_MAX_DRIVE]; TCHAR szDir[_MAX_DIR]; TCHAR szFName[_MAX_FNAME]; TCHAR szExt[_MAX_EXT]; TCHAR szFileName[_MAX_PATH]; TCHAR szPath[_MAX_PATH]; g.vsFileName.clear(); g.idxCurr = -1; errno_t er = _wsplitpath_s(pszPath, szDrive, szDir, szFName, szExt); swprintf_s(g.szBaseDir, L"%s%s", szDrive, szDir); swprintf_s(szFileName, L"%s%s", szFName, szExt); swprintf_s(szPath, L"%s*.*", g.szBaseDir); WIN32_FIND_DATA wfd; HANDLE hFindFile = FindFirstFile(szPath, &wfd); DWORD dwMask = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_HIDDEN; VecStr::size_type idx = 0; do { if (wfd.dwFileAttributes & dwMask) { continue; } g.vsFileName.push_back(wfd.cFileName); if (wcscmp(wfd.cFileName, szFileName) == 0) { g.idxCurr = idx; } idx++; } while (FindNextFile(hFindFile, &wfd)); FindClose(hFindFile); } //------------------------------------------------------------------------------ BOOL IsImgFile(LPCTSTR pszPath) { static LPCTSTR ext[] = { L".jpg", L".jpeg", L".gif", L".png", L".j6i" }; TCHAR szExt[_MAX_EXT]; _wsplitpath_s(pszPath, NULL, 0, NULL, 0, NULL, 0, szExt, _MAX_EXT); for (int n = 0; n < _countof(ext); n++) { if (_wcsicmp(ext[n], szExt) == 0) { return TRUE; } } return FALSE; } //============================================================================== LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_PAINT: OnPaint(hWnd); return 0; case WM_COMMAND: if (OnCommand(hWnd, wParam)) { return 0; } break; case WM_DROPFILES: OnDropFiles(hWnd, wParam); DragFinish((HDROP)wParam); return 0; case WM_CREATE: CoInitialize(NULL); CoCreateInstance(CLSID_ShellImageDataFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&g.pImgDatFac)); GetImage(hWnd); return 0; case WM_DESTROY: SAFE_RELEASE(g.pImgDat); SAFE_RELEASE(g.pImgDatFac); CoUninitialize(); PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, uMsg, wParam, lParam); } //------------------------------------------------------------------------------ BOOL OnCommand(HWND hWnd, WPARAM wParam) { switch (LOWORD(wParam)) { case ID_RIGHT: case ID_DOWN: g.idxCurr++; if (g.vsFileName.size() <= g.idxCurr) { g.idxCurr = 0; } break; case ID_LEFT: case ID_UP: if (g.idxCurr <= 0) { g.idxCurr = g.vsFileName.size(); } g.idxCurr--; break; case ID_ENTER: ShowWindow(hWnd, IsZoomed(hWnd) ? SW_SHOWNOACTIVATE : SW_MAXIMIZE); break; case ID_SIZE_NORMAL: OnSizeNormal(hWnd); // あえてスルー case ID_SIZE_ADJUST: OnSizeAdjust(hWnd); break; case ID_EXECUTE: OnExecute(); break; case ID_DELETE: OnDelete(hWnd); break; case ID_ESCAPE: DestroyWindow(hWnd); return TRUE; default: return FALSE; } GetImage(hWnd); InvalidateRect(hWnd, NULL, FALSE); // ちらつき防止のため背景消去しない return TRUE; } //------------------------------------------------------------------------------ void OnDelete(HWND hWnd) { if (g.vsFileName.empty()) return; TCHAR szPath[MAX_PATH]; // '\0'2つで終わる要あり swprintf_s(szPath, L"%s%s%c", g.szBaseDir, g.vsFileName[g.idxCurr].c_str(), L'\0'); SHFILEOPSTRUCT fo; ZeroMemory(&fo, sizeof fo); fo.hwnd = hWnd; fo.wFunc = FO_DELETE; fo.pFrom = szPath; fo.fFlags = FOF_ALLOWUNDO; SHFileOperation(&fo); } //------------------------------------------------------------------------------ void OnDropFiles(HWND hWnd, WPARAM wParam) { HDROP hDrop; TCHAR szPath[MAX_PATH]; hDrop = (HDROP)wParam; DragQueryFile(hDrop, 0, szPath, _countof(szPath)); CreateFileList(szPath); GetImage(hWnd); InvalidateRect(hWnd, NULL, FALSE); // ちらつき防止のため背景消去しない } //------------------------------------------------------------------------------ void OnSizeNormal(HWND hWnd) { if (g.pImgDat == NULL) return; g.sizeDst = g.sizeImg; RECT rcWorkArea;// タスクバーを除くデスクトップ領域 RECT rcWnd; // ウィンドウ領域 RECT rcClt; // クライアント領域 SIZE size; // ウィンドウ領域とクライアント領域の差分 SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWorkArea, 0); GetWindowRect(hWnd, &rcWnd); GetClientRect(hWnd, &rcClt); size.cx = WIDTH(rcWnd) - WIDTH(rcClt); size.cy = HEIGHT(rcWnd) - HEIGHT(rcClt); // デスクトップ領域からはみ出す場合、ウィンドウを左上方向に移動する if (rcWorkArea.right < rcWnd.left + g.sizeDst.cx + size.cx) { rcWnd.left = 0; } if (rcWorkArea.bottom < rcWnd.top + g.sizeDst.cy + size.cy) { rcWnd.top = 0; } // 最大クライアント領域に収める if (rcWorkArea.right - size.cx < g.sizeDst.cx) { g.sizeDst.cx = rcWorkArea.right - size.cx; } if (rcWorkArea.bottom - size.cy < g.sizeDst.cy) { g.sizeDst.cy = rcWorkArea.bottom - size.cy; } // アスペクト比の調整 if (g.sizeImg.cx < g.sizeImg.cy * g.sizeDst.cx / g.sizeDst.cy) { g.sizeDst.cx = g.sizeDst.cy * g.sizeImg.cx / g.sizeImg.cy; } else { g.sizeDst.cy = g.sizeDst.cx * g.sizeImg.cy / g.sizeImg.cx; } // ウィンドウ位置のセット rcWnd.right = g.sizeDst.cx + size.cx; rcWnd.bottom = g.sizeDst.cy + size.cy; SetWindowPos(hWnd, NULL, rcWnd.left, rcWnd.top, rcWnd.right, rcWnd.bottom, SWP_NOZORDER); } //------------------------------------------------------------------------------ void OnSizeAdjust(HWND hWnd) { if (g.pImgDat == NULL) return; RECT rc; SetRect(&rc, 0, 0, g.sizeDst.cx, g.sizeDst.cy); AdjustWindowRectEx(&rc, WS_OVERLAPPEDWINDOW, FALSE, 0); SetWindowPos(hWnd, NULL, 0, 0, WIDTH(rc), HEIGHT(rc), SWP_NOZORDER | SWP_NOMOVE); } //------------------------------------------------------------------------------ void OnExecute(void) { if (g.vsFileName.empty()) return; TCHAR szFile[MAX_PATH]; TCHAR szParams[MAX_PATH]; GetModuleFileName(NULL, szFile, MAX_PATH); swprintf_s(szParams, L"\"%s%s\"", g.szBaseDir, g.vsFileName[g.idxCurr].c_str()); SHELLEXECUTEINFO ei; ZeroMemory(&ei, sizeof ei); ei.cbSize = sizeof ei; ei.nShow = SW_SHOWNORMAL; ei.fMask = SEE_MASK_NOCLOSEPROCESS; ei.lpFile = szFile; ei.lpParameters = szParams; ShellExecuteEx(&ei); } //------------------------------------------------------------------------------ void OnPaint(HWND hWnd) { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); if (g.pImgDat == NULL) goto Exit; RECT rcClt; GetClientRect(hWnd, &rcClt); // 画像とクライアント領域のアスペクト比を比較し // アスペクト比を維持したままクライアント領域に収める if (g.sizeImg.cx < g.sizeImg.cy * rcClt.right / rcClt.bottom) { g.sizeDst.cx = rcClt.bottom * g.sizeImg.cx / g.sizeImg.cy; g.sizeDst.cy = rcClt.bottom; } else { g.sizeDst.cx = rcClt.right; g.sizeDst.cy = rcClt.right * g.sizeImg.cy / g.sizeImg.cx; } RECT rcDst; rcDst.left = (rcClt.right - g.sizeDst.cx) / 2; rcDst.top = (rcClt.bottom - g.sizeDst.cy) / 2; rcDst.right = rcDst.left + g.sizeDst.cx; rcDst.bottom = rcDst.top + g.sizeDst.cy; // 画像描画 RECT rcTmp; SetRect(&rcTmp, 0, 0, g.sizeImg.cx, g.sizeImg.cy); g.pImgDat->Draw(hdc, &rcDst, &rcTmp); // 余白塗り潰し HBRUSH hbr = (HBRUSH)(COLOR_WINDOW + 1); if (rcClt.left < rcDst.left) { CopyRect(&rcTmp, &rcClt); rcTmp.right = rcDst.left; FillRect(hdc, &rcTmp, hbr); } if (rcClt.top < rcDst.top) { CopyRect(&rcTmp, &rcClt); rcTmp.bottom = rcDst.top; FillRect(hdc, &rcTmp, hbr); } if (rcDst.right < rcClt.right) { CopyRect(&rcTmp, &rcClt); rcTmp.left = rcDst.right; FillRect(hdc, &rcTmp, hbr); } if (rcDst.bottom < rcClt.bottom) { CopyRect(&rcTmp, &rcClt); rcTmp.top = rcDst.bottom; FillRect(hdc, &rcTmp, hbr); } Exit: EndPaint(hWnd, &ps); } //------------------------------------------------------------------------------ void GetImage(HWND hWnd) { SAFE_RELEASE(g.pImgDat); if (g.vsFileName.empty()) { SetWindowText(hWnd, APP_NAME); return; } // 画像ファイルの読み込み TCHAR szBuf[512]; LPCTSTR pszFileName = g.vsFileName[g.idxCurr].c_str(); swprintf_s(szBuf, L"%s%s", g.szBaseDir, pszFileName); HRESULT hr = g.pImgDatFac->CreateImageFromFile(szBuf, &g.pImgDat); if (SUCCEEDED(hr)) { hr = g.pImgDat->Decode(SHIMGDEC_DEFAULT, 0, 0); } if (SUCCEEDED(hr)) { hr = g.pImgDat->GetSize(&g.sizeImg); } if (FAILED(hr) || g.sizeImg.cx <= 0 || g.sizeImg.cy <= 0) { SAFE_RELEASE(g.pImgDat); g.sizeImg.cx = g.sizeImg.cy = 0; } // ファイル更新日時の取得 SYSTEMTIME st; MyGetFileTime(&st, szBuf); // タイトルバー swprintf_s(szBuf, L"%s [%d/%d] %d/%02d/%02d %02d:%02d:%02d (%dx%d) - %s", pszFileName, g.idxCurr + 1, g.vsFileName.size(), st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, g.sizeImg.cx, g.sizeImg.cy, APP_NAME); SetWindowText(hWnd, szBuf); } //------------------------------------------------------------------------------ BOOL MyGetFileTime(LPSYSTEMTIME pSystemTime, LPCTSTR pszFileName) { HANDLE hFile = CreateFile(pszFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { return FALSE; } FILETIME ftCreation; FILETIME ftLocal; GetFileTime(hFile, &ftCreation, NULL, NULL); FileTimeToLocalFileTime(&ftCreation, &ftLocal); FileTimeToSystemTime(&ftLocal, pSystemTime); CloseHandle(hFile); return TRUE; } }} resource.h #highlight(c){{ #define ID_SIZE_ADJUST 100 #define ID_SIZE_NORMAL 101 #define ID_EXECUTE 102 #define IDR_MAIN 128 #define ID_ENTER 129 #define ID_ESCAPE 130 #define ID_LEFT 131 #define ID_UP 132 #define ID_RIGHT 133 #define ID_DOWN 134 #define ID_DELETE 135 }} ImgView3.rc #highlight(c){{ // resource script #include <windows.h> #include "resource.h" // アクセラレータ IDR_MAIN ACCELERATORS BEGIN VK_RETURN, ID_ENTER, VIRTKEY // 0x0D VK_ESCAPE, ID_ESCAPE, VIRTKEY // 0x1B VK_LEFT, ID_LEFT, VIRTKEY // 0x25 VK_UP, ID_UP, VIRTKEY // 0x26 VK_RIGHT, ID_RIGHT, VIRTKEY // 0x27 VK_DOWN, ID_DOWN, VIRTKEY // 0x28 VK_DELETE, ID_DELETE, VIRTKEY // 0x2E "1", ID_SIZE_ADJUST, VIRTKEY // 0x31 VK_NUMPAD1, ID_SIZE_ADJUST, VIRTKEY // 0x61 "2", ID_SIZE_NORMAL, VIRTKEY // 0x32 VK_NUMPAD2, ID_SIZE_NORMAL, VIRTKEY // 0x62 "3", ID_EXECUTE, VIRTKEY // 0x33 VK_NUMPAD3, ID_EXECUTE, VIRTKEY // 0x63 END }}
|開発環境|Microsoft Visual C++ 2013| |実行環境|Microsoft Windows 8.1 (64bit)| |プロジェクトの種類|Win32 プロジェクト| |プロジェクト名|ImgView3| |アプリケーションの種類|Windows アプリケーション| |追加のオプション|空のプロジェクト, SDLチェック| エクスプローラーの並び順の取得は別途研究 ImgView3.cpp #highlight(cpp){{ #include <Windows.h> #include <CommCtrl.h> #include <shimgdata.h> #include <stdio.h> #include <map> #include <string> #include <vector> #include "resource.h" using namespace std; #define WIDTH(rect) ((rect).right - (rect).left) #define HEIGHT(rect) ((rect).bottom - (rect).top) #define SAFE_RELEASE(p) { if(p) { (p)->Release(); (p)=NULL; } } #define APP_NAME TEXT("ImgView3") typedef vector<wstring> VecStr; typedef multimap<ULONGLONG, wstring> MapStr; // 関数プロトタイプ宣言 void CreateFileList(LPCTSTR pszPath); BOOL IsImgFile(LPCTSTR pszPath); LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); BOOL OnCommand(HWND hWnd, WPARAM wParam); void OnDelete(HWND hWnd); void OnDropFiles(HWND hWnd, WPARAM wParam); void OnSizeNormal(HWND hWnd); void OnSizeAdjust(HWND hWnd); void OnExecute(void); void OnPaint(HWND hWnd); void GetImage(HWND hWnd); BOOL MyGetFileTime(LPSYSTEMTIME pSystemTime, LPCTSTR pszFileName); // 外部変数構造体 static struct { TCHAR szBaseDir[MAX_PATH]; // 基準ディレクトリ VecStr vsFileName; // ファイル名配列 VecStr::size_type idxCurr; // 現在の位置 IShellImageDataFactory *pImgDatFac; // 画像データファクトリ IShellImageData *pImgDat; // 画像データ SIZE sizeImg; // 画像サイズ SIZE sizeDst; // 出力サイズ HWND hListView; // エクスプローラのリストビュー } g; //============================================================================== int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE, LPSTR, int nCmdShow) { // プログラム引数 LPTSTR pszCmdLine = GetCommandLine(); int argc; LPTSTR *argv = CommandLineToArgvW(pszCmdLine, &argc); if (2 <= argc) { CreateFileList(argv[1]); } // ウィンドウクラスの登録 WNDCLASSEX wcx; ZeroMemory(&wcx, sizeof wcx); wcx.cbSize = sizeof wcx; wcx.style = CS_HREDRAW | CS_VREDRAW; wcx.lpfnWndProc = WndProc; wcx.hInstance = hInstance; wcx.hCursor = LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW)); wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wcx.lpszClassName = APP_NAME; if (RegisterClassEx(&wcx) == 0) { return 0; } // ウィンドウの作成 HWND hWnd = CreateWindowEx( WS_EX_ACCEPTFILES, APP_NAME, APP_NAME, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL); if (hWnd == NULL) { return 0; } ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); // メッセージループ MSG msg; HACCEL hAccTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDR_MAIN)); while (GetMessage(&msg, NULL, 0, 0)) { if (TranslateAccelerator(msg.hwnd, hAccTable, &msg) == 0) { TranslateMessage(&msg); DispatchMessage(&msg); } } return msg.wParam; } //------------------------------------------------------------------------------ void CreateFileList(LPCTSTR pszPath) { TCHAR szDrive[_MAX_DRIVE]; TCHAR szDir[_MAX_DIR]; TCHAR szFName[_MAX_FNAME]; TCHAR szExt[_MAX_EXT]; TCHAR szFileName[_MAX_PATH]; TCHAR szPath[_MAX_PATH]; g.vsFileName.clear(); g.idxCurr = -1; errno_t er = _wsplitpath_s(pszPath, szDrive, szDir, szFName, szExt); swprintf_s(g.szBaseDir, L"%s%s", szDrive, szDir); swprintf_s(szFileName, L"%s%s", szFName, szExt); swprintf_s(szPath, L"%s*.*", g.szBaseDir); // ファイル一覧を取得し更新日時の昇順でソート WIN32_FIND_DATA wfd; HANDLE hFindFile = FindFirstFile(szPath, &wfd); DWORD dwMask = FILE_ATTRIBUTE_DIRECTORY | FILE_ATTRIBUTE_HIDDEN; MapStr list; do { if (wfd.dwFileAttributes & dwMask) { continue; } FILETIME ft = wfd.ftLastWriteTime; ULONGLONG qw = (ULONGLONG(ft.dwHighDateTime) << 32) + ft.dwLowDateTime; list.insert(make_pair(qw, wfd.cFileName)); } while (FindNextFile(hFindFile, &wfd)); FindClose(hFindFile); // 配列に転記 VecStr::size_type idx = 0; for (MapStr::iterator it = list.begin(); it != list.end(); it++) { g.vsFileName.push_back(it->second); if (wcscmp(it->second.c_str(), szFileName) == 0) { g.idxCurr = idx; } idx++; } } //------------------------------------------------------------------------------ BOOL IsImgFile(LPCTSTR pszPath) { static LPCTSTR ext[] = { L".jpg", L".jpeg", L".gif", L".png" }; TCHAR szExt[_MAX_EXT]; _wsplitpath_s(pszPath, NULL, 0, NULL, 0, NULL, 0, szExt, _MAX_EXT); for (int n = 0; n < _countof(ext); n++) { if (_wcsicmp(ext[n], szExt) == 0) { return TRUE; } } return FALSE; } //============================================================================== LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_PAINT: OnPaint(hWnd); return 0; case WM_COMMAND: if (OnCommand(hWnd, wParam)) { return 0; } break; case WM_DROPFILES: OnDropFiles(hWnd, wParam); DragFinish((HDROP)wParam); return 0; case WM_CREATE: CoInitialize(NULL); CoCreateInstance(CLSID_ShellImageDataFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&g.pImgDatFac)); GetImage(hWnd); return 0; case WM_DESTROY: SAFE_RELEASE(g.pImgDat); SAFE_RELEASE(g.pImgDatFac); CoUninitialize(); PostQuitMessage(0); return 0; } return DefWindowProc(hWnd, uMsg, wParam, lParam); } //------------------------------------------------------------------------------ BOOL OnCommand(HWND hWnd, WPARAM wParam) { switch (LOWORD(wParam)) { case ID_RIGHT: case ID_DOWN: g.idxCurr++; if (g.vsFileName.size() <= g.idxCurr) { g.idxCurr = 0; } break; case ID_LEFT: case ID_UP: if (g.idxCurr <= 0) { g.idxCurr = g.vsFileName.size(); } g.idxCurr--; break; case ID_ENTER: ShowWindow(hWnd, IsZoomed(hWnd) ? SW_SHOWNOACTIVATE : SW_MAXIMIZE); break; case ID_SIZE_NORMAL: OnSizeNormal(hWnd); // あえてスルー case ID_SIZE_ADJUST: OnSizeAdjust(hWnd); break; case ID_EXECUTE: OnExecute(); break; case ID_DELETE: OnDelete(hWnd); break; case ID_ESCAPE: DestroyWindow(hWnd); return TRUE; default: return FALSE; } GetImage(hWnd); InvalidateRect(hWnd, NULL, FALSE); // ちらつき防止のため背景消去しない return TRUE; } //------------------------------------------------------------------------------ void OnDelete(HWND hWnd) { if (g.vsFileName.empty()) return; TCHAR szPath[MAX_PATH]; // '\0'2つで終わる要あり swprintf_s(szPath, L"%s%s%c", g.szBaseDir, g.vsFileName[g.idxCurr].c_str(), L'\0'); SHFILEOPSTRUCT fo; ZeroMemory(&fo, sizeof fo); fo.hwnd = hWnd; fo.wFunc = FO_DELETE; fo.pFrom = szPath; fo.fFlags = FOF_ALLOWUNDO; SHFileOperation(&fo); } //------------------------------------------------------------------------------ void OnDropFiles(HWND hWnd, WPARAM wParam) { HDROP hDrop; TCHAR szPath[MAX_PATH]; hDrop = (HDROP)wParam; DragQueryFile(hDrop, 0, szPath, _countof(szPath)); CreateFileList(szPath); GetImage(hWnd); InvalidateRect(hWnd, NULL, FALSE); // ちらつき防止のため背景消去しない } //------------------------------------------------------------------------------ void OnSizeNormal(HWND hWnd) { if (g.pImgDat == NULL) return; g.sizeDst = g.sizeImg; RECT rcWorkArea;// タスクバーを除くデスクトップ領域 RECT rcWnd; // ウィンドウ領域 RECT rcClt; // クライアント領域 SIZE size; // ウィンドウ領域とクライアント領域の差分 SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWorkArea, 0); GetWindowRect(hWnd, &rcWnd); GetClientRect(hWnd, &rcClt); size.cx = WIDTH(rcWnd) - WIDTH(rcClt); size.cy = HEIGHT(rcWnd) - HEIGHT(rcClt); // デスクトップ領域からはみ出す場合、ウィンドウを左上方向に移動する if (rcWorkArea.right < rcWnd.left + g.sizeDst.cx + size.cx) { rcWnd.left = 0; } if (rcWorkArea.bottom < rcWnd.top + g.sizeDst.cy + size.cy) { rcWnd.top = 0; } // 最大クライアント領域に収める if (rcWorkArea.right - size.cx < g.sizeDst.cx) { g.sizeDst.cx = rcWorkArea.right - size.cx; } if (rcWorkArea.bottom - size.cy < g.sizeDst.cy) { g.sizeDst.cy = rcWorkArea.bottom - size.cy; } // アスペクト比の調整 if (g.sizeImg.cx < g.sizeImg.cy * g.sizeDst.cx / g.sizeDst.cy) { g.sizeDst.cx = g.sizeDst.cy * g.sizeImg.cx / g.sizeImg.cy; } else { g.sizeDst.cy = g.sizeDst.cx * g.sizeImg.cy / g.sizeImg.cx; } // ウィンドウ位置のセット rcWnd.right = g.sizeDst.cx + size.cx; rcWnd.bottom = g.sizeDst.cy + size.cy; SetWindowPos(hWnd, NULL, rcWnd.left, rcWnd.top, rcWnd.right, rcWnd.bottom, SWP_NOZORDER); } //------------------------------------------------------------------------------ void OnSizeAdjust(HWND hWnd) { if (g.pImgDat == NULL) return; RECT rc; SetRect(&rc, 0, 0, g.sizeDst.cx, g.sizeDst.cy); AdjustWindowRectEx(&rc, WS_OVERLAPPEDWINDOW, FALSE, 0); SetWindowPos(hWnd, NULL, 0, 0, WIDTH(rc), HEIGHT(rc), SWP_NOZORDER | SWP_NOMOVE); } //------------------------------------------------------------------------------ void OnExecute(void) { if (g.vsFileName.empty()) return; TCHAR szFile[MAX_PATH]; TCHAR szParams[MAX_PATH]; GetModuleFileName(NULL, szFile, MAX_PATH); swprintf_s(szParams, L"\"%s%s\"", g.szBaseDir, g.vsFileName[g.idxCurr].c_str()); SHELLEXECUTEINFO ei; ZeroMemory(&ei, sizeof ei); ei.cbSize = sizeof ei; ei.nShow = SW_SHOWNORMAL; ei.fMask = SEE_MASK_NOCLOSEPROCESS; ei.lpFile = szFile; ei.lpParameters = szParams; ShellExecuteEx(&ei); } //------------------------------------------------------------------------------ void OnPaint(HWND hWnd) { PAINTSTRUCT ps; HDC hdc = BeginPaint(hWnd, &ps); if (g.pImgDat == NULL) goto Exit; RECT rcClt; GetClientRect(hWnd, &rcClt); // 画像とクライアント領域のアスペクト比を比較し // アスペクト比を維持したままクライアント領域に収める if (g.sizeImg.cx < g.sizeImg.cy * rcClt.right / rcClt.bottom) { g.sizeDst.cx = rcClt.bottom * g.sizeImg.cx / g.sizeImg.cy; g.sizeDst.cy = rcClt.bottom; } else { g.sizeDst.cx = rcClt.right; g.sizeDst.cy = rcClt.right * g.sizeImg.cy / g.sizeImg.cx; } RECT rcDst; rcDst.left = (rcClt.right - g.sizeDst.cx) / 2; rcDst.top = (rcClt.bottom - g.sizeDst.cy) / 2; rcDst.right = rcDst.left + g.sizeDst.cx; rcDst.bottom = rcDst.top + g.sizeDst.cy; // 画像描画 RECT rcTmp; SetRect(&rcTmp, 0, 0, g.sizeImg.cx, g.sizeImg.cy); g.pImgDat->Draw(hdc, &rcDst, &rcTmp); // 余白塗り潰し HBRUSH hbr = (HBRUSH)(COLOR_WINDOW + 1); if (rcClt.left < rcDst.left) { CopyRect(&rcTmp, &rcClt); rcTmp.right = rcDst.left; FillRect(hdc, &rcTmp, hbr); } if (rcClt.top < rcDst.top) { CopyRect(&rcTmp, &rcClt); rcTmp.bottom = rcDst.top; FillRect(hdc, &rcTmp, hbr); } if (rcDst.right < rcClt.right) { CopyRect(&rcTmp, &rcClt); rcTmp.left = rcDst.right; FillRect(hdc, &rcTmp, hbr); } if (rcDst.bottom < rcClt.bottom) { CopyRect(&rcTmp, &rcClt); rcTmp.top = rcDst.bottom; FillRect(hdc, &rcTmp, hbr); } Exit: EndPaint(hWnd, &ps); } //------------------------------------------------------------------------------ void GetImage(HWND hWnd) { SAFE_RELEASE(g.pImgDat); if (g.vsFileName.empty()) { SetWindowText(hWnd, APP_NAME); return; } // 画像ファイルの読み込み TCHAR szBuf[512]; LPCTSTR pszFileName = g.vsFileName[g.idxCurr].c_str(); swprintf_s(szBuf, L"%s%s", g.szBaseDir, pszFileName); HRESULT hr = g.pImgDatFac->CreateImageFromFile(szBuf, &g.pImgDat); if (SUCCEEDED(hr)) { hr = g.pImgDat->Decode(SHIMGDEC_DEFAULT, 0, 0); } if (SUCCEEDED(hr)) { hr = g.pImgDat->GetSize(&g.sizeImg); } if (FAILED(hr) || g.sizeImg.cx <= 0 || g.sizeImg.cy <= 0) { SAFE_RELEASE(g.pImgDat); g.sizeImg.cx = g.sizeImg.cy = 0; } // ファイル更新日時の取得 SYSTEMTIME st; MyGetFileTime(&st, szBuf); // タイトルバー swprintf_s(szBuf, L"%s [%d/%d] %d/%02d/%02d %02d:%02d:%02d (%dx%d) - %s", pszFileName, g.idxCurr + 1, g.vsFileName.size(), st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond, g.sizeImg.cx, g.sizeImg.cy, APP_NAME); SetWindowText(hWnd, szBuf); } //------------------------------------------------------------------------------ BOOL MyGetFileTime(LPSYSTEMTIME pSystemTime, LPCTSTR pszFileName) { HANDLE hFile = CreateFile(pszFileName, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { return FALSE; } FILETIME ftLastWrite; FILETIME ftLocal; GetFileTime(hFile, NULL, NULL, &ftLastWrite); FileTimeToLocalFileTime(&ftLastWrite, &ftLocal); FileTimeToSystemTime(&ftLocal, pSystemTime); CloseHandle(hFile); return TRUE; } }} resource.h #highlight(c){{ #define ID_SIZE_ADJUST 100 #define ID_SIZE_NORMAL 101 #define ID_EXECUTE 102 #define IDR_MAIN 128 #define ID_ENTER 129 #define ID_ESCAPE 130 #define ID_LEFT 131 #define ID_UP 132 #define ID_RIGHT 133 #define ID_DOWN 134 #define ID_DELETE 135 }} ImgView3.rc #highlight(c){{ // resource script #include <windows.h> #include "resource.h" // アクセラレータ IDR_MAIN ACCELERATORS BEGIN VK_RETURN, ID_ENTER, VIRTKEY // 0x0D VK_ESCAPE, ID_ESCAPE, VIRTKEY // 0x1B VK_LEFT, ID_LEFT, VIRTKEY // 0x25 VK_UP, ID_UP, VIRTKEY // 0x26 VK_RIGHT, ID_RIGHT, VIRTKEY // 0x27 VK_DOWN, ID_DOWN, VIRTKEY // 0x28 VK_DELETE, ID_DELETE, VIRTKEY // 0x2E "1", ID_SIZE_ADJUST, VIRTKEY // 0x31 VK_NUMPAD1, ID_SIZE_ADJUST, VIRTKEY // 0x61 "2", ID_SIZE_NORMAL, VIRTKEY // 0x32 VK_NUMPAD2, ID_SIZE_NORMAL, VIRTKEY // 0x62 "3", ID_EXECUTE, VIRTKEY // 0x33 VK_NUMPAD3, ID_EXECUTE, VIRTKEY // 0x63 END }}

表示オプション

横に並べて表示:
変化行の前後のみ表示: