windows资源管理器及ie监听

本文介绍了一种使用C++监听Internet Explorer和Explorer窗口导航事件的方法,通过实现DWebBrowserEvents接口,跟踪浏览器窗口的导航位置变化,并更新列表视图显示最新位置。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Okay, it’s been a while since we set aside our Little Program to learn a bit about connection points and using dispatch interfaces as connection point interfaces. Now we can put that knowledge to use.

Internet Explorer and Explorer windows fire a group of events known as DWeb­Browser­Events, so we just need to listen on those events to follow the window as it navigates around.

Take our scratch program and make these changes:

#define UNICODE
#define _UNICODE
#define STRICT
#define STRICT_TYPED_ITEMIDS
#include <windows.h>
#include <windowsx.h>
#include <ole2.h>
#include <commctrl.h>
#include <shlwapi.h>

#include <shlobj.h>
#include <atlbase.h>
#include <atlalloc.h>
#include <exdisp.h>
#include <exdispid.h>

...
// DispInterfaceBase incorporated by reference

void UpdateText(HWND hwnd, PCWSTR pszText);

class CWebBrowserEventsSink :
    public CDispInterfaceBase<DWebBrowserEvents>
    public: CWebBrowserEventsSink(HWND hwnd) : m_hwnd(hwnd) { }

 IFACEMETHODIMP SimpleInvoke(
    DISPID dispid, DISPPARAMS *pdispparams, VARIANT *pvarResult)
 {
  switch (dispid) {
  case DISPID_NAVIGATECOMPLETE:
   UpdateText(m_hwnd, pdispparams->rgvarg[0].bstrVal);
   break;

  case DISPID_QUIT:
   UpdateText(m_hwnd, L"<exited>");
   Disconnect();
   break;
  }
  return S_OK;
 };

private:
 HWND m_hwnd;
};

Our event sink class listens for DISPID_NAVIGATE­COMPLETE and DISPID_QUIT and updates the text with the new navigation location or the string L”” if the window exited. In the exit case, we also disconnect from the connection point to break the circular reference.

The IDL file for Navigate­Complete says

[id(DISPID_NAVIGATECOMPLETE), helpstring(“…”)]
void NavigateComplete([in] BSTR URL );
Therefore, we know that the URL parameter arrives as a VT_BSTR in position zero, so we can access it as pdispparams->rgvarg[0].bstrVal.

That class is basically the guts of the program. The rest is scaffolding. Like hooking up this guy to a listview item so it can report its findings somewhere.

struct ItemInfo
{
 ItemInfo(HWND hwnd, IDispatch *pdisp)
  : hwnd(hwnd) {
  spSink.Attach(new(std::nothrow) CWebBrowsrEventsSink(hwnd));
  if (spSink) spSink->Connect(pdisp);
 }
 ~ItemInfo() { if (spSink) spSink->Disconnect(); }

 HWND hwnd;
 CComPtr<CWebBrowserEventsSink> spSink;
};

ItemInfo *GetItemByIndex(int iItem)
{
 LVITEM item;
 item.mask = LVIF_PARAM;
 item.iItem = iItem;
 item.iSubItem = 0;
 item.lParam = 0;
 ListView_GetItem(g_hwndChild, &item);
 return reinterpret_cast<ItemInfo *>(item.lParam);
}

ItemInfo *GetItemByWindow(HWND hwnd, int *piItem)
{
 int iItem = ListView_GetItemCount(g_hwndChild);
 while (--iItem >= 0) {
  ItemInfo *pii = GetItemByIndex(iItem);
  if (pii->hwnd == hwnd) {
   if (piItem) *piItem = iItem;
   return pii;
  }
 }
 return nullptr;
}

void UpdateText(HWND hwnd, PCWSTR pszText)
{
 int iItem;
 if (GetItemByWindow(hwnd, &iItem)) {
  ListView_SetItemText(g_hwndChild, iItem, 0,
                       const_cast<PWSTR>(pszText));
 }
}

Attached to each listview item is an Item­Info structure which remembers the browser window it is associated with and the event sink that is listening for events.

// GetLocationFromView, GetLocationFromBrowser, and GetBrowserInfo
// incorporated by reference

CComPtr<IShellWindows> g_spWindows;

// rename DumpWindows to BuildWindowList
HRESULT BuildWindowList()
{
 CComPtr<IUnknown> spunkEnum;
 HRESULT hr = g_spWindows->_NewEnum(&spunkEnum);
 if (FAILED(hr)) return hr;

 CComQIPtr<IEnumVARIANT> spev(spunkEnum);
 for (CComVariant svar;
      spev->Next(1, &svar, nullptr) == S_OK;
      svar.Clear()) {
  if (svar.vt != VT_DISPATCH) continue;

  HWND hwnd;
  CComHeapPtr<WCHAR> spszLocation;
  if (FAILED(GetBrowserInfo(svar.pdispVal,
             &hwnd, &spszLocation))) continue;

  ItemInfo *pii =
            new(std::nothrow) ItemInfo(hwnd, svar.pdispVal);
  if (!pii) continue;

  LVITEM item;
  item.mask = LVIF_TEXT | LVIF_PARAM;
  item.iItem = MAXLONG;
  item.iSubItem = 0;
  item.pszText = spszLocation;
  item.lParam = reinterpret_cast<LPARAM>(pii);
  int iItem = ListView_InsertItem(g_hwndChild, &item);
  if (iItem < 0) delete pii;
 }
 return S_OK;
}

To build the window list, we enumerate the contents of the IShell­Windows. For each window, we get its window handle and current location and create a listview item for it. The reference data for the listview item is the Item­Info.

BOOL
OnCreate(HWND hwnd, LPCREATESTRUCT lpcs)
{
 g_hwndChild = CreateWindow(WC_LISTVIEW, 0,
    LVS_LIST | WS_CHILD | WS_VISIBLE |
    WS_HSCROLL | WS_VSCROLL, 0, 0, 0, 0,
    hwnd, (HMENU)1, g_hinst, 0);
 g_spWindows.CoCreateInstance(CLSID_ShellWindows);
 BuildWindowList();
 return TRUE;
}

Our creation function creates a child listview and fills it with stuff.

And of course we clean up our objects when the items are deleted and when the window is destroyed.

LRESULT OnNotify(HWND hwnd, int idFrom, NMHDR *pnm)
{
 switch (idFrom) {
 case 1:
  switch (pnm->code) {
  case LVN_DELETEITEM:
   {
    auto pnmlv = CONTAINING_RECORD(pnm, NMLISTVIEW, hdr);
    delete reinterpret_cast<ItemInfo *>(pnmlv->lParam);
   }
   break;
  }
 }
 return 0;
}

void OnDestroy(HWND hwnd)
{
 g_spWindows.Release();
 PostQuitMessage(0);
}

 HANDLE_MSG(hwnd, WM_NOTIFY, OnNotify);

And there we have it, a program that displays all the Internet Explorer and Explorer windows and updates their locations as you navigate.

Note, however, that our program doesn’t notice when new windows are created. We’ll hook that up next time.

原文:A big little program: Monitoring Internet Explorer and Explorer windows, part 2: Tracking navigations

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值