From 1bc82c8b81110a3b29e335e6ee88fd8b3b033566 Mon Sep 17 00:00:00 2001 From: ema Date: Mon, 5 May 2025 02:58:39 +0800 Subject: [PATCH] Native Support for Desktop Icons #1610 --- QuickLook.Native/QuickLook.Native32/DOpus.h | 8 +-- .../QuickLook.Native32/HelperMethods.cpp | 71 ++++++++++++++++--- QuickLook/Plugin/InfoPanel/InfoPanel.xaml.cs | 5 +- 3 files changed, 65 insertions(+), 19 deletions(-) diff --git a/QuickLook.Native/QuickLook.Native32/DOpus.h b/QuickLook.Native/QuickLook.Native32/DOpus.h index 75f0550..5c49399 100644 --- a/QuickLook.Native/QuickLook.Native32/DOpus.h +++ b/QuickLook.Native/QuickLook.Native32/DOpus.h @@ -19,9 +19,9 @@ class DOpus { public: - static void PrepareMessageWindow(); - static void GetSelected(PWCHAR buffer); + static void PrepareMessageWindow(); + static void GetSelected(PWCHAR buffer); private: - static void ParseXmlBuffer(PWCHAR buffer); - static LRESULT CALLBACK msgWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + static void ParseXmlBuffer(PWCHAR buffer); + static LRESULT CALLBACK msgWindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); }; diff --git a/QuickLook.Native/QuickLook.Native32/HelperMethods.cpp b/QuickLook.Native/QuickLook.Native32/HelperMethods.cpp index de2c796..a1cc028 100644 --- a/QuickLook.Native/QuickLook.Native32/HelperMethods.cpp +++ b/QuickLook.Native/QuickLook.Native32/HelperMethods.cpp @@ -16,6 +16,8 @@ // along with this program. If not, see . #include "stdafx.h" +#include "strsafe.h" + #include "HelperMethods.h" void HelperMethods::GetSelectedInternal(CComPtr psb, PWCHAR buffer) @@ -33,8 +35,11 @@ void HelperMethods::GetSelectedInternal(CComPtr psb, PWCHAR buffe void HelperMethods::ObtainFirstItem(CComPtr dao, PWCHAR buffer) { - FORMATETC formatetc; - STGMEDIUM medium = {sizeof medium}; + if (!dao || !buffer) + return; + + FORMATETC formatetc = {}; + STGMEDIUM medium = {}; formatetc.cfFormat = CF_HDROP; formatetc.ptd = nullptr; @@ -44,18 +49,62 @@ void HelperMethods::ObtainFirstItem(CComPtr dao, PWCHAR buffer) medium.tymed = TYMED_HGLOBAL; - if (FAILED(dao->GetData(&formatetc, &medium))) - return; + // Try CF_HDROP first + if (SUCCEEDED(dao->GetData(&formatetc, &medium))) + { + HDROP hDrop = HDROP(medium.hGlobal); + int count = DragQueryFile(hDrop, 0xFFFFFFFF, nullptr, 0); + if (count >= 1) + { + WCHAR localBuffer[MAX_PATH] = { '\0' }; + if (DragQueryFileW(hDrop, 0, localBuffer, MAX_PATH) > 0) + { + GetLongPathName(localBuffer, buffer, MAX_PATH_EX); + ReleaseStgMedium(&medium); + return; + } + ReleaseStgMedium(&medium); + } + } - int n = DragQueryFile(HDROP(medium.hGlobal), 0xFFFFFFFF, nullptr, 0); + // If CF_HDROP fails, try CFSTR_SHELLIDLIST + // Support Desktop Icon (This PC, Recycle Bin and so on) + // https://github.com/QL-Win/QuickLook/issues/1610 + static const CLIPFORMAT cfShellIDList = (CLIPFORMAT)RegisterClipboardFormatW(CFSTR_SHELLIDLIST); + formatetc.cfFormat = cfShellIDList; - if (n < 1) - return; + if (SUCCEEDED(dao->GetData(&formatetc, &medium))) + { + CIDA* pida = (CIDA*)GlobalLock(medium.hGlobal); + if (!pida) + { + ReleaseStgMedium(&medium); + return; + } - WCHAR localBuffer[MAX_PATH] = { '\0' }; - DragQueryFile(HDROP(medium.hGlobal), 0, localBuffer, MAX_PATH); - - GetLongPathName(localBuffer, buffer, MAX_PATH_EX); + ITEMIDLIST* pidlFolder = (ITEMIDLIST*)((BYTE*)pida + pida->aoffset[0]); + ITEMIDLIST* pidlItem = (ITEMIDLIST*)((BYTE*)pida + pida->aoffset[1]); + PIDLIST_ABSOLUTE pidlFull = ILCombine(pidlFolder, pidlItem); + GlobalUnlock(medium.hGlobal); + ReleaseStgMedium(&medium); + + if (!pidlFull) + return; + + // Convert to IShellItem to get canonical parsing path + CComPtr shellItem; + if (SUCCEEDED(SHCreateItemFromIDList(pidlFull, IID_PPV_ARGS(&shellItem)))) + { + PWSTR pszPath = nullptr; + if (SUCCEEDED(shellItem->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING, &pszPath))) + { + StringCchCopyW(buffer, MAX_PATH, pszPath); // returns e.g., ::{645FF040-5081-101B-9F08-00AA002F954E} + CoTaskMemFree(pszPath); + } + } + + ILFree(pidlFull); + } } bool HelperMethods::IsListaryToolbarVisible() diff --git a/QuickLook/Plugin/InfoPanel/InfoPanel.xaml.cs b/QuickLook/Plugin/InfoPanel/InfoPanel.xaml.cs index f5d3c79..1976061 100644 --- a/QuickLook/Plugin/InfoPanel/InfoPanel.xaml.cs +++ b/QuickLook/Plugin/InfoPanel/InfoPanel.xaml.cs @@ -83,10 +83,7 @@ public partial class InfoPanel : UserControl } else if (Path.GetPathRoot(path) == path) // is this a drive? { - long totalSpace; - long totalFreeSpace; - - FileHelper.GetDriveSpace(path, out totalSpace, out totalFreeSpace); + FileHelper.GetDriveSpace(path, out var totalSpace, out var totalFreeSpace); Dispatcher.Invoke(() => {