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

        通常情况下,我们用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等系统中验证通过。






你可能感兴趣的:(如何实现打开文件所在文件夹的功能(打开所在文件夹并选中文件))