zoukankan      html  css  js  c++  java
  • Win32 API 打开指定文件所在的目录并选中该文件

          通常情况下,我们用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来实现上述功能,代码如下所示:

    bool OpenFolderAndSelectFile( CString strFilePath )
    {
        LPSHELLFOLDER pDesktopFolder;
        ::CoInitialize( NULL );
    
        if ( FAILED( SHGetDesktopFolder( &pDesktopFolder ) ) )
        {
            ::CoUninitialize();
            return false;
        }
    
        LPITEMIDLIST pidl;
        ULONG chEaten;
        WCHAR wfilePath[MAX_PATH+1] = { 0 };
        // IShellFolder::ParseDisplayName要传入宽字节
    #ifdef _UNICODE
        _tcscpy( wfilePath, strFilePath );
    #else
        MultiByteToWideChar( CP_ACP, 0, (LPCSTR)strFilePath, -1, wfilePath, MAX_PATH ); 
    #endif
        LPWSTR lpWStr = wfilePath;
    
        HRESULT hr = pDesktopFolder->ParseDisplayName( NULL, 0, lpWStr, &chEaten, &pidl, NULL );
        if ( FAILED( hr ) )
        {
            pDesktopFolder->Release();
            ::CoUninitialize();
            return false;
        }
    
        LPCITEMIDLIST cpidl = pidl;
        bool bSucceedOrNot = false;
    // SHOpenFolderAndSelectItems是非公开的API函数,需要从shell32.dll获取
    // 该函数只有XP及以上的系统才支持,Win2000和98是不支持的,
    // 如果后面要支持上述老的系统,则要添加额外的处理代码 
        HMODULE hShell32DLL = ::LoadLibrary( _T("shell32.dll") );
        ASSERT( hShell32DLL != NULL );
    
        if( hShell32DLL )
        {
            typedef HRESULT (WINAPI *pSelFun)( LPCITEMIDLIST pidlFolder, UINT cidl, LPCITEMIDLIST *apidl, DWORD dwFlags );
            pSelFun pFun = (pSelFun)::GetProcAddress( hShell32DLL, "SHOpenFolderAndSelectItems" );
            ::FreeLibrary( hShell32DLL );
            ASSERT( pFun != NULL );   
            if( pFun != NULL )
            { // 第二个参数cidl置为0,表示是选中文件
                bSucceedOrNot = SUCCEEDED(pFun(cpidl, 0, NULL, 0));
            }
        }
    
        pDesktopFolder->Release();    // 释放pDesktopFolder
        ::CoUninitialize();
        return bSucceedOrNot;
    }
  • 相关阅读:
    eval命令的使用
    declare与typeset的使用
    【线型DP模板】最上上升子序列(LIS),最长公共子序列(LCS),最长公共上升子序列(LCIS)
    【线型DP】【LCS】UVA_10635 Prince and Princess
    【经典DP】洛谷 P2782 友好城市
    HDU-1051/POJ-1065 Wooden sticks 木棍子(动态规划 LIS 线型动归)
    BZOJ3659 Which Dreamed It
    CF300D Painting Square
    CF632E Thief in a Shop 和 CF958F3 Lightsabers (hard)
    CF528D Fuzzy Search 和 BZOJ4259 残缺的字符串
  • 原文地址:https://www.cnblogs.com/shankun/p/4088860.html
Copyright © 2011-2022 走看看