社本@元ネオニート Blog

社本@元ネオニート (元々ワック) のいたずら書き (for Programmers)

AILight Banner
AILight Blog

プロフィール

社本@元ネオニート Blog
働いたら負けかなと思っていたのですが。。とうとう働き始めました。アメリカのシアトル・エリアにある企業向けのバックアップソフトを開発している会社です。日本人は私だけ。なんとか。。やっていけてるようです。

目次

Blog 利用状況

記事分類

過去の記事

タグ

新しいファイルダイアログ(IFileDialog) その2 - Windows Vista/Shell

> 新APIを試して気づいた。.NET Framework+Vistaでファイルオープンダイアログ使うとXP仕様のダイアログで表示されるのね。かなり悲しい。

ファイル名を取得する場合、GetOpenFileName/GetSaveFileName APIが
今までずっと使われていました。
OPENFILENAME構造体の拡張はありますが、Win16時代から(15年くらい?)
ずっと同じAPIが使われていたことになります。

しかし、Windows Vistaでは新しいCOMベースのAPIが追加されました。
新しいファイアルダイログを呼び出すために、この新しいCOMベースの
APIを呼び出す必要があります。

新しいファイアルダイアログを簡単に呼び出す関数を作っていますので、
紹介しておきます。

---
#include <ShObjIdl.h>


/////////////////////////////////////////////////////////////////////////////
// CComDlgFilterSpec
class CComDlgFilterSpec : public COMDLG_FILTERSPEC
{
protected:
 typedef CComDlgFilterSpec     thisClass;

public:
 CComDlgFilterSpec(LPCTSTR szName, LPCTSTR szSpec)
 {
  USES_CONVERSION;

  ::ZeroMemory(this, sizeof(COMDLG_FILTERSPEC));
  thisClass::MemAllocAndCopy(this->pszName, T2W((LPTSTR)szName));
  thisClass::MemAllocAndCopy(this->pszSpec, T2W((LPTSTR)szSpec));
 }
 CComDlgFilterSpec(const CComDlgFilterSpec& newVal)
 {
  ::ZeroMemory(this, sizeof(COMDLG_FILTERSPEC));
  thisClass::MemAllocAndCopy(this->pszName, newVal.pszName);
  thisClass::MemAllocAndCopy(this->pszSpec, newVal.pszSpec);
 }
 ~CComDlgFilterSpec()
 {
  thisClass::MemFree(this->pszName);
  thisClass::MemFree(this->pszSpec);
 }

public:
 CComDlgFilterSpec& operator =(const CComDlgFilterSpec& newVal)
 {
  if (this != &newVal)
  {
   thisClass::MemAllocAndCopy(this->pszName, newVal.pszName);
   thisClass::MemAllocAndCopy(this->pszSpec, newVal.pszSpec);
  }

  return *this;
 }

protected:
 HRESULT MemAllocAndCopy(LPCWSTR& szDst, LPCWSTR szSrc)
 {
  if (szDst != NULL)
  {
   thisClass::MemFree(szDst);
  }

  CStringW strSrc = szSrc;

  int nLength = strSrc.GetLength();
  void* pDst = ::CoTaskMemAlloc((nLength + 1) * 2);
  if (pDst == NULL)
  {
   return E_OUTOFMEMORY;
  }

  ::ZeroMemory(pDst, (nLength + 1) * 2);
  ::CopyMemory(pDst, (LPCWSTR)strSrc, nLength * 2);
  szDst = (LPCWSTR)pDst;

  return S_OK;
 }
 HRESULT MemFree(LPCWSTR& szDst)
 {
  ::CoTaskMemFree((void*)szDst);
  szDst = NULL;

  return S_OK;
 }
};


/////////////////////////////////////////////////////////////////////////////
// CComDlgFilterSpecs
class CComDlgFilterSpecs : public std::vector
{
protected:
 typedef CComDlgFilterSpecs     thisClass;

public:
 CComDlgFilterSpecs()
 {
 }
 CComDlgFilterSpecs(LPCTSTR szFilter)
 {
  HRESULT hr = S_OK;
  
  hr = this->Load(szFilter);
  if (FAILED(hr))
  {
   // 無視する。。
  }
 }
 ~CComDlgFilterSpecs()
 {
 }

public:
 HRESULT Load(LPCTSTR szFilter)
 {
  if (szFilter == NULL)
  {
   return E_FAIL;
  }

  HRESULT hr = S_OK;

  TCHAR szWin32Filter[1024] = { 0 };
  _tcscpy_s(szWin32Filter, szFilter);

  LPTSTR p = (LPTSTR)szWin32Filter;
  while ((p = _tcschr(p, '|')) != NULL)
  {
   *p++ = NULL;
  }

  /*LPTSTR*/ p = (LPTSTR)szWin32Filter;
  while (*p != NULL)
  {
   TCHAR szName[256] = { 0 };
   _tcscpy_s(szName, p);
   p += _tcslen(p) + 1;
   TCHAR szSpec[256] = { 0 };
   _tcscpy_s(szSpec, p);
   p += _tcslen(p) + 1;
//   ATLTRACE(_T("%s : %s\n"), szName, szSpec);

   hr = this->Append(szName, szSpec);
   if (FAILED(hr))
   {
    // 無視する。。
   }
  }

  return S_OK;
 }

public:
 HRESULT Append(LPCTSTR szName, LPCTSTR szSpec)
 {
  this->push_back(CComDlgFilterSpec(szName, szSpec));

  return S_OK;
 }
 HRESULT Append(const CComDlgFilterSpec& filterSpec)
 {
  this->push_back(filterSpec);

  return S_OK;
 }
};


/////////////////////////////////////////////////////////////////////////////
// CFileDialogHelper

class CFileDialogHelper
{
protected:
 typedef CFileDialogHelper     thisClass;

protected:
 CFileDialogHelper();
 virtual ~CFileDialogHelper();

public:
 static CString GetOpenFileName(LPCTSTR szDefaultExt, LPCTSTR szDefaultFileName, LPCTSTR szFilter = _T("すべてのファイル (*.*)|*.*||"), HWND hWnd = ::GetActiveWindow())
 {
  USES_CONVERSION;

  HRESULT hr = S_OK;

  IFileDialogPtr spFileDialog = NULL;
//  hr = spFileDialog.CreateInstance(CLSID_FileOpenDialog);
  hr = spFileDialog.CreateInstance(__uuidof(FileOpenDialog));
  if (FAILED(hr))
  {
   return _T("");
  }

  DWORD dwFlags = 0;
  hr = spFileDialog->GetOptions(&dwFlags);
  if (FAILED(hr))
  {
   return _T("");
  }

  hr = spFileDialog->SetOptions(dwFlags | FOS_FORCEFILESYSTEM);
  if (FAILED(hr))
  {
   return _T("");
  }

  CComDlgFilterSpecs filterSpecs(szFilter);
  hr = spFileDialog->SetFileTypes((UINT)filterSpecs.size(), (const COMDLG_FILTERSPEC*)&filterSpecs[0]);
  if (FAILED(hr))
  {
   return _T("");
  }

  hr = spFileDialog->SetFileTypeIndex(1);
  if (FAILED(hr))
  {
   return _T("");
  }

  hr = spFileDialog->SetDefaultExtension(T2W((LPTSTR)szDefaultExt));
  if (FAILED(hr))
  {
   return _T("");
  }

  hr = spFileDialog->Show(hWnd);
  if (FAILED(hr))
  {
   return _T("");
  }

  IShellItemPtr spShellItem;
  hr = spFileDialog->GetResult(&spShellItem);
  if (FAILED(hr))
  {
   return _T("");
  }

  LPWSTR szFileName = NULL;
  hr = spShellItem->GetDisplayName(SIGDN_FILESYSPATH, &szFileName);
  if (FAILED(hr))
  {
   return _T("");
  }

  CString strFileName = W2T(szFileName);
  ::CoTaskMemFree(szFileName);

  return strFileName;
 }
 static CString GetSaveFileName(LPCTSTR szDefaultExt, LPCTSTR szDefaultFileName, LPCTSTR szFilter = _T("すべてのファイル (*.*)|*.*||"), HWND hWnd = ::GetActiveWindow())
 {
  USES_CONVERSION;

  HRESULT hr = S_OK;

  IFileDialogPtr spFileDialog = NULL;
//  hr = spFileDialog.CreateInstance(CLSID_FileSaveDialog);
  hr = spFileDialog.CreateInstance(__uuidof(FileSaveDialog));
  if (FAILED(hr))
  {
   return _T("");
  }

  DWORD dwFlags = 0;
  hr = spFileDialog->GetOptions(&dwFlags);
  if (FAILED(hr))
  {
   return _T("");
  }

  hr = spFileDialog->SetOptions(dwFlags | FOS_FORCEFILESYSTEM);
  if (FAILED(hr))
  {
   return _T("");
  }

  CComDlgFilterSpecs filterSpecs(szFilter);
  hr = spFileDialog->SetFileTypes((UINT)filterSpecs.size(), (const COMDLG_FILTERSPEC*)&filterSpecs[0]);
  if (FAILED(hr))
  {
   return _T("");
  }

  hr = spFileDialog->SetFileTypeIndex(1);
  if (FAILED(hr))
  {
   return _T("");
  }

  hr = spFileDialog->SetDefaultExtension(T2W((LPTSTR)szDefaultExt));
  if (FAILED(hr))
  {
   return _T("");
  }

  CString strName = ::PathFindFileName(szDefaultFileName);
  hr = spFileDialog->SetFileName(T2W((LPTSTR)(LPCTSTR)strName));
  if (FAILED(hr))
  {
   return _T("");
  }

  hr = spFileDialog->Show(hWnd);
  if (FAILED(hr))
  {
   return _T("");
  }

  IShellItemPtr spShellItem;
  hr = spFileDialog->GetResult(&spShellItem);
  if (FAILED(hr))
  {
   return _T("");
  }
 
  LPWSTR szFileName = NULL;
  hr = spShellItem->GetDisplayName(SIGDN_FILESYSPATH, &szFileName);
  if (FAILED(hr))
  {
   return _T("");
  }

  CString strFileName = W2T(szFileName);
  ::CoTaskMemFree(szFileName);

  return strFileName;
 }
};
---

■IFileDialog Interface - MSDN
http://msdn2.microsoft.com/en-gb/library/ms645937.aspx

■IShellItem Interface - MSDN
http://msdn2.microsoft.com/en-us/library/ms632806.aspx

■新しいファイルダイアログ(IFileDialog) - Windows Vista/Shell - 社本@ワック Blog
http://www.ailight.jp/blog/sha256/archive/2005/10/07/9877.aspx

■[.NET]VistaのFileOpen(Save)Dialog - 新日々此何有哉
http://d.hatena.ne.jp/kkamegawa/20061211

投稿日時 : 2006年12月12日 5:01


コメントを追加

#  新しいファイルダイアログ(IFileDialog) その3 - Windows Vista/Shell 2006年12月27日 18:35 社本@ワック Blog

新しいファイルダイアログ(IFileDialog) その3 - Windows Vista/Shell

#  新しいファイルダイアログ(IFileDialog) その3 - Windows Vista/Shell 2006年12月27日 18:51 社本@ワック Blog

新しいファイルダイアログ(IFileDialog) その3 - Windows Vista/Shell
タイトル
名前
URL
コメント