Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/143.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在Win32 API中查看新的资源管理器窗口_C++_C_Windows_Winapi - Fatal编程技术网

C++ 在Win32 API中查看新的资源管理器窗口

C++ 在Win32 API中查看新的资源管理器窗口,c++,c,windows,winapi,C++,C,Windows,Winapi,我目前正在制作一个程序,使用win32 API将选项卡添加到Windows文件资源管理器中,因为我对目前任何这样做的程序(Clover、Groupy等)都不满意。 要做到这一点,我显然需要获取当前打开的所有资源管理器窗口,并让程序监视正在创建的新窗口 我目前的做法是在我的消息循环中调用EnumWindows,并将任何尚未连接的资源管理器窗口附加到程序的主窗口 while(GetMessage(&uMsg, NULL, 0, 0) > 0) { TranslateMessag

我目前正在制作一个程序,使用win32 API将选项卡添加到Windows文件资源管理器中,因为我对目前任何这样做的程序(Clover、Groupy等)都不满意。 要做到这一点,我显然需要获取当前打开的所有资源管理器窗口,并让程序监视正在创建的新窗口

我目前的做法是在我的消息循环中调用
EnumWindows
,并将任何尚未连接的资源管理器窗口附加到程序的主窗口

while(GetMessage(&uMsg, NULL, 0, 0) > 0)
{
    TranslateMessage(&uMsg);
    DispatchMessage(&uMsg);
    EnumWindows((WNDENUMPROC)findExplorerWindows, (LPARAM)mainWindow);
}

这显然不是最优的(新窗口仅在消息发送到我的程序时才会连接到我的程序,总的来说,它会让一切都慢下来,特别是当已经有很多打开的窗口时)我想知道是否有一种方法可以监视打开的窗口列表,以便在创建新窗口或诸如此类的事件时触发事件。

下面是一些使用该界面的示例控制台代码(使用COM)。 首先它转储当前的资源管理器窗口(“视图”),然后它钩住伴随接口引发的事件

#包括
#包括
#包括
#包括
#包括
//处理DShellWindowsEvents的COM类
类Windows事件:公共IDispatch
{
//可怜人的COM对象…我们不在乎,我们基本上是一个静态的东西
STDMETHODIMP查询接口(refid-riid,void**ppvObject)
{
if(IsequalID(riid,IID_IUnknown))
{
*ppvObject=静态投影(此);
返回S_OK;
}
if(IsequalID(riid,IID_IDispatch))
{
*ppvObject=静态投影(此);
返回S_OK;
}
*ppvObject=NULL;
返回E_NOINTERFACE;
}
STDMETHODIMP_ULONG)AddRef(){return 1;}
STDMETHODIMP_ULONG)Release(){return 1;}
//这就是Shell所称的(顺便说一句,在同一UI线程上)
//只有两个事件“WindowRegistered”(打开)和“WindowReversed”(关闭)
STDMETHODIMP调用(DISPID DISPID成员、refid riid、LCID LCID、单词wFlags、DISPPARAMS*pDispParams、VARIANT*pVarResult、EXCEPINFO*pExcepInfo、UINT*puArgErr)
{
//第一个参数是窗口的注册cookie
int cookie=V_I4(&pDispParams->rgvarg[0]);
if(DISPID member==DISPID\u windowregisted)//需要exdispid.h
{
wprintf(L“窗口已注册,cookie:%u\n”,cookie);
}
else if(DISPID member==DISPID\u windowreversed)
{
wprintf(L“窗口已撤销,cookie:%u\n”,cookie);
}
//目前cookie并不是非常有用,它应该可以被FindWindowSW使用
c变量为空;
长hwnd;
CComPtr窗口;
HRESULT hr=Windows->FindWindowSW(&pDispParams->rgvarg[0],&empty,0,&hwnd,SWFO_COOKIEPASSED,&window);
//总是返回S_FALSE…它似乎不起作用
//所以,你必须再次要求所有的窗口。。。
返回S_OK;
}
//其余的都没有实现
STDMETHODIMP GetTypeInfoCount(UINT*pctinfo){返回E_NOTIMPL;}
STDMETHODIMP GetTypeInfo(UINT-iTInfo,LCID-LCID,ITypeInfo**ppTInfo){return E_NOTIMPL;}
STDMETHODIMP GetIDsOfNames(refid-riid,LPOLESTR*rgszNames,UINT-cNames,LCID-LCID,DISPID*rgDispId){return E_NOTIMPL;}
公众:
计算机窗口;
};
int main()
{
共初始化(空);
{
计算机窗口;
如果(成功(windows.CoCreateInstance(CLSID_ShellWindows)))
{
//转储当前窗口
长计数=0;
windows->get_Count(&Count);
用于(长i=0;iItem(CComVariant(i),&window)))
{
//去拿窗户把手
CComPtr应用程序;
如果(成功(窗口->查询接口(&app)))
{
HWND HWND=NULL;
app->get_-HWND((SHANDLE_PTR*)&HWND);
wprintf(L“HWND[%i]:%p\n”,i,HWND);
}
}
}
//现在等待windows打开
//获取事件的DShellWindowsEvents dispinterface
中央采购委员会;
如果(成功(windows.QueryInterface(&cpc)))
{
// https://docs.microsoft.com/en-us/windows/win32/shell/dshellwindowsevents
CComPtr cp;
如果(成功(cpc->FindConnectionPoint(DIID\u DShellWindowsEvents,&cp)))
{
窗口事件;
events.Windows=Windows;
DWORD cookie=0;
//钩事件
if(成功(cp->advice(&events,&cookie)))
{
//发送COM消息以确保事件到达
做
{
味精;
while(GetMessage(&msg,NULL,0,0))
{
翻译信息(&msg);
发送消息(&msg);
}
}虽然(正确);
//通常,如果有人向当前线程发送PostQuitMessage(0),我们应该到达这里
//但这是一个控制台示例。。。
//脱钩事件
cp->Unadvise(cookie);
}
}
}
}
}
coninitialize();
返回0;
}

下面是一些使用该接口的示例控制台代码(使用COM)。 首先它转储当前的资源管理器窗口(“视图”),然后它钩住伴随接口引发的事件

#包括
#包括
#包括
#包括
#包括
//处理DShellWindowsEvents的COM类
类Windows事件:公共IDispatch
{
//可怜人的COM对象…我们不在乎,我们基本上是一个静态的东西
STDMETHODIMP查询接口(refid-riid,void**ppvObject)
{
if(IsequalID(riid,IID_IUnknown))
{
*ppvObject=静态投影(此);
返回S_OK;
}
if(IsequalID(riid,IID_IDispatch))
{
*ppvObject=静态投影(此);
返回S_OK;
}
*ppvObject=NULL;
返回E_NOINTERFACE;
}
STDMETHODIMP_ULONG)AddRef(){return 1;}
STDMETHODIMP_ULONG)Release(){return 1;}
//这就是Shell所称的(顺便说一句,在同一UI线程上)
//只有两个事件“WindowRegistered”(打开)和“W”
#include <atlbase.h>
#include <atlcom.h>
#include <shobjidl_core.h>
#include <shlobj_core.h>
#include <exdispid.h>


// a COM class that handles DShellWindowsEvents
class WindowsEvents : public IDispatch
{
  // poor man's COM object... we don't care, we're basically a static thing here
  STDMETHODIMP QueryInterface(REFIID riid, void** ppvObject)
  {
    if (IsEqualIID(riid, IID_IUnknown))
    {
      *ppvObject = static_cast<IUnknown*>(this);
      return S_OK;
    }

    if (IsEqualIID(riid, IID_IDispatch))
    {
      *ppvObject = static_cast<IDispatch*>(this);
      return S_OK;
    }

    *ppvObject = NULL;
    return E_NOINTERFACE;
  }
  STDMETHODIMP_(ULONG) AddRef() { return 1; }
  STDMETHODIMP_(ULONG) Release() { return 1; }

  // this is what's called by the Shell (BTW, on the same UI thread)
  // there are only two events "WindowRegistered" (opened) and "WindowRevoked" (closed)
  STDMETHODIMP Invoke(DISPID dispIdMember, REFIID riid, LCID lcid, WORD wFlags, DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
  {
    // first parameter is window's registration cookie
    int cookie = V_I4(&pDispParams->rgvarg[0]);
    if (dispIdMember == DISPID_WINDOWREGISTERED) // needs exdispid.h
    {
      wprintf(L"Window registered, cookie:%u\n", cookie);
    }
    else if (dispIdMember == DISPID_WINDOWREVOKED)
    {
      wprintf(L"Window revoked, cookie:%u\n", cookie);
    }

    // currently the cookie is not super useful, it's supposed to be usable by FindWindowSW
    CComVariant empty;
    long hwnd;
    CComPtr<IDispatch> window;
    HRESULT hr = Windows->FindWindowSW(&pDispParams->rgvarg[0], &empty, 0, &hwnd, SWFO_COOKIEPASSED, &window);
    // always returns S_FALSE... it does not seem to work
    // so, you'll have to ask for all windows again...
    return S_OK;
  }

  // the rest is left not implemented
  STDMETHODIMP GetTypeInfoCount(UINT* pctinfo) { return E_NOTIMPL; }
  STDMETHODIMP GetTypeInfo(UINT iTInfo, LCID lcid, ITypeInfo** ppTInfo) { return E_NOTIMPL; }
  STDMETHODIMP GetIDsOfNames(REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgDispId) { return E_NOTIMPL; }

public:
  CComPtr<IShellWindows> Windows;
};

int main()
{
  CoInitialize(NULL);
  {
    CComPtr<IShellWindows> windows;
    if (SUCCEEDED(windows.CoCreateInstance(CLSID_ShellWindows)))
    {
      // dump current windows
      long count = 0;
      windows->get_Count(&count);
      for (long i = 0; i < count; i++)
      {
        CComPtr<IDispatch> window;
        if (SUCCEEDED(windows->Item(CComVariant(i), &window)))
        {
          // get the window handle
          CComPtr<IWebBrowserApp> app;
          if (SUCCEEDED(window->QueryInterface(&app)))
          {
            HWND hwnd = NULL;
            app->get_HWND((SHANDLE_PTR*)&hwnd);
            wprintf(L"HWND[%i]:%p\n", i, hwnd);
          }
        }
      }

      // now wait for windows to open
      // get the DShellWindowsEvents dispinterface for events
      CComPtr<IConnectionPointContainer> cpc;
      if (SUCCEEDED(windows.QueryInterface(&cpc)))
      {
        // https://docs.microsoft.com/en-us/windows/win32/shell/dshellwindowsevents
        CComPtr<IConnectionPoint> cp;
        if (SUCCEEDED(cpc->FindConnectionPoint(DIID_DShellWindowsEvents, &cp)))
        {
          WindowsEvents events;
          events.Windows = windows;
          DWORD cookie = 0;

          // hook events
          if (SUCCEEDED(cp->Advise(&events, &cookie)))
          {
            // pump COM messages to make sure events arrive
            do
            {
              MSG msg;
              while (GetMessage(&msg, NULL, 0, 0))
              {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
              }
            } while (TRUE);

            // normally we should get here if someone sends a PostQuitMessage(0) to the current thread
            // but this is a console sample...

            // unhook events
            cp->Unadvise(cookie);
          }
        }
      }
    }
  }
  CoUninitialize();
  return 0;
}