原文链接:CYABFFW: Yet Another BrowseForFolder Wrapper
以良好的MFC风格将Shell API函数SHBrowseForFolder()封装为一个CWnd子类。
使用示例1:
CYABFFWdlg();
if
(IDOK
==
dlg.DoModal())
{
CStrings=dlg.GetPath();
//Dosomethingwith`s'
CYABFFWdlg(_T(
"
Pleaseselectadirectory
"
),
//
Hinttouser
BIF_USE_NEWUI,
//
Flagsforthedlg
this
,
//
Parentwindow
CSIDL_DRIVES);
//
Rootofsearch
if
(IDOK
==
dlg.DoModal())
{
CStrings=dlg.GetPath();
//Dosomethingwith`s'
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->
classCYABFFW:publicCWnd

{
//Construction
public:
/**////Constructwithatextualhint,BFFflags,parentwindow,a
///rootfolderexpressedasaCSIDLvalue,andadefault
///selectionexpressedasatextualpath
CYABFFW(constCString&strHint=CString(),UINTnFlags=0U,
CWnd*pParentWnd=NULL,intnRootFolder=CSIDL_DESKTOP,
constCString&strDefaultSel=CString());
/**////ConstructwithadefaultselectionexpressedasaCSIDL
///value,atextualhint,BFFflags,parentwindow,&aroot
///folderexpressedasaCSIDLvalue
CYABFFW(intnDefaultSel,constCString&strHint=CString(),
UINTnFlags=0U,CWnd*pParentWnd=NULL,
intnRootFolder=CSIDL_DESKTOP);
/**////ConstructwithahintfromResource,BFFflags,parent
///window,arootfolderexpressedasaCSIDLvalue,anda
///defaultselectionexpressedasatextualpath
CYABFFW(intnHint,UINTnFlags=0U,CWnd*pParentWnd=NULL,
intnRootFolder=CSIDL_DESKTOP,
constCString&strDefaultSel=CString());
/**////ConstructwithahintfromResource,adefaultselection
///expressedasaCSIDLvalue,BFFflags,parentwindow,&a
///rootfolderexpressedasaCSIDLvalue
CYABFFW(intnDefaultSel,intnHint,UINTnFlags=0U,
CWnd*pParentWnd=NULL,intnRootFolder=CSIDL_DESKTOP);
/**////Constructwithatextualhint,anarbitraryrootfolder,
///BFFflags,aparentwindow,andadefaultselection
///expressedasatextualpath
CYABFFW(constCString&strHint,constCString&strRoot,
UINTnFlags=0U,CWnd*pParentWnd=NULL,
constCString&strDefaultSel=CString());
/**////Constructwithatextualhint,adefaultselection
///expressedasaCSIDLvalue,anarbitraryrootfolder,BFF
///flags,&aparentwindow
CYABFFW(intnDefaultSel,constCString&strHint,constCString&strRoot,
UINTnFlags=0U,CWnd*pParentWnd=NULL);
/**////ConstructwithahintfromResource,anarbitraryroot
///folder,BFFflags,aparentwidnow,andatextualdefault
///selection
CYABFFW(intnHint,constCString&strRoot,UINTnFlags=0U,
CWnd*pParentWnd=NULL,
constCString&strDefaultSel=CString());
/**////ConstructwithahintfromResource,adefaultselection
///expressedasaCSIDLvalue,anarbitraryrootfolder,BFF
///flags,&aparentwidnow
CYABFFW(intnDefaultSel,intnHint,constCString&strRoot,
UINTnFlags=0U,CWnd*pParentWnd=NULL);
//Attributes
public:
/**////Retrievethedisplaynameoftheselecteditem
CStringGetDisplayName()const;
/**////RetrievetheITEMIDLISToftheselecteditem
LPCITEMIDLISTGetItemIdList()const;
/**////Retrievethepathtotheselecteditem
CStringGetPath()const;
//Operations
public:
/**////DisplaytheDialog-returnsIDOKorIDCANCEL
intDoModal();
//Overrides
public:
/**////CalledwhentheBFFDialoghasinitialized
virtualvoidOnInitBFFDialog();
/**////Calledwhentheselectionhaschangedinthetreecontrol
virtualvoidOnBFFSelChanged(LPITEMIDLISTpNewSel);
/**////Calledwhentheusertypesaninvalidname
virtualBOOLOnBFFValidateFailed(constCString&strBadName);
//ClassWizardgeneratedvirtualfunctionoverrides
//{{AFX_VIRTUAL(CYABFFW)
//}}AFX_VIRTUAL
//Implementation
public:
virtual~CYABFFW();
//Generatedmessagemapfunctions
protected:
//{{AFX_MSG(CYABFFW)NOTE-theClassWizardwilladdandremove
//memberfunctionshere.
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
private:
/**////StaticmethodtobeusedfortheSHBFFcallback
staticintCALLBACKBrowseCallbackProc(HWNDhWnd,UINTnMsg,
LPARAMlParam,
LPARAMlpData);
private:
/**////Freethememoryreferencedbym_pItemIdList
voidFreeItemIdList(IMalloc*pMalloc=NULL);
/**////CSIDL=>ITEMIDLIST
LPITEMIDLISTResolveCsidl(intnCsidl)const;
/**////Textualfilesystempath=>ITEMIDLIST
LPITEMIDLISTResolveFsPath(constCString&strPath)const;
private:
/**////Displaynameoftheselecteditem
CStringm_strDisplayName;
/**////Flagstobepassedtothebrowsedialog
UINTm_nFlags;
/**////"Hint"tobedisplayedabovethetreecontrol
CStringm_strHint;
/**////ITEMIDLISTidentifyingtheselectedShellitem
LPITEMIDLISTm_pItemIdList;
/**////ParentCWnd(NULL=>Appmainwindow)
CWnd*m_pParentWnd;
/**////Selectedpath
CStringm_strPath;
/**////ITEMIDLISTidentifyingtheroot
LPITEMIDLISTm_pRoot;
/**////Defaultselection,ifgivenastext(emptyifnone)
CStringm_strDefaultSel;
/**////Defaultselection,ifgivenasaCSIDLvalue(NULLifnone)
LPITEMIDLISTm_pDefaultSel;
};
<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->

CYABFFW::CYABFFW(constCString&strHint/**//*=CString()*/,
UINTnFlags/**//*=0U*/,
CWnd*pParentWnd/**//*=NULL*/,
intnRootFolder/**//*=CSIDL_DESKTOP*/,
constCString&strDefault/**//*=CString()*/):
m_nFlags(nFlags),
m_strHint(strHint),
m_pItemIdList(NULL),
m_pParentWnd(pParentWnd),
m_pRoot(NULL),
m_strDefaultSel(strDefault),
m_pDefaultSel(NULL)

{
ASSERT_NULL_OR_VALID(pParentWnd);//Paranoia
m_pRoot=ResolveCsidl(nRootFolder);
}

CYABFFW::CYABFFW(intnDefaultSel,
constCString&strHint/**//*=CString()*/,
UINTnFlags/**//*=0U*/,
CWnd*pParentWnd/**//*=NULL*/,
intnRootFolder/**//*=CSIDL_DESKTOP*/):
m_nFlags(nFlags),
m_strHint(strHint),
m_pItemIdList(NULL),
m_pParentWnd(pParentWnd),
m_pRoot(NULL),
m_pDefaultSel(NULL)

{
ASSERT_NULL_OR_VALID(pParentWnd);//Paranoia
m_pRoot=ResolveCsidl(nRootFolder);
m_pDefaultSel=ResolveCsidl(nDefaultSel);
}

CYABFFW::CYABFFW(intnHint,
UINTnFlags/**//*=0U*/,
CWnd*pParentWnd/**//*=NULL*/,
intnRootFolder/**//*=CSIDL_DESKTOP*/,
constCString&strDefaultSel/**//*=CString()*/):
m_nFlags(nFlags),
m_pItemIdList(NULL),
m_pParentWnd(pParentWnd),
m_pRoot(NULL),
m_strDefaultSel(strDefaultSel),
m_pDefaultSel(NULL)

{
ASSERT_NULL_OR_VALID(pParentWnd);//Paranoia
if(!m_strHint.LoadString(nHint))
AfxThrowResourceException();
m_pRoot=ResolveCsidl(nRootFolder);
}
CYABFFW::CYABFFW(intnDefaultSel,
intnHint,
UINTnFlags/**//*=0U*/,
CWnd*pParentWnd/**//*=NULL*/,
intnRootFolder/**//*=CSIDL_DESKTOP*/):
m_nFlags(nFlags),
m_pItemIdList(NULL),
m_pParentWnd(pParentWnd),
m_pRoot(NULL),
m_pDefaultSel(NULL)

{
ASSERT_NULL_OR_VALID(pParentWnd);//Paranoia
if(!m_strHint.LoadString(nHint))
AfxThrowResourceException();
m_pRoot=ResolveCsidl(nRootFolder);
m_pDefaultSel=ResolveCsidl(nDefaultSel);
}

CYABFFW::CYABFFW(constCString&strHint,
constCString&strRoot,
UINTnFlags/**//*=0U*/,
CWnd*pParentWnd/**//*=NULL*/,
constCString&strDefaultSel/**//*=CString()*/):
m_nFlags(nFlags),
m_strHint(strHint),
m_pItemIdList(NULL),
m_pParentWnd(pParentWnd),
m_pRoot(NULL),
m_strDefaultSel(strDefaultSel),
m_pDefaultSel(NULL)

{
ASSERT_NULL_OR_VALID(pParentWnd);//Paranoia
m_pRoot=ResolveFsPath(strRoot);
}

CYABFFW::CYABFFW(intnDefaultSel,
constCString&strHint,
constCString&strRoot,
UINTnFlags/**//*=0U*/,
CWnd*pParentWnd/**//*=NULL*/):
m_nFlags(nFlags),
m_strHint(strHint),
m_pItemIdList(NULL),
m_pParentWnd(pParentWnd),
m_pRoot(NULL),
m_pDefaultSel(NULL)

{
ASSERT_NULL_OR_VALID(pParentWnd);//Paranoia
m_pRoot=ResolveFsPath(strRoot);
m_pDefaultSel=ResolveCsidl(nDefaultSel);
}

CYABFFW::CYABFFW(intnHint,
constCString&strRoot,
UINTnFlags/**//*=0U*/,
CWnd*pParentWnd/**//*=NULL*/,
constCString&strDefaultSel/**//*=CString()*/):
m_nFlags(nFlags),
m_pItemIdList(NULL),
m_pParentWnd(pParentWnd),
m_pRoot(NULL),
m_strDefaultSel(strDefaultSel),
m_pDefaultSel(NULL)

{
ASSERT_NULL_OR_VALID(pParentWnd);//Paranoia
if(!m_strHint.LoadString(nHint))
AfxThrowResourceException();
m_pRoot=ResolveFsPath(strRoot);
}

CYABFFW::CYABFFW(intnDefaultSel,
intnHint,
constCString&strRoot,
UINTnFlags/**//*=0U*/,
CWnd*pParentWnd/**//*=NULL*/):
m_nFlags(nFlags),
m_pItemIdList(NULL),
m_pParentWnd(pParentWnd),
m_pRoot(NULL)

{
ASSERT_NULL_OR_VALID(pParentWnd);//Paranoia
if(!m_strHint.LoadString(nHint))
AfxThrowResourceException();
m_pRoot=ResolveFsPath(strRoot);
m_pDefaultSel=ResolveCsidl(nDefaultSel);
}
#ifdef_DEBUG
CStringCYABFFW::GetDisplayName()const

{
returnm_strDisplayName;
}

LPCITEMIDLISTCYABFFW::GetItemIdList()const

{
returnm_pItemIdList;
}
CStringCYABFFW::GetPath()const

{
returnm_strPath;
}
#endif//_DEBUG
intCYABFFW::DoModal()

{
//We'llneedthiseventually
HRESULThr;
IMalloc*pMalloc;
if(FAILED(hr=::SHGetMalloc(&pMalloc)))
AfxThrowOleException(hr);
//Fillouta'BROWSEINFO'structuretohandto'SHBrowseFor-
//Folder':
BROWSEINFObrowseInfo;
::ZeroMemory(&browseInfo,sizeof(BROWSEINFO));
browseInfo.hwndOwner=(NULL==m_pParentWnd?NULL:
m_pParentWnd->m_hWnd);
browseInfo.pidlRoot=m_pRoot;
//UseaCStringformemorymanagement
browseInfo.pszDisplayName=
m_strDisplayName.GetBufferSetLength(MAX_PATH);
browseInfo.lpszTitle=m_strHint;
browseInfo.ulFlags=m_nFlags;
browseInfo.lpfn=BrowseCallbackProc;
browseInfo.lParam=(long)this;
if(NULL!=m_pItemIdList)
FreeItemIdList();//Probablyneverhappen,but

if(NULL==(m_pItemIdList=::SHBrowseForFolder(&browseInfo)))

{
//UserCancelledout-cleanup&bail.
m_strDisplayName.ReleaseBuffer();
pMalloc->Release();
returnIDCANCEL;
}
//Right-ifwe'rehere,theuseractuallyselectedanitem.
//Trytogetafullpath.Thiswillfailiftheselecteditem
//isnotpartoftheFileSystem.
::SHGetPathFromIDList(m_pItemIdList,
m_strPath.GetBufferSetLength(MAX_PATH));
//Cleanuptime
m_strPath.ReleaseBuffer();
m_strDisplayName.ReleaseBuffer();
pMalloc->Release();
//Note:m_pItemIdListhas*not*beenfreed!Wekeeparoundin
//casethecallerwantstoretrieveitlater.Itwill
//ultimatelybefree-dinthedestructor.
returnIDOK;
}
voidCYABFFW::OnInitBFFDialog()

{
if(!m_strDefaultSel.IsEmpty())

{
TRACE(_T("Settingthedefaultselectionto%s./n"),
(LPCTSTR)m_strDefaultSel);
SendMessage(BFFM_SETSELECTION,TRUE,(LPARAM)(LPCTSTR)m_strDefaultSel);
}
elseif(m_pDefaultSel)

{
SendMessage(BFFM_SETSELECTION,FALSE,(LPARAM)m_pDefaultSel);
}
}

voidCYABFFW::OnBFFSelChanged(LPITEMIDLIST/**//*pNewSel*/)

{/**//*Nohandlingbydefault*/}


BOOLCYABFFW::OnBFFValidateFailed(constCString&/**//*strBadName*/)

{returnTRUE;/**//*Nohandlingbydefault*/}
CYABFFW::~CYABFFW()

{
HRESULThr;
IMalloc*pMalloc;
if(FAILED(hr=::SHGetMalloc(&pMalloc)))
AfxThrowOleException(hr);
pMalloc->Free(m_pRoot);
FreeItemIdList(pMalloc);
}

BEGIN_MESSAGE_MAP(CYABFFW,CWnd)
//{{AFX_MSG_MAP(CYABFFW)
//NOTE-theClassWizardwilladdandremovemappingmacroshere.
//}}AFX_MSG_MAP
END_MESSAGE_MAP()

intCYABFFW::BrowseCallbackProc(HWNDhWnd,
UINTnMsg,
LPARAMlParam,
LPARAMlpData)

{
CYABFFW*pWnd=reinterpret_cast<CYABFFW*>(lpData);
ASSERT_VALID(pWnd);
ASSERT(NULL==pWnd->m_hWnd||hWnd==pWnd->m_hWnd);
if(NULL==pWnd->m_hWnd&&!pWnd->SubclassWindow(hWnd))
AfxThrowOleException(HRESULT_FROM_WIN32(::GetLastError()));
switch(nMsg)

{
caseBFFM_INITIALIZED:
//Indicatesthebrowsedialogboxhasfinished
//initializing.ThelParamvalueiszero.
pWnd->OnInitBFFDialog();
return0;
caseBFFM_SELCHANGED:
//Indicatestheselectionhaschanged.ThelParamparameter
//pointstotheitemidentifierlistforthenewlyselected
//item.

{
LPITEMIDLISTp=reinterpret_cast<LPITEMIDLIST>(lParam);
ASSERT_POINTER(p,ITEMIDLIST);
pWnd->OnBFFSelChanged(p);
return0;
}
caseBFFM_VALIDATEFAILED:
//Indicatestheusertypedaninvalidnameintotheeditbox
//ofthebrowsedialogbox.ThelParamparameteristhe
//addressofacharacterbufferthatcontainstheinvalid
//name.Anapplicationcanusethismessagetoinformthe
//userthatthenameenteredwasnotvalid.Returnzeroto
//allowthedialogtobedismissedornonzerotokeepthe
//dialogdisplayed.

{
LPTSTRp=reinterpret_cast<LPTSTR>(lParam);
ASSERT(!::IsBadStringPtr(p,UINT_MAX));
BOOLbDismissOk=pWnd->OnBFFValidateFailed(CString(p));
returnbDismissOk?0:1;
}
default:
TRACE(_T("WARNING:Unknownmessage0x%08x(0x%08x)")
_T("passedtoCYABFFW::BrowseCallbackProc!/n"),
nMsg,lParam);
return0;
}//EndswitchonnMsg.
}

voidCYABFFW::FreeItemIdList(IMalloc*pMalloc/**//*=NULL*/)

{
if(NULL==m_pItemIdList)
return;
boolbWeRelease=false;
if(NULL==pMalloc)

{
bWeRelease=true;
HRESULThr;
IMalloc*pMalloc;
if(FAILED(hr=::SHGetMalloc(&pMalloc)))
AfxThrowOleException(hr);
}
pMalloc->Free(m_pItemIdList);
if(bWeRelease)
pMalloc->Release();
m_pItemIdList=NULL;
}
LPITEMIDLISTCYABFFW::ResolveCsidl(intnCsidl)const

{
//Short-circuitspecialcase
if(CSIDL_DESKTOP==nCsidl)
returnNULL;
LPITEMIDLISTpidlRoot;
HRESULThr=::SHGetFolderLocation(NULL,nCsidl,NULL,0U,
&pidlRoot);
if(FAILED(hr))

{
ASSERT(NULL==pidlRoot);
AfxThrowOleException(hr);
}
returnpidlRoot;//Callerassumesresponsibility
}
LPITEMIDLISTCYABFFW::ResolveFsPath(constCString&strPath)const

{
USES_CONVERSION;
#ifdef_DEBUG
DWORDdwFileAttrs=::GetFileAttributes(strPath);
ASSERT(0xffffffff!=dwFileAttrs&&
FILE_ATTRIBUTE_DIRECTORY&dwFileAttrs);
#endif//_DEBUG
HRESULThr;
IShellFolder*pDesktop;
if(FAILED(hr=::SHGetDesktopFolder(&pDesktop)))
AfxThrowOleException(hr);
//Unfortunately,T2OLEexpectsanon-conststring,so
LPOLESTRp2=T2OLE(const_cast<LPTSTR>(
static_cast<LPCTSTR>(strPath)));
LPITEMIDLISTpItemIdList;
if(FAILED(hr=pDesktop->ParseDisplayName(NULL,NULL,
p2,
NULL,
&pItemIdList,
NULL)))

{
pDesktop->Release();
AfxThrowOleException(hr);
}
pDesktop->Release();
returnpItemIdList;//Callerassumesresponsibility
}
本文介绍了一个用MFC风格封装的ShellAPI函数SHBrowseForFolder()的类CYABFFW,该类提供了一个方便使用的文件夹选择对话框。通过不同的构造函数可以设置提示文本、默认选择项等参数。
6130

被折叠的 条评论
为什么被折叠?



