概述
代码思路来源于开源项目 QuickLook,并做了简化.
开始
在VS2017 下创建C++控制台项目,在预编译头文件添加适当的include
#ifndef PCH_H
#define PCH_H
// TODO: 添加要在此处预编译的标头
#include<atlcomcli.h>
#include<Exdisp.h>
#include<Shobjidl.h>
#include<shlguid.h>
#include<Shlobj.h>
#include<Shellapi.h>
#include<Psapi.h>
#include<AppModel.h>
#include<string>
#endif //PCH_H
// 以上为QuickLook所添加的头文件.
复制代码
创建函数定义
void GetSelectedInternernal(CComQIPtr<IWebBrowserApp> pwba);
void ObtainFirstItem(CComPtr<IDataObject> dao);
void getSelectedFromDesktop();
复制代码
main 函数
int main()
{
for (;;)
{
getSelectedFromDesktop();
Sleep(1000);
}
}
// 考虑到测试用途直接来个无限循环+Sleep
复制代码
getSelectedFromDesktop
void getSelectedFromDesktop() {
// 初始化
CoInitialize(nullptr);
CComPtr<IShellWindows> psw;
CComQIPtr<IWebBrowserApp> pwba;
// 获取 IShellWindows 实例
if (FAILED(psw.CoCreateInstance(CLSID_ShellWindows)))
return;
VARIANT pvarLoc;
VariantInit(&pvarLoc);
long phwnd;
// 获取 IWebBrowserApp 实例
if (FAILED(psw->FindWindowSW(&pvarLoc, &pvarLoc, SWC_DESKTOP, &phwnd, SWFO_NEEDDISPATCH, reinterpret_cast<IDispatch**>(
&pwba))))
return;
GetSelectedInternernal(pwba);
}
复制代码
GetSelectedInternernal
// 层层递进取得最终的IShellView,并取出选中项(SVGIO_SELECTION)
void GetSelectedInternernal(CComQIPtr<IWebBrowserApp> pwba) {
CComQIPtr<IServiceProvider> psp;
if (FAILED(pwba->QueryInterface(IID_IServiceProvider, reinterpret_cast<void**>(&psp)))) {
return;
}
CComPtr<IShellBrowser> psb;
if (FAILED(psp->QueryService(SID_STopLevelBrowser, IID_IShellBrowser, reinterpret_cast<LPVOID*>(&psb)))) {
return;
}
CComPtr<IShellView> psv;
if (FAILED(psb->QueryActiveShellView(&psv))) {
return;
}
CComPtr<IDataObject> dao;
if (FAILED(psv->GetItemObject(SVGIO_SELECTION, IID_IDataObject, reinterpret_cast<void**>(&dao)))) {
return;
}
ObtainFirstItem(dao);
}
复制代码
// 最终提取文件地址
void ObtainFirstItem(CComPtr<IDataObject> dao) {
FORMATETC formatetc;
STGMEDIUM medium = { sizeof 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;
WCHAR buffer[260] = { '