#include "stdafx.h" #include "Shell32.h" #include using namespace std; Shell32::FocusedWindowType Shell32::GetFocusedWindowType() { auto type = INVALID; auto hwndfg = GetForegroundWindow(); if (isCursorActivated(hwndfg)) return INVALID; auto classBuffer = new WCHAR[MAX_PATH]; if (SUCCEEDED(GetClassName(hwndfg, classBuffer, MAX_PATH))) { if (wcscmp(classBuffer, L"WorkerW") == 0 || wcscmp(classBuffer, L"Progman") == 0) { if (FindWindowEx(hwndfg, nullptr, L"SHELLDLL_DefView", nullptr) != nullptr) { type = DESKTOP; } } else if (wcscmp(classBuffer, L"ExploreWClass") == 0 || wcscmp(classBuffer, L"CabinetWClass") == 0) { type = EXPLORER; } } delete[] classBuffer; return type; } void Shell32::GetCurrentSelection(PWCHAR buffer) { switch (GetFocusedWindowType()) { case EXPLORER: getSelectedFromExplorer(buffer); break; case DESKTOP: getSelectedFromDesktop(buffer); break; default: break; } } void Shell32::getSelectedFromExplorer(PWCHAR buffer) { CoInitialize(nullptr); CComPtr psw; if (FAILED(psw.CoCreateInstance(CLSID_ShellWindows))) return; auto hwndFGW = GetForegroundWindow(); auto count = 0L; psw->get_Count(&count); for (auto i = 0; i < count; i++) { VARIANT vi; V_VT(&vi) = VT_I4; V_I4(&vi) = i; CComPtr pdisp; // ReSharper disable once CppSomeObjectMembersMightNotBeInitialized if (FAILED(psw->Item(vi, &pdisp))) continue; CComQIPtr pwba; if (FAILED(pdisp->QueryInterface(IID_IWebBrowserApp, reinterpret_cast(&pwba)))) continue; HWND hwndWBA; if (FAILED(pwba->get_HWND(reinterpret_cast(&hwndWBA)))) continue; if (hwndWBA != hwndFGW || isCursorActivated(hwndWBA)) continue; getSelectedInternal(pwba, buffer); } } void Shell32::getSelectedFromDesktop(PWCHAR buffer) { CoInitialize(nullptr); CComPtr psw; CComQIPtr pwba; if (FAILED(psw.CoCreateInstance(CLSID_ShellWindows))) return; VARIANT pvarLoc = {VT_EMPTY}; long phwnd; if (FAILED(psw->FindWindowSW(&pvarLoc, &pvarLoc, SWC_DESKTOP, &phwnd, SWFO_NEEDDISPATCH, reinterpret_cast(&pwba)))) return; if (isCursorActivated(reinterpret_cast(phwnd))) return; getSelectedInternal(pwba, buffer); } void Shell32::getSelectedInternal(CComQIPtr pwba, PWCHAR buffer) { CComQIPtr psp; if (FAILED(pwba->QueryInterface(IID_IServiceProvider, reinterpret_cast(&psp)))) return; CComPtr psb; if (FAILED(psp->QueryService(SID_STopLevelBrowser, IID_IShellBrowser, reinterpret_cast(&psb)))) return; CComPtr psv; if (FAILED(psb->QueryActiveShellView(&psv))) return; CComPtr dao; if (FAILED(psv->GetItemObject(SVGIO_SELECTION, IID_IDataObject, reinterpret_cast(&dao)))) return; return obtainFirstItem(dao, buffer); } void Shell32::obtainFirstItem(CComPtr dao, PWCHAR buffer) { FORMATETC formatetc; STGMEDIUM medium; formatetc.cfFormat = CF_HDROP; formatetc.ptd = nullptr; formatetc.dwAspect = DVASPECT_CONTENT; formatetc.lindex = -1; formatetc.tymed = TYMED_HGLOBAL; medium.tymed = TYMED_HGLOBAL; if (FAILED(dao->GetData(&formatetc, &medium))) return; int n = DragQueryFile(HDROP(medium.hGlobal), 0xFFFFFFFF, nullptr, 0); if (n < 1) return; DragQueryFile(HDROP(medium.hGlobal), 0, buffer, MAX_PATH - 1); } bool Shell32::isCursorActivated(HWND hwnd) { auto tId = GetWindowThreadProcessId(hwnd, nullptr); GUITHREADINFO gui = {sizeof gui}; GetGUIThreadInfo(tId, &gui); return gui.flags || gui.hwndCaret; }