[ttssh2-commit] [10409] 新しいファイルを開くダイアログを使用できるようにした

Back to archive index
scmno****@osdn***** scmno****@osdn*****
2022年 12月 13日 (火) 23:42:53 JST


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\x91΃p\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);


ttssh2-commit メーリングリストの案内
Back to archive index