Revision: 10409 https://osdn.net/projects/ttssh2/scm/svn/commits/10409 Author: zmatsuo Date: 2022-12-13 23:42:53 +0900 (Tue, 13 Dec 2022) Log Message: ----------- 新しいファイルを開くダイアログを使用できるようにした - IFileDialog(IFileOpenDialog, FileSaveDialog)を使用 - MAX_PATH以上のファイル名を扱えるようになった - r10403 - helpボタンが標準でついていない - ダイアログをリサイズできるようにした - OFN_EXPLORER | OFN_ENABLESIZING を追加 - ticket #39314 Revision Links: -------------- https://osdn.net/projects/ttssh2/scm/svn/commits/10403 Ticket Links: ------------ https://osdn.net/projects/ttssh2/tracker/detail/39314 Modified Paths: -------------- trunk/teraterm/common/ttcommdlg.cpp trunk/teraterm/common/ttcommdlg.h -------------- next part -------------- Modified: trunk/teraterm/common/ttcommdlg.cpp =================================================================== --- trunk/teraterm/common/ttcommdlg.cpp 2022-12-11 15:54:41 UTC (rev 10408) +++ trunk/teraterm/common/ttcommdlg.cpp 2022-12-13 14:42:53 UTC (rev 10409) @@ -38,6 +38,19 @@ #include "ttcommdlg.h" +#define NEW_DIALOG_ENABLE 1 // Vista+ +#define OLD_DIALOG_ENABLE 1 + +// VS2005\x82̏ꍇ +#if _MSC_VER == 1400 +// 2005\x82Ŏg\x82\xA6\x82\xE9SDK\x82ɂ\xCDIFileOpenDialog\x82\xAA\x82Ȃ\xA2 +#undef NEW_DIALOG_ENABLE +#define NEW_DIALOG_ENABLE 0 +#undef OLD_DIALOG_ENABLE +#define OLD_DIALOG_ENABLE 1 +#endif + +#if OLD_DIALOG_ENABLE static int CALLBACK BrowseCallback(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData) { switch(uMsg) { @@ -60,7 +73,7 @@ /** * API\x94\xC5,\x8CÂ\xA2 */ -static BOOL TTSHBrowseForFolderWAPI(TTBROWSEINFOW *bi, const wchar_t *def, wchar_t **folder) +static BOOL TTSHBrowseForFolderWAPI(const TTBROWSEINFOW *bi, const wchar_t *def, wchar_t **folder) { wchar_t buf[MAX_PATH]; // PIDL\x8C`\x8E\xAE\x82Ŏ\xE6\x82\xE9\x82̂Ń_\x83~\x81[,\x88ꉞMAX_PATH\x92\xB7\x82Ŏ\xE9 BROWSEINFOW b = {}; @@ -87,6 +100,8 @@ // PIDL\x8C`\x8E\xAE\x82̖߂\xE8\x92l\x82̃t\x83@\x83C\x83\x8B\x83V\x83X\x83e\x83\x80\x82̃p\x83X\x82ɕϊ\xB7 #if _MSC_VER > 1400 // VS2005\x82Ŏg\x82\xA6\x82\xE9SDK\x82ɂ\xCDSHGetPathFromIDListEx()\x82\xAA\x93\xFC\x82\xC1\x82Ă\xA2\x82Ȃ\xA2 + // TODO + // SHGetPathFromIDListEx() \x82\xF0 win32help \x82֎\x9D\x82\xC1\x82Ă\xA2\x82\xAD if (true) { size_t len = MAX_PATH / 2; wchar_t *path = NULL; @@ -118,6 +133,7 @@ CoTaskMemFree(pidl); return TRUE; } +#endif // OLD_DIALOG_ENABLE /** * SHBrowseForFolderW() \x82قڌ݊\xB7\x8A\x94 @@ -135,17 +151,19 @@ * \x95s\x97v\x82ɂȂ\xC1\x82\xBD\x82\xE7 free() \x82\xB7\x82邱\x82\xC6 * MAX_PATH\x8F\xE3\x8C\xC0\x82Ȃ\xB5 */ -BOOL TTSHBrowseForFolderW(TTBROWSEINFOW *bi, const wchar_t *def, wchar_t **folder) +BOOL TTSHBrowseForFolderW(const TTBROWSEINFOW *bi, const wchar_t *def, wchar_t **folder) { -#if _MSC_VER == 1400 // VS2005\x82̏ꍇ - // 2005\x82Ŏg\x82\xA6\x82\xE9SDK\x82ɂ\xCDIFileOpenDialog\x82\xAA\x82Ȃ\xA2 +#if !NEW_DIALOG_ENABLE return TTSHBrowseForFolderWAPI(bi, def, folder); #else IFileOpenDialog *pDialog; HRESULT hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER, IID_IFileOpenDialog, (void **)&pDialog); if (FAILED(hr)) { - // IFileOpenDialog \x82\xAA\x8Eg\x82\xA6\x82Ȃ\xA2OS, Vista\x88ȑO +#if OLD_DIALOG_ENABLE return TTSHBrowseForFolderWAPI(bi, def, folder); +#else + return FALSE; +#endif } DWORD options; @@ -152,7 +170,7 @@ pDialog->GetOptions(&options); pDialog->SetOptions(options | FOS_PICKFOLDERS); pDialog->SetTitle(bi->lpszTitle); - { + if (def != NULL) { IShellItem *psi; hr = SHCreateItemFromParsingName(def, NULL, IID_IShellItem, (void **)&psi); if (SUCCEEDED(hr)) { @@ -207,7 +225,7 @@ return TTSHBrowseForFolderW(&bi, def, folder); } -static BOOL GetOpenSaveFileNameW(const TTOPENFILENAMEW *ofn, bool save, wchar_t **filename) +static BOOL GetOpenSaveFileNameWAPI(const TTOPENFILENAMEW *ofn, bool save, wchar_t **filename) { // GetSaveFileNameW(), GetOpenFileNameW() \x82\xAA\x83J\x83\x8C\x83\x93\x83g\x83t\x83H\x83\x8B\x83_\x82\xF0\x95ύX\x82\xB5\x82Ă\xB5\x82܂\xA4\x82\xBD\x82\xDF wchar_t *curdir; @@ -226,11 +244,10 @@ } } } - else { - if (ofn->lpstrInitialDir != NULL) { - // \x8F\x89\x8A\xFA\x83t\x83H\x83\x8B\x83_\x8Ew\x92肠\x82\xE8 - init_dir = _wcsdup(ofn->lpstrInitialDir); - } + + if (init_dir == NULL && ofn->lpstrInitialDir != NULL) { + // \x8F\x89\x8A\xFA\x83t\x83H\x83\x8B\x83_\x8Ew\x92肠\x82\xE8 + init_dir = _wcsdup(ofn->lpstrInitialDir); } wchar_t File[MAX_PATH]; @@ -250,6 +267,7 @@ o.lpstrTitle = ofn->lpstrTitle; o.lpstrInitialDir = init_dir; o.Flags = ofn->Flags; + o.Flags |= (OFN_EXPLORER | OFN_ENABLESIZING); BOOL ok = save ? GetSaveFileNameW(&o) : GetOpenFileNameW(&o); #if defined(_DEBUG) if (!ok) { @@ -267,6 +285,148 @@ return ok; } +#if NEW_DIALOG_ENABLE +static COMDLG_FILTERSPEC *CreateFilterSpec(const wchar_t *filter, UINT *count) +{ + if (filter == NULL) { + *count = 0; + return NULL; + } + int n = 0; + const wchar_t *p = filter; + while (*p != 0) { + p += wcslen(p); + p++; + p += wcslen(p); + p++; + if (p - filter > 32*1024) { + // \x89\xBD\x82\xA9\x82\xA8\x82\xA9\x82\xB5\x82\xA2 + *count = 0; + return NULL; + } + n++; + } + *count = n; + + COMDLG_FILTERSPEC *spec = (COMDLG_FILTERSPEC *)malloc(sizeof(COMDLG_FILTERSPEC) * n); + p = filter; + for (int i = 0; i < n; i++) { + spec[i].pszName = p; + p += wcslen(p); + p++; + spec[i].pszSpec = p; + p += wcslen(p); + p++; + } + return spec; +} +#endif // NEW_DIALOG_ENABLE + +static BOOL GetOpenSaveFileNameW(const TTOPENFILENAMEW *ofn, bool save, wchar_t **filename) +{ +#if !NEW_DIALOG_ENABLE + return GetOpenSaveFileNameWAPI(ofn, save, filename); +#else + HRESULT hr = 0; + IFileDialog *pFile; + REFCLSID clsid = save ? CLSID_FileSaveDialog : CLSID_FileOpenDialog; + hr = CoCreateInstance(clsid, NULL, CLSCTX_ALL, IID_IFileDialog, (void**)&pFile); + if (FAILED(hr)) { +#if OLD_DIALOG_ENABLE + return GetOpenSaveFileNameWAPI(ofn, save, filename); +#else + return FALSE; +#endif + } + + DWORD options; + pFile->GetOptions(&options); + pFile->SetOptions(options | FOS_NOCHANGEDIR); + + // \x8F\x89\x8A\xFA\x83t\x83H\x83\x8B\x83_ + wchar_t* init_dir = NULL; + if (ofn->lpstrFile != NULL) { + // \x8F\x89\x8A\xFA\x83t\x83@\x83C\x83\x8B\x8Ew\x92肠\x82\xE8 + if (!IsRelativePathW(ofn->lpstrFile)) { + // \x8F\x89\x8A\xFA\x83t\x83@\x83C\x83\x8B\x82\xAA\x90\xE2\x91p\x83X\x82Ȃ\xE7\x83p\x83X\x82\xF0\x8E\xE6\x82\xE8\x8Fo\x82\xB5\x82ď\x89\x8A\xFA\x83t\x83H\x83\x8B\x83_\x82ɂ\xB7\x82\xE9 + init_dir = _wcsdup(ofn->lpstrFile); + wchar_t* p = wcsrchr(init_dir, L'\\'); + if (p != NULL) { + *p = L'\0'; + } + } + } + if (init_dir == NULL && ofn->lpstrInitialDir != NULL) { + // \x8F\x89\x8A\xFA\x83t\x83H\x83\x8B\x83_\x8Ew\x92肠\x82\xE8 + init_dir = _wcsdup(ofn->lpstrInitialDir); + } + if (init_dir != NULL) { + IShellItem* psi; + hr = SHCreateItemFromParsingName(init_dir, NULL, IID_IShellItem, (void**)&psi); + if (SUCCEEDED(hr)) { + hr = pFile->SetFolder(psi); + psi->Release(); + } + free(init_dir); + init_dir = NULL; + } + + // \x83^\x83C\x83g\x83\x8B + if (ofn->lpstrTitle != NULL) { + pFile->SetTitle(ofn->lpstrTitle); + } + + // (\x8Dŏ\x89\x82\xA9\x82\xE7\x93\xFC\x97͂\xB3\x82\xEA\x82Ă\xA2\x82\xE9)\x83t\x83@\x83C\x83\x8B\x96\xBC + if (ofn->lpstrFile != NULL) { + // \x83t\x83\x8B\x83p\x83X\x82ł\xA2\x82\xEA\x82\xE9\x82Ƃ\xBE\x82߂炵\x82\xA2 + const wchar_t *base = wcsrchr(ofn->lpstrFile, L'\\'); + if (base != NULL) { + base++; + } + else { + // \x83p\x83X\x8B\xE6\x90肪\x82Ȃ\xA2 + base = ofn->lpstrFile; + } + pFile->SetFileName(base); + } + + if (ofn->lpstrFilter != NULL) { + UINT count; + COMDLG_FILTERSPEC *filter_spec = CreateFilterSpec(ofn->lpstrFilter, &count); + pFile->SetFileTypes(count, filter_spec); + pFile->SetFileTypeIndex(ofn->nFilterIndex); + free(filter_spec); + } + + if (ofn->lpstrDefExt != NULL) { + pFile->SetDefaultExtension(ofn->lpstrDefExt); + } + + BOOL result = FALSE; + hr = pFile->Show(ofn->hwndOwner); + if (SUCCEEDED(hr)) { + IShellItem *pItem; + hr = pFile->GetResult(&pItem); + if (SUCCEEDED(hr)) { + PWSTR pFilename; + hr = pItem->GetDisplayName(SIGDN_FILESYSPATH, &pFilename); + if (SUCCEEDED(hr)) { + *filename = _wcsdup(pFilename); + CoTaskMemFree(pFilename); + result = TRUE; + } + pItem->Release(); + } + } + pFile->Release(); + + if (!result) { + *filename = NULL; + } + return result; +#endif +} + /** * GetOpenFileNameW() \x8C݊\xB7\x8A\x94 * \x88قȂ\xE9\x93_ @@ -273,6 +433,7 @@ * - \x83t\x83H\x83\x8B\x83_\x82\xAA\x95ύX\x82\xB3\x82\xEA\x82Ȃ\xA2 * - \x8F\x89\x8A\xFA\x83t\x83H\x83\x8B\x83_\x90ݒ\xE8 * - \x8F\x89\x8A\xFA\x83t\x83@\x83C\x83\x8B\x82̃t\x83\x8B\x83p\x83X\x82\xF0\x8F\x89\x8A\xFA\x83t\x83H\x83\x8B\x83_\x82ɂ\xB7\x82\xE9 + * - OFN_SHOWHELP \x82\xF0\x83T\x83|\x81[\x83g\x82\xB5\x82Ă\xA2\x82Ȃ\xA2 * * @param filename \x91I\x91\xF0\x82\xB3\x82ꂽ\x83t\x83@\x83C\x83\x8B\x96\xBC(\x96߂\xE8\x92l\x82\xAA TRUE\x82̎\x9E) * MAX_PATH\x90\xA7\x8C\xC0\x82Ȃ\xB5\x81A\x95s\x97v\x82ɂȂ\xC1\x82\xBD\x82\xE7free()\x82\xB7\x82邱\x82\xC6 Modified: trunk/teraterm/common/ttcommdlg.h =================================================================== --- trunk/teraterm/common/ttcommdlg.h 2022-12-11 15:54:41 UTC (rev 10408) +++ trunk/teraterm/common/ttcommdlg.h 2022-12-13 14:42:53 UTC (rev 10409) @@ -35,22 +35,15 @@ #endif typedef struct { - HWND hwndOwner; - HINSTANCE hInstance; - LPCWSTR lpstrFilter; - LPWSTR lpstrCustomFilter; - DWORD nMaxCustFilter; - DWORD nFilterIndex; - LPCWSTR lpstrFile; // \x8F\x89\x8A\xFA\x83t\x83@\x83C\x83\x8B\x96\xBC - LPWSTR lpstrFileTitle; - DWORD nMaxFileTitle; - LPCWSTR lpstrInitialDir; // \x8F\x89\x8A\xFA\x83t\x83H\x83\x8B\x83_ - LPCWSTR lpstrTitle; - DWORD Flags; - WORD nFileOffset; - WORD nFileExtension; - LPCWSTR lpstrDefExt; - DWORD FlagsEx; + HWND hwndOwner; + HINSTANCE hInstance; + LPCWSTR lpstrFilter; + DWORD nFilterIndex; + LPCWSTR lpstrFile; // \x8F\x89\x8A\xFA\x83t\x83@\x83C\x83\x8B\x96\xBC + LPCWSTR lpstrInitialDir; // \x8F\x89\x8A\xFA\x83t\x83H\x83\x8B\x83_ + LPCWSTR lpstrTitle; + DWORD Flags; + LPCWSTR lpstrDefExt; } TTOPENFILENAMEW; BOOL TTGetOpenFileNameW(const TTOPENFILENAMEW *ofn, wchar_t **filename); @@ -62,7 +55,7 @@ UINT ulFlags; } TTBROWSEINFOW; -BOOL TTSHBrowseForFolderW(TTBROWSEINFOW *bi, const wchar_t *def, wchar_t **folder); +BOOL TTSHBrowseForFolderW(const TTBROWSEINFOW *bi, const wchar_t *def, wchar_t **folder); DllExport BOOL doSelectFolder(HWND hWnd, char *path, int pathlen, const char *def, const char *msg); BOOL doSelectFolderW(HWND hWnd, const wchar_t *def, const wchar_t *msg, wchar_t **folder);