gpt4 book ai didi

c++ - 如何在 C++ winapi 中获取事件文件资源管理器窗口的路径

转载 作者:行者123 更新时间:2023-11-30 00:45:18 25 4
gpt4 key购买 nike

我一直在苦苦思索如何才能做到这一点。基本上,我的应用程序需要使用 winapi 在 c++ 中的 Windows 中找出事件文件资源管理器(即前台的文件资源管理器)的目录路径。

取而代之的是:

TCHAR* getWindowDir(){
TCHAR* windowTitle = new TCHAR[MAX_PATH];
HWND windowHandle = GetForegroundWindow();
GetWindowText(windowHandle,windowTitle,MAX_PATH);
return windowTitle;
}

这显然会返回窗口标题,我希望它返回事件目录。

最佳答案

创建 IShellWindows 的实例并使用它来枚举所有当前打开的资源管理器窗口。使用各种相关接口(interface),您可以以PIDL的形式获取窗口句柄和当前文件夹。来自 IShellWindows 枚举的每个项目。如果窗口句柄等于 GetForegroundWindow() 的结果,则将 PIDL 转换为路径。

在下文中,我提供了一些用于获取有关所有资源管理器窗口的信息的代码。它部分基于 code of Raymond Chen但使用智能指针来编写不那么脆弱和更干净的代码。我还通过异常添加了错误处理。

首先是所需的包含和一些实用程序代码:

#include <Windows.h>
#include <shlobj.h>
#include <atlcomcli.h> // for COM smart pointers
#include <atlbase.h> // for COM smart pointers
#include <vector>
#include <system_error>
#include <memory>
#include <iostream>

// Throw a std::system_error if the HRESULT indicates failure.
template< typename T >
void ThrowIfFailed( HRESULT hr, T&& msg )
{
if( FAILED( hr ) )
throw std::system_error{ hr, std::system_category(), std::forward<T>( msg ) };
}

// Deleter for a PIDL allocated by the shell.
struct CoTaskMemDeleter
{
void operator()( ITEMIDLIST* pidl ) const { ::CoTaskMemFree( pidl ); }
};
// A smart pointer for PIDLs.
using UniquePidlPtr = std::unique_ptr< ITEMIDLIST, CoTaskMemDeleter >;

现在我们定义一个函数 GetCurrentExplorerFolders() 来返回所有当前打开的资源管理器窗口的信息,包括窗口句柄和当前文件夹的 PIDL

// Return value of GetCurrentExplorerFolders()
struct ExplorerFolderInfo
{
HWND hwnd = nullptr; // window handle of explorer
UniquePidlPtr pidl; // PIDL that points to current folder
};

// Get information about all currently open explorer windows.
// Throws std::system_error exception to report errors.
std::vector< ExplorerFolderInfo > GetCurrentExplorerFolders()
{
CComPtr< IShellWindows > pshWindows;
ThrowIfFailed(
pshWindows.CoCreateInstance( CLSID_ShellWindows ),
"Could not create instance of IShellWindows" );

long count = 0;
ThrowIfFailed(
pshWindows->get_Count( &count ),
"Could not get number of shell windows" );

std::vector< ExplorerFolderInfo > result;
result.reserve( count );

for( long i = 0; i < count; ++i )
{
ExplorerFolderInfo info;

CComVariant vi{ i };
CComPtr< IDispatch > pDisp;
ThrowIfFailed(
pshWindows->Item( vi, &pDisp ),
"Could not get item from IShellWindows" );

if( ! pDisp )
// Skip - this shell window was registered with a NULL IDispatch
continue;

CComQIPtr< IWebBrowserApp > pApp{ pDisp };
if( ! pApp )
// This window doesn't implement IWebBrowserApp
continue;

// Get the window handle.
pApp->get_HWND( reinterpret_cast<SHANDLE_PTR*>( &info.hwnd ) );

CComQIPtr< IServiceProvider > psp{ pApp };
if( ! psp )
// This window doesn't implement IServiceProvider
continue;

CComPtr< IShellBrowser > pBrowser;
if( FAILED( psp->QueryService( SID_STopLevelBrowser, &pBrowser ) ) )
// This window doesn't provide IShellBrowser
continue;

CComPtr< IShellView > pShellView;
if( FAILED( pBrowser->QueryActiveShellView( &pShellView ) ) )
// For some reason there is no active shell view
continue;

CComQIPtr< IFolderView > pFolderView{ pShellView };
if( ! pFolderView )
// The shell view doesn't implement IFolderView
continue;

// Get the interface from which we can finally query the PIDL of
// the current folder.
CComPtr< IPersistFolder2 > pFolder;
if( FAILED( pFolderView->GetFolder( IID_IPersistFolder2, (void**) &pFolder ) ) )
continue;

LPITEMIDLIST pidl = nullptr;
if( SUCCEEDED( pFolder->GetCurFolder( &pidl ) ) )
{
// Take ownership of the PIDL via std::unique_ptr.
info.pidl = UniquePidlPtr{ pidl };
result.push_back( std::move( info ) );
}
}

return result;
}

示例显示如何调用 GetCurrentExplorerFolders(),将 PIDL 转换为路径并捕获异常。

int main()
{
::CoInitialize( nullptr );

try
{
std::wcout << L"Currently open explorer windows:\n";
for( const auto& info : GetCurrentExplorerFolders() )
{
CComHeapPtr<wchar_t> pPath;
if( SUCCEEDED( ::SHGetNameFromIDList( info.pidl.get(), SIGDN_FILESYSPATH, &pPath ) ) )
{
std::wcout << L"hwnd: 0x" << std::hex << info.hwnd
<< L", path: " << static_cast<LPWSTR>( pPath ) << L"\n";
}
}
}
catch( std::system_error& e )
{
std::cout << "ERROR: " << e.what() << "\nError code: " << e.code() << "\n";
}

::CoUninitialize();
}

可能的输出:

Currently open explorer windows:
hwnd: 0x0030058E, path: C:\Windows
hwnd: 0x000C06D4, path: C:\Program Files

关于c++ - 如何在 C++ winapi 中获取事件文件资源管理器窗口的路径,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43815932/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com