Обнаружение изменений в режиме просмотра папок - PullRequest
0 голосов
/ 29 мая 2020

Есть ли способ зафиксировать или поглотить изменение в режиме просмотра IFolderView (например, детали, значки и т. Д. c.)?

Я вижу DISPID_VIEWMODECHANGED, но Я не понимаю, к какой это раковине. Я не думаю, что он принадлежит DShellFolderViewEvents.

Кроме того, я не верю, что DWebBrowserEvents2 DISPID_DOCUMENTCOMPLETE срабатывает при изменении режима просмотра.

Спасибо за любой ввод.

1 Ответ

2 голосов
/ 30 мая 2020

Это действительно DISPID_VIEWMODECHANGED для DShellFolderViewEvents, но получить его довольно сложно.

Вот пример кода консольного приложения, которое отслеживает все изменения режима просмотра для всех открытых в данный момент представлений проводника. Итак, чтобы проверить это, вы должны:

  1. открыть некоторые представления Explorer;
  2. запустить программу. Когда вы меняете любой из режимов просмотра открытой папки, вы должны увидеть напечатанное событие.

Некоторые ссылки:

Получение уведомления каждый раз, когда выбор изменяется в Окно проводника

Диспетчерские интерфейсы как интерфейсы точек подключения

int main()
{
  CoInitialize(NULL);
  {
    CComPtr<IShellWindows> windows;
    windows.CoCreateInstance(CLSID_ShellWindows);

    long count = 0;
    windows->get_Count(&count);

    // array to remember one sink for one view
    CAtlArray<CComPtr<CShellFolderViewEventsSink>> sinks;
    for (int i = 0; i < count; i++)
    {
      // get window #i
      CComPtr<IDispatch> disp;
      windows->Item(CComVariant(i), &disp);
      if (disp)
      {
        // get top level browser
        CComPtr<IShellBrowser> browser;
        CComQIPtr<IServiceProvider>(disp)->QueryService(SID_STopLevelBrowser, IID_PPV_ARGS(&browser));
        if (browser)
        {
          // get shell view
          CComPtr<IShellView> view;
          browser->QueryActiveShellView(&view);
          if (view)
          {
            // get the ShellViewFolder (scripting) object
            CComPtr<IDispatch> viewDisp;
            view->GetItemObject(SVGIO_BACKGROUND, IID_PPV_ARGS(&viewDisp));
            if (viewDisp)
            {
              CComPtr<IShellFolderViewDual> fview;
              viewDisp->QueryInterface(&fview);
              if (fview)
              {
                CComPtr<CShellFolderViewEventsSink> sink;
                sink.Attach(new CShellFolderViewEventsSink());
                sinks.Add(sink);
                sink->Connect(fview);
              }
            }
          }
        }
      }
    }

    // wait for user input (and pump messages)
    MessageBox(nullptr, L"Click to stop listening", L"View Events", MB_OK);
    for (int i = 0; i < sinks.GetCount(); i++)
    {
      sinks.GetAt(i)->Disconnect();
    }
  }
  CoUninitialize();
  return 0;
}

// class that checks for DISPID_VIEWMODECHANGED
class CShellFolderViewEventsSink : public CDispInterfaceBase<DShellFolderViewEvents>
{
public:
  CShellFolderViewEventsSink() { }
  HRESULT Invoke( DISPID dispid, DISPPARAMS* pdispparams, VARIANT* pvarResult)
  {
    switch (dispid)
    {
    case DISPID_VIEWMODECHANGED:
      printf("DISPID_VIEWMODECHANGED called\n");
      break;
    }
    return S_OK;
  }
};

// support class to hook IDispatch events
template<typename DispInterface>
class CDispInterfaceBase : public DispInterface
{
  LONG m_cRef;
  CComPtr<IConnectionPoint> m_spcp;
  DWORD m_dwCookie;

public:
  CDispInterfaceBase() : m_cRef(1), m_dwCookie(0) { }

  // IDispatch
  IFACEMETHODIMP QueryInterface(REFIID riid, void** ppv)
  {
    *ppv = nullptr;
    HRESULT hr = E_NOINTERFACE;
    if (riid == IID_IUnknown || riid == IID_IDispatch || riid == __uuidof(DispInterface))
    {
      *ppv = static_cast<DispInterface*>(static_cast<IDispatch*>(this));
      AddRef();
      hr = S_OK;
    }
    return hr;
  }

  IFACEMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&m_cRef); }
  IFACEMETHODIMP_(ULONG) Release() { LONG cRef = InterlockedDecrement(&m_cRef); if (!cRef) delete this; return cRef; }

  // IDispatch
  IFACEMETHODIMP GetTypeInfoCount(UINT* pctinfo) { *pctinfo = 0; return E_NOTIMPL; }
  IFACEMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) { *ppTInfo = nullptr; return E_NOTIMPL; }
  IFACEMETHODIMP GetIDsOfNames(REFIID, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) { return E_NOTIMPL; }
  IFACEMETHODIMP Invoke(DISPID dispid, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pdispparams, VARIANT* pvarResult, EXCEPINFO* pexcepinfo, UINT* puArgErr)
  {
    if (pvarResult) VariantInit(pvarResult);
    return Invoke(dispid, pdispparams, pvarResult);
  }

  virtual HRESULT Invoke(DISPID dispid, DISPPARAMS* pdispparams, VARIANT* pvarResult) = 0;

public:
  HRESULT Connect(IUnknown* punk)
  {
    CComPtr<IConnectionPointContainer> spcpc;
    HRESULT  hr = punk->QueryInterface(IID_PPV_ARGS(&spcpc));
    if (SUCCEEDED(hr)) hr = spcpc->FindConnectionPoint(__uuidof(DispInterface), &m_spcp);
    if (SUCCEEDED(hr)) hr = m_spcp->Advise(this, &m_dwCookie);
    return hr;
  }

  void Disconnect()
  {
    if (m_dwCookie)
    {
      m_spcp->Unadvise(m_dwCookie);
      m_spcp.Release();
      m_dwCookie = 0;
    }
  }
};
...