// Windows/Shell.cpp
#include "StdAfx.h"
#include "../Common/MyCom.h"
#ifndef _UNICODE
#include "../Common/StringConvert.h"
#endif
#include "COM.h"
#include "Shell.h"
#ifndef _UNICODE
extern bool g_IsNT;
#endif
namespace NWindows {
namespace NShell {
#ifndef UNDER_CE
// SHGetMalloc is unsupported in Windows Mobile?
void CItemIDList::Free()
{
if (m_Object == NULL)
return;
CMyComPtr<IMalloc> shellMalloc;
if (::SHGetMalloc(&shellMalloc) != NOERROR)
throw 41099;
shellMalloc->Free(m_Object);
m_Object = NULL;
}
/*
CItemIDList::(LPCITEMIDLIST itemIDList): m_Object(NULL)
{ *this = itemIDList; }
CItemIDList::(const CItemIDList& itemIDList): m_Object(NULL)
{ *this = itemIDList; }
CItemIDList& CItemIDList::operator=(LPCITEMIDLIST object)
{
Free();
if (object != 0)
{
UINT32 size = GetSize(object);
m_Object = (LPITEMIDLIST)CoTaskMemAlloc(size);
if (m_Object != NULL)
MoveMemory(m_Object, object, size);
}
return *this;
}
CItemIDList& CItemIDList::operator=(const CItemIDList &object)
{
Free();
if (object.m_Object != NULL)
{
UINT32 size = GetSize(object.m_Object);
m_Object = (LPITEMIDLIST)CoTaskMemAlloc(size);
if (m_Object != NULL)
MoveMemory(m_Object, object.m_Object, size);
}
return *this;
}
*/
/////////////////////////////
// CDrop
void CDrop::Attach(HDROP object)
{
Free();
m_Object = object;
m_Assigned = true;
}
void CDrop::Free()
{
if (m_MustBeFinished && m_Assigned)
Finish();
m_Assigned = false;
}
UINT CDrop::QueryCountOfFiles()
{
return QueryFile(0xFFFFFFFF, (LPTSTR)NULL, 0);
}
UString CDrop::QueryFileName(UINT fileIndex)
{
UString fileName;
#ifndef _UNICODE
if (!g_IsNT)
{
AString fileNameA;
UINT bufferSize = QueryFile(fileIndex, (LPTSTR)NULL, 0);
QueryFile(fileIndex, fileNameA.GetBuffer(bufferSize + 2), bufferSize + 1);
fileNameA.ReleaseBuffer();
fileName = GetUnicodeString(fileNameA);
}
else
#endif
{
UINT bufferSize = QueryFile(fileIndex, (LPWSTR)NULL, 0);
QueryFile(fileIndex, fileName.GetBuffer(bufferSize + 2), bufferSize + 1);
fileName.ReleaseBuffer();
}
return fileName;
}
void CDrop::QueryFileNames(UStringVector &fileNames)
{
UINT numFiles = QueryCountOfFiles();
fileNames.ClearAndReserve(numFiles);
for (UINT i = 0; i < numFiles; i++)
fileNames.AddInReserved(QueryFileName(i));
}
bool GetPathFromIDList(LPCITEMIDLIST itemIDList, CSysString &path)
{
bool result = BOOLToBool(::SHGetPathFromIDList(itemIDList, path.GetBuffer(MAX_PATH * 2)));
path.ReleaseBuffer();
return result;
}
#endif
#ifdef UNDER_CE
bool BrowseForFolder(LPBROWSEINFO, CSysString)
{
return false;
}
bool BrowseForFolder(HWND, LPCTSTR, UINT, LPCTSTR, CSysString &)
{
return false;
}
bool BrowseForFolder(HWND /* owner */, LPCTSTR /* title */,
LPCTSTR /* initialFolder */, CSysString & /* resultPath */)
{
/*
// SHBrowseForFolder doesn't work before CE 6.0 ?
if (GetProcAddress(LoadLibrary(L"ceshell.dll", L"SHBrowseForFolder") == 0)
MessageBoxW(0, L"no", L"", 0);
else
MessageBoxW(0, L"yes", L"", 0);
*/
/*
UString s = L"all files";
s += L" (*.*)";
return MyGetOpenFileName(owner, title, initialFolder, s, resultPath, true);
*/
return false;
}
#else
bool BrowseForFolder(LPBROWSEINFO browseInfo, CSysString &resultPath)
{
NWindows::NCOM::CComInitializer comInitializer;
LPITEMIDLIST itemIDList = ::SHBrowseForFolder(browseInfo);
if (itemIDList == NULL)
return false;
CItemIDList itemIDListHolder;
itemIDListHolder.Attach(itemIDList);
return GetPathFromIDList(itemIDList, resultPath);
}
int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data)
{
#ifndef UNDER_CE
switch(uMsg)
{
case BFFM_INITIALIZED:
{
SendMessage(hwnd, BFFM_SETSELECTION, TRUE, data);
break;
}
/*
case BFFM_SELCHANGED:
{
TCHAR dir[MAX_PATH];
if (::SHGetPathFromIDList((LPITEMIDLIST) lp , dir))
SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)dir);
else
SendMessage(hwnd, BFFM_SETSTATUSTEXT, 0, (LPARAM)TEXT(""));
break;
}
*/
default:
break;
}
#endif
return 0;
}
bool BrowseForFolder(HWND owner, LPCTSTR title, UINT ulFlags,
LPCTSTR initialFolder, CSysString &resultPath)
{
CSysString displayName;
BROWSEINFO browseInfo;
browseInfo.hwndOwner = owner;
browseInfo.pidlRoot = NULL;
// there are Unicode/astring problems in WinCE SDK!!!
#ifdef UNDER_CE
browseInfo.pszDisplayName = (LPSTR)displayName.GetBuffer(MAX_PATH);
browseInfo.lpszTitle = (LPCSTR)title;
#else
browseInfo.pszDisplayName = displayName.GetBuffer(MAX_PATH);
browseInfo.lpszTitle = title;
#endif
browseInfo.ulFlags = ulFlags;
browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc : NULL;
browseInfo.lParam = (LPARAM)initialFolder;
return BrowseForFolder(&browseInfo, resultPath);
}
bool BrowseForFolder(HWND owner, LPCTSTR title,
LPCTSTR initialFolder, CSysString &resultPath)
{
return BrowseForFolder(owner, title,
#ifndef UNDER_CE
BIF_NEWDIALOGSTYLE |
#endif
BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT, initialFolder, resultPath);
// BIF_STATUSTEXT; BIF_USENEWUI (Version 5.0)
}
#ifndef _UNICODE
typedef BOOL (WINAPI * SHGetPathFromIDListWP)(LPCITEMIDLIST pidl, LPWSTR pszPath);
bool GetPathFromIDList(LPCITEMIDLIST itemIDList, UString &path)
{
path.Empty();
SHGetPathFromIDListWP shGetPathFromIDListW = (SHGetPathFromIDListWP)
::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHGetPathFromIDListW");
if (shGetPathFromIDListW == 0)
return false;
bool result = BOOLToBool(shGetPathFromIDListW(itemIDList, path.GetBuffer(MAX_PATH * 2)));
path.ReleaseBuffer();
return result;
}
typedef LPITEMIDLIST (WINAPI * SHBrowseForFolderWP)(LPBROWSEINFOW lpbi);
bool BrowseForFolder(LPBROWSEINFOW browseInfo, UString &resultPath)
{
NWindows::NCOM::CComInitializer comInitializer;
SHBrowseForFolderWP shBrowseForFolderW = (SHBrowseForFolderWP)
::GetProcAddress(::GetModuleHandleW(L"shell32.dll"), "SHBrowseForFolderW");
if (shBrowseForFolderW == 0)
return false;
LPITEMIDLIST itemIDList = shBrowseForFolderW(browseInfo);
if (itemIDList == NULL)
return false;
CItemIDList itemIDListHolder;
itemIDListHolder.Attach(itemIDList);
return GetPathFromIDList(itemIDList, resultPath);
}
int CALLBACK BrowseCallbackProc2(HWND hwnd, UINT uMsg, LPARAM /* lp */, LPARAM data)
{
switch(uMsg)
{
case BFFM_INITIALIZED:
{
SendMessageW(hwnd, BFFM_SETSELECTIONW, TRUE, data);
break;
}
/*
case BFFM_SELCHANGED:
{
wchar_t dir[MAX_PATH * 2];
if (shGetPathFromIDListW((LPITEMIDLIST)lp , dir))
SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)dir);
else
SendMessageW(hwnd, BFFM_SETSTATUSTEXTW, 0, (LPARAM)L"");
break;
}
*/
default:
break;
}
return 0;
}
static bool BrowseForFolder(HWND owner, LPCWSTR title, UINT ulFlags,
LPCWSTR initialFolder, UString &resultPath)
{
UString displayName;
BROWSEINFOW browseInfo;
browseInfo.hwndOwner = owner;
browseInfo.pidlRoot = NULL;
browseInfo.pszDisplayName = displayName.GetBuffer(MAX_PATH);
browseInfo.lpszTitle = title;
browseInfo.ulFlags = ulFlags;
browseInfo.lpfn = (initialFolder != NULL) ? BrowseCallbackProc2 : NULL;
browseInfo.lParam = (LPARAM)initialFolder;
return BrowseForFolder(&browseInfo, resultPath);
}
bool BrowseForFolder(HWND owner, LPCWSTR title, LPCWSTR initialFolder, UString &resultPath)
{
if (g_IsNT)
return BrowseForFolder(owner, title,
BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS
// | BIF_STATUSTEXT // This flag is not supported when BIF_NEWDIALOGSTYLE is specified.
, initialFolder, resultPath);
// BIF_STATUSTEXT; BIF_USENEWUI (Version 5.0)
CSysString s;
bool res = BrowseForFolder(owner, GetSystemString(title),
BIF_NEWDIALOGSTYLE | BIF_RETURNONLYFSDIRS
// | BIF_STATUSTEXT // This flag is not supported when BIF_NEWDIALOGSTYLE is specified.
, GetSystemString(initialFolder), s);
resultPath = GetUnicodeString(s);
return res;
}
#endif
#endif
}}