From cbc7920dbe25ae0e3d206431059fe1f6dc9da73a Mon Sep 17 00:00:00 2001 From: Ziliang Guo Date: Thu, 11 Dec 2014 19:52:47 +0000 Subject: [PATCH] [CORE-7737] Implement browsing with the shell image viewer. Patch by Ricardo Hanke. svn path=/trunk/; revision=65608 --- reactos/dll/win32/shimgvw/CMakeLists.txt | 2 +- reactos/dll/win32/shimgvw/shimgvw.c | 183 +++++++++++++++++++++++ reactos/dll/win32/shimgvw/shimgvw.h | 7 + 3 files changed, 191 insertions(+), 1 deletion(-) diff --git a/reactos/dll/win32/shimgvw/CMakeLists.txt b/reactos/dll/win32/shimgvw/CMakeLists.txt index c923f33bc80..be17accfd3c 100644 --- a/reactos/dll/win32/shimgvw/CMakeLists.txt +++ b/reactos/dll/win32/shimgvw/CMakeLists.txt @@ -10,5 +10,5 @@ list(APPEND SOURCE add_library(shimgvw SHARED ${SOURCE}) set_module_type(shimgvw win32dll) target_link_libraries(shimgvw wine) -add_importlibs(shimgvw advapi32 comctl32 user32 gdi32 gdiplus comdlg32 msvcrt kernel32 ntdll) +add_importlibs(shimgvw advapi32 comctl32 user32 gdi32 gdiplus comdlg32 shlwapi msvcrt kernel32 ntdll) add_cd_file(TARGET shimgvw DESTINATION reactos/system32 FOR all) diff --git a/reactos/dll/win32/shimgvw/shimgvw.c b/reactos/dll/win32/shimgvw/shimgvw.c index 65f48c34204..b6e10d3f09f 100644 --- a/reactos/dll/win32/shimgvw/shimgvw.c +++ b/reactos/dll/win32/shimgvw/shimgvw.c @@ -26,6 +26,7 @@ #include #include #include +#include #define NDEBUG #include @@ -35,6 +36,7 @@ HINSTANCE hInstance; SHIMGVW_SETTINGS shiSettings; +SHIMGVW_FILENODE *currentFile; GpImage *image; WNDPROC PrevProc = NULL; @@ -159,6 +161,166 @@ static void pSaveImageAs(HWND hwnd) free(codecInfo); } +static VOID +pLoadImageFromNode(SHIMGVW_FILENODE *node, HWND hwnd) +{ + WCHAR szTitleBuf[800]; + WCHAR szResStr[512]; + WCHAR *c; + + if (node) + { + c = wcsrchr(node->FileName, '\\'); + if (c) + { + c++; + } + + LoadStringW(hInstance, IDS_APPTITLE, szResStr, 512); + StringCbPrintfExW(szTitleBuf, 800, NULL, NULL, 0, L"%ls%ls%ls", szResStr, L" - ", c); + SetWindowTextW(hwnd, szTitleBuf); + + if (image) + { + GdipDisposeImage(image); + } + + pLoadImage(node->FileName); + InvalidateRect(hDispWnd, NULL, TRUE); + UpdateWindow(hDispWnd); + } +} + +static SHIMGVW_FILENODE* +pBuildFileList(LPWSTR szFirstFile) +{ + HANDLE hFindHandle; + WCHAR *extension; + WCHAR szSearchPath[MAX_PATH]; + WCHAR szSearchMask[MAX_PATH]; + WCHAR szFileTypes[MAX_PATH]; + WIN32_FIND_DATAW findData; + SHIMGVW_FILENODE *currentNode; + SHIMGVW_FILENODE *root; + SHIMGVW_FILENODE *conductor; + ImageCodecInfo *codecInfo; + UINT num; + UINT size; + UINT j; + + + wcscpy(szSearchPath, szFirstFile); + PathRemoveFileSpecW(szSearchPath); + + GdipGetImageDecodersSize(&num, &size); + codecInfo = malloc(size); + if (!codecInfo) + { + DPRINT1("malloc() failed in pLoadFileList()\n"); + return NULL; + } + + GdipGetImageDecoders(num, size, codecInfo); + + root = malloc(sizeof(SHIMGVW_FILENODE)); + if (!root) + { + DPRINT1("malloc() failed in pLoadFileList()\n"); + free(codecInfo); + return NULL; + } + + conductor = root; + + for (j = 0; j < num; ++j) + { + StringCbPrintfExW(szFileTypes, MAX_PATH, NULL, NULL, 0, L"%ls", codecInfo[j].FilenameExtension); + + extension = wcstok(szFileTypes, L";"); + while (extension != NULL) + { + StringCbPrintfExW(szSearchMask, MAX_PATH, NULL, NULL, 0, L"%ls%ls%ls", szSearchPath, L"\\", extension); + + hFindHandle = FindFirstFileW(szSearchMask, &findData); + if (hFindHandle != INVALID_HANDLE_VALUE) + { + do + { + StringCbPrintfExW(conductor->FileName, MAX_PATH, NULL, NULL, 0, L"%ls%ls%ls", szSearchPath, L"\\", findData.cFileName); + + // compare the name of the requested file with the one currently found. + // if the name matches, the current node is returned by the function. + if (wcscmp(szFirstFile, conductor->FileName) == 0) + { + currentNode = conductor; + } + + conductor->Next = malloc(sizeof(SHIMGVW_FILENODE)); + + // if malloc fails, make circular what we have and return it + if (!conductor->Next) + { + DPRINT1("malloc() failed in pLoadFileList()\n"); + + conductor->Next = root; + root->Prev = conductor; + + FindClose(hFindHandle); + free(codecInfo); + return conductor; + } + + conductor->Next->Prev = conductor; + conductor = conductor->Next; + } + while (FindNextFileW(hFindHandle, &findData) != 0); + + FindClose(hFindHandle); + } + + extension = wcstok(NULL, L";"); + } + } + + // we now have a node too much in the list. In case the requested file was not found, + // we use this node to store the name of it, otherwise we free it. + if (currentNode == NULL) + { + StringCbPrintfExW(conductor->FileName, MAX_PATH, NULL, NULL, 0, L"%ls", szFirstFile); + currentNode = conductor; + } + else + { + conductor = conductor->Prev; + free(conductor->Next); + } + + // link the last node with the first one to make the list circular + conductor->Next = root; + root->Prev = conductor; + conductor = currentNode; + + free(codecInfo); + + return conductor; +} + +static VOID +pFreeFileList(SHIMGVW_FILENODE *root) +{ + SHIMGVW_FILENODE *conductor; + + root->Prev->Next = NULL; + root->Prev = NULL; + + while (root) + { + conductor = root; + root = conductor->Next; + free(conductor); + } +} + static VOID ImageView_DrawImage(HWND hwnd) { @@ -410,9 +572,17 @@ ImageView_WndProc(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lParam) switch (wParam) { case IDC_PREV: + { + currentFile = currentFile->Prev; + pLoadImageFromNode(currentFile, hwnd); + } break; case IDC_NEXT: + { + currentFile = currentFile->Next; + pLoadImageFromNode(currentFile, hwnd); + } break; case IDC_ZOOMP: @@ -522,6 +692,7 @@ ImageView_CreateWindow(HWND hwnd, LPWSTR szFileName) ULONG_PTR gdiplusToken; WNDCLASS WndClass = {0}; TCHAR szBuf[512]; + WCHAR szInitialFile[MAX_PATH]; HWND hMainWnd; MSG msg; @@ -560,6 +731,16 @@ ImageView_CreateWindow(HWND hwnd, LPWSTR szFileName) CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, NULL, NULL, hInstance, NULL); + // make sure the path has no quotes on it + wcscpy(szInitialFile, szFileName); + PathUnquoteSpacesW(szInitialFile); + + currentFile = pBuildFileList(szInitialFile); + if (currentFile) + { + pLoadImageFromNode(currentFile, hMainWnd); + } + // Show it ShowWindow(hMainWnd, SW_SHOW); UpdateWindow(hMainWnd); @@ -571,6 +752,8 @@ ImageView_CreateWindow(HWND hwnd, LPWSTR szFileName) DispatchMessageW(&msg); } + pFreeFileList(currentFile); + if (image) GdipDisposeImage(image); GdiplusShutdown(gdiplusToken); diff --git a/reactos/dll/win32/shimgvw/shimgvw.h b/reactos/dll/win32/shimgvw/shimgvw.h index 47135ead049..9bce39c6cbf 100644 --- a/reactos/dll/win32/shimgvw/shimgvw.h +++ b/reactos/dll/win32/shimgvw/shimgvw.h @@ -13,3 +13,10 @@ typedef struct INT Right; INT Bottom; } SHIMGVW_SETTINGS; + +typedef struct SHIMGVW_FILENODE_INTERNAL +{ + WCHAR FileName[MAX_PATH]; + struct SHIMGVW_FILENODE_INTERNAL *Prev; + struct SHIMGVW_FILENODE_INTERNAL *Next; +} SHIMGVW_FILENODE;