OSDN Git Service

ShellExtension: Fix the problem that the WinMerge menu does not appear when right...
authorTakashi Sawanaka <sdottaka@users.sourceforge.net>
Sat, 11 Feb 2023 03:06:09 +0000 (12:06 +0900)
committerTakashi Sawanaka <sdottaka@users.sourceforge.net>
Sat, 11 Feb 2023 03:06:09 +0000 (12:06 +0900)
ShellExtension/WinMergeContextMenu/dllmain.cpp

index 33915cb..f4a6914 100644 (file)
@@ -108,94 +108,38 @@ public:
 protected:
 
     // code from https://github.com/microsoft/terminal/blob/main/src/cascadia/ShellExtension/OpenTerminalHere.cpp
-    std::wstring _GetPathFromExplorer() const
-    {
-        std::wstring path;
-        HRESULT hr = NOERROR;
-
-        auto hwnd = ::GetForegroundWindow();
-        if (hwnd == nullptr)
-        {
-            return path;
-        }
-
-        TCHAR szName[MAX_PATH] = { 0 };
-        ::GetClassName(hwnd, szName, MAX_PATH);
-        if (0 == StrCmp(szName, L"WorkerW") ||
-            0 == StrCmp(szName, L"Progman"))
-        {
-            //special folder: desktop
-            hr = ::SHGetFolderPath(NULL, CSIDL_DESKTOP, NULL, SHGFP_TYPE_CURRENT, szName);
-            if (FAILED(hr))
-            {
-                return path;
-            }
-
-            path = szName;
-            return path;
-        }
-
-        if (0 != StrCmp(szName, L"CabinetWClass"))
-        {
-            return path;
-        }
-
-        ComPtr<IShellWindows> shell;
-        hr = CoCreateInstance(CLSID_ShellWindows, nullptr, CLSCTX_ALL, IID_IShellWindows, &shell);
-        if (FAILED(hr) || shell == nullptr)
-        {
-            return path;
-        }
-
-        ComPtr<IDispatch> disp;
-        wil::unique_variant variant;
-        variant.vt = VT_I4;
-
-        ComPtr<IWebBrowserApp> browser;
-        // look for correct explorer window
-        for (variant.intVal = 0;
-            shell->Item(variant, &disp) == S_OK;
-            variant.intVal++)
-        {
-            ComPtr<IWebBrowserApp> tmp;
-            if (FAILED(disp->QueryInterface<IWebBrowserApp>(&tmp)))
-            {
-                disp = nullptr; // get rid of DEBUG non-nullptr warning
-                continue;
-            }
-
-            HWND tmpHWND = NULL;
-            hr = tmp->get_HWND(reinterpret_cast<SHANDLE_PTR*>(&tmpHWND));
-            if (hwnd == tmpHWND)
-            {
-                browser = tmp;
-                disp = nullptr; // get rid of DEBUG non-nullptr warning
-                break; //found
-            }
-
-            disp = nullptr; // get rid of DEBUG non-nullptr warning
-        }
-
-        if (browser != nullptr)
-        {
-            wil::unique_bstr url;
-            hr = browser->get_LocationURL(&url);
-            if (FAILED(hr))
-            {
-                return path;
-            }
-
-            std::wstring sUrl(url.get(), SysStringLen(url.get()));
-            DWORD size = MAX_PATH;
-            hr = ::PathCreateFromUrl(sUrl.c_str(), szName, &size, NULL);
-            if (SUCCEEDED(hr))
-            {
-                path = szName;
-            }
-        }
-
-        return path;
-    }
+       HRESULT GetBestLocationFromSelectionOrSite(IShellItemArray* psiArray, IShellItem** location) const noexcept
+       {
+               ComPtr<IShellItem> psi;
+               if (psiArray)
+               {
+                       DWORD count{};
+                       RETURN_IF_FAILED(psiArray->GetCount(&count));
+                       if (count) // Sometimes we get an array with a count of 0. Fall back to the site chain.
+                       {
+                               RETURN_IF_FAILED(psiArray->GetItemAt(0, &psi));
+                       }
+               }
+
+               if (!psi)
+               {
+                       RETURN_IF_FAILED(GetLocationFromSite(&psi));
+               }
+
+               RETURN_HR_IF(S_FALSE, !psi);
+               RETURN_IF_FAILED(psi.CopyTo(location));
+               return S_OK;
+       }
+
+       HRESULT GetLocationFromSite(IShellItem** location) const noexcept
+       {
+               ComPtr<IServiceProvider> serviceProvider;
+               RETURN_IF_FAILED(m_site.As<IServiceProvider>(&serviceProvider));
+               ComPtr<IFolderView> folderView;
+               RETURN_IF_FAILED(serviceProvider->QueryService<IFolderView>(SID_SFolderView, &folderView));
+               RETURN_IF_FAILED(folderView->GetFolder(IID_PPV_ARGS(location)));
+               return S_OK;
+       }
 
     std::vector<std::wstring> GetPaths(_In_opt_ IShellItemArray* selection)
     {
@@ -203,9 +147,17 @@ protected:
         DWORD dwNumItems = 0;
         if (!selection)
         {
-            std::wstring path = _GetPathFromExplorer();
-            if (!path.empty())
-                paths.push_back(path);
+                       ComPtr<IShellItem> psi;
+                       if (SUCCEEDED(GetBestLocationFromSelectionOrSite(selection, &psi)))
+                       {
+                               wil::unique_cotaskmem_string pszFilePath;
+                               if (SUCCEEDED(psi->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath)))
+                               {
+                                       std::wstring path = pszFilePath.get();
+                                       if (!path.empty())
+                                               paths.push_back(path);
+                               }
+                       }
         }
         else
         {