您的位置:首页 > 其它

如何实现打开文件所在文件夹的功能(打开所在文件夹并选中文件)

2014-02-13 21:08 716 查看
通常情况下,我们用ShellExecute就可以实现“打开指定文件所在的目录并选中该文件”的功能,代码如下所示:

CString str = _T("/select, E:\\TestDir\\test.txt");
ShellExecute( NULL, _T("open"), _T("explorer.exe"), str, NULL, SW_SHOWNORMAL );
如上所示,使用“/select,“参数(注意:“/select”参数后面的逗号不能丢)。但用ShellExecute实现的功能是有问题的:当所在的文件夹已经打开,且选中的是其他的文件,如果此时执行ShellExecute,会将文件夹窗口置顶显示,但是不能选中目标文件。于是,查看QQ的做法,QQ是每一次都打开一个新的窗口,这样可以通过“/n, /select,“参数可以实现。但这样的处理不是最合理的,最合理的做法:如果文件夹已经打开,就不用再重新打开一次,直接置顶显示,并选中目标文件。

通过查阅相关资料,得知可以通过调用系统库shell32.dll中的非公开API函数SHOpenFolderAndSelectItems来实现上述功能,代码如下所示:

// 打开文件夹并选中对应的文件
BOOL32 OpenFolderAndSelectFile( CString strFilePath )
{
LPITEMIDLIST pidl;
LPCITEMIDLIST cpidl;
LPSHELLFOLDER pDesktopFolder;
ULONG chEaten;
HRESULT hr;
WCHAR wfilePath[MAX_PATH+1] = { 0 };

::CoInitialize( NULL );

if ( SUCCEEDED( SHGetDesktopFolder( &pDesktopFolder ) ) )
{
// IShellFolder::ParseDisplayName要传入宽字节
LPWSTR lpWStr = NULL;
#ifdef _UNICODE
_tcscpy( wfilePath, strFilePath );
lpWStr = wfilePath;
#else
MultiByteToWideChar( CP_ACP, 0, (LPCSTR)strFilePath, -1, wfilePath, MAX_PATH );
lpWStr = wfilePath;
#endif

hr = pDesktopFolder->ParseDisplayName( NULL, 0, lpWStr, &chEaten, &pidl, NULL );
if ( FAILED( hr ) )
{
pDesktopFolder->Release();
::CoUninitialize();
return FALSE;
}

cpidl = pidl;

// SHOpenFolderAndSelectItems是非公开的API函数,需要从shell32.dll获取
// 该函数只有XP及以上的系统才支持,Win2000和98是不支持的,考虑到Win2000
// 和98已经基本不用了,所以就不考虑了,如果后面要支持上述老的系统,则要
// 添加额外的处理代码
HMODULE hShell32DLL = ::LoadLibrary( _T("shell32.dll") );
ASSERT( hShell32DLL != NULL );
if( hShell32DLL != NULL )
{
typedef HRESULT (WINAPI *pSelFun)( LPCITEMIDLIST pidlFolder, UINT cidl, LPCITEMIDLIST  *apidl, DWORD dwFlags );
pSelFun pFun = (pSelFun)::GetProcAddress( hShell32DLL, "SHOpenFolderAndSelectItems" );
ASSERT( pFun != NULL );
if( pFun != NULL )
{
hr = pFun( cpidl, 0, NULL, 0 ); // 第二个参数cidl置为0,表示是选中文件
if ( FAILED( hr ) )
{
::FreeLibrary( hShell32DLL );
pDesktopFolder->Release();
::CoUninitialize();
return FALSE;
}
}

::FreeLibrary( hShell32DLL );
}
else
{
pDesktopFolder->Release();
::CoUninitialize();
return FALSE;
}

// 释放pDesktopFolder
pDesktopFolder->Release();
}
else
{
::CoUninitialize();
return FALSE;
}

::CoUninitialize();
return TRUE;
}
上述代码已经在XP、Win7等系统中验证通过。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: