<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>The Old New Thing</title><link>http://blogs.msdn.com/b/oldnewthing/</link><description>not actually to establish a blogging point where individuals can enrich their learns on facilitating and leveraging .NET-related activities most effectively</description><dc:language>en-US</dc:language><generator>Telligent Evolution Platform Developer Build (Build: 5.6.50428.7875)</generator><item><title>Microspeak: to family well</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2013/06/18/10426545.aspx</link><pubDate>Tue, 18 Jun 2013 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10426545</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>15</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10426545</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2013/06/18/10426545.aspx#comments</comments><description>&lt;P&gt;
If you hang out with designers, you may hear the word
&lt;I&gt;family&lt;/I&gt; used as a verb, usually with the adverb &lt;I&gt;well&lt;/I&gt;.
&lt;/P&gt;
&lt;BLOCKQUOTE CLASS=q&gt;
The old icons now look dated and do not
family well with the Web site.
&lt;/BLOCKQUOTE&gt;
&lt;BLOCKQUOTE CLASS=q&gt;
We renamed the feature from &lt;I&gt;Auto Shape&lt;/I&gt; to &lt;I&gt;Instant Shape&lt;/I&gt;
so that it families well with other features like
&lt;I&gt;Instant Color&lt;/I&gt;.
&lt;/BLOCKQUOTE&gt;
&lt;BLOCKQUOTE CLASS=q&gt;
The authenticity certificate on the side of the box should
family well with the design on the front of the box.
&lt;/BLOCKQUOTE&gt;
&lt;P&gt;
From context, it appears that &lt;I&gt;to family well&lt;/I&gt; basically
means
&lt;I&gt;to be harmonious or consistent with&lt;/I&gt;.
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10426545" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Other/">Other</category><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Microspeak/">Microspeak</category></item><item><title>I wonder if the Queen of England ever pulls this sort of prank in real life</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2013/06/17/10426276.aspx</link><pubDate>Mon, 17 Jun 2013 14:00:01 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10426276</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>13</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10426276</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2013/06/17/10426276.aspx#comments</comments><description>&lt;P&gt;
I dreamed that I was playing doubles tennis.
My partner was Boris Becker.
Our opponents were the Queen of England and a policeman on a horse.
The horse served his horseshoe,
which I returned poorly.
As the horseshoe bounced across the ground,
it made huge divots.
The game was called due to poor ground conditions.
&lt;/P&gt;
&lt;P&gt;
The Queen played a game with the crowd by pretending to sit down
(allowing everybody to sit),
then faking them out and standing (making everybody stand up again).
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10426276" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Non_2D00_Computer/">Non-Computer</category><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Dream/">Dream</category></item><item><title>Displaying a property sheet for multiple files</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2013/06/17/10426275.aspx</link><pubDate>Mon, 17 Jun 2013 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10426275</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>8</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10426275</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2013/06/17/10426275.aspx#comments</comments><description>&lt;P&gt;
Today's Little Program will show a property sheet that covers multiple
files,
just like the one you get from Explorer if you multi-select a bunch
of files and right-click them all then select &lt;I&gt;Properties&lt;/I&gt;.
&lt;/P&gt;
&lt;P&gt;
In fact, that description of how you do the operation interactively
maps directly to how you do the operation programmatically!
&lt;/P&gt;
&lt;PRE&gt;
#define UNICODE
#define &lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2004/02/12/71851.aspx"&gt;_UNICODE&lt;/A&gt;
#define &lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2013/01/24/10387757.aspx"&gt;STRICT_TYPED_ITEMIDS&lt;/A&gt;
#include &amp;lt;windows.h&amp;gt;
#include &amp;lt;ole2.h&amp;gt;
#include &amp;lt;shlobj.h&amp;gt;
#include &amp;lt;atlbase.h&amp;gt;
#include &amp;lt;atlalloc.h&amp;gt;

HRESULT GetUIObjectOf(
    IShellFolder *psf,
    HWND hwndOwner,
    UINT cidl,
    PCUITEMID_CHILD_ARRAY apidl, REFIID riid, void **ppv)
{
 return psf-&gt;GetUIObjectOf(hwndOwner, cidl, apidl, riid, nullptr, ppv);
}
&lt;/PRE&gt;
&lt;P&gt;
The &lt;CODE&gt;Get&amp;shy;UI&amp;shy;Object&amp;shy;Of&lt;/CODE&gt; helper function
merely wraps the
&lt;CODE&gt;IShell&amp;shy;Folder::&lt;WBR&gt;Get&amp;shy;UI&amp;shy;Object&amp;shy;Of&lt;/CODE&gt;
method to insert the pesky &lt;CODE&gt;nullptr&lt;/CODE&gt; parameter
between the &lt;CODE&gt;riid&lt;/CODE&gt; and &lt;CODE&gt;ppv&lt;/CODE&gt;.
The &lt;CODE&gt;riid&lt;/CODE&gt; and &lt;CODE&gt;ppv&lt;/CODE&gt; parameters
by convention go right next to each other,
and the &lt;CODE&gt;IID_&lt;WBR&gt;PPV_&lt;WBR&gt;ARGS&lt;/CODE&gt; macro assumes
that the function you're calling follows that convention.
Unfortunately, the people who designed
&lt;CODE&gt;IShell&amp;shy;Folder::&lt;WBR&gt;Get&amp;shy;UI&amp;shy;Object&amp;shy;Of&lt;/CODE&gt;
didn't get the memo, and we've been stuck with it ever since.
&lt;/P&gt;
&lt;PRE&gt;
HRESULT InvokeCommandByVerb(
    IContextMenu *pcm,
    HWND hwnd,
    LPCSTR pszVerb)
{
 HMENU hmenu = CreatePopupMenu();
 HRESULT hr = hmenu ? S_OK : E_OUTOFMEMORY;
 if (SUCCEEDED(hr)) {
  hr = pcm-&amp;gt;QueryContextMenu(hmenu, 0, 1, 0x7FFF, CMF_NORMAL);
  if (SUCCEEDED(hr)) {
   CMINVOKECOMMANDINFO info = { 0 };
   info.cbSize = sizeof(info);
   info.hwnd = hwnd;
   info.lpVerb = pszVerb;
   hr = pcm-&amp;gt;InvokeCommand(&amp;amp;info);
  }
  DestroyMenu(hmenu);
 }
 return hr;
}
&lt;/PRE&gt;
&lt;P&gt;
The &lt;CODE&gt;Invoke&amp;shy;Command&amp;shy;By&amp;shy;Verb&lt;/CODE&gt; function
merely
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2004/09/20/231739.aspx"&gt;
hosts an &lt;CODE&gt;IContext&amp;shy;Menu&lt;/CODE&gt; and invokes a single verb&lt;/A&gt;.
&lt;/P&gt;
&lt;P&gt;
Okay, those are the only two helper functions we need this week.
The rest we can steal from earlier articles.
&lt;/P&gt;
&lt;P&gt;
For the purpose of illustration,
the program will display a multi-file property sheet for the first
two files in your
My Documents folder folder.
Remember, Little Programs do little to no error checking.
&lt;/P&gt;
&lt;PRE&gt;
int __cdecl wmain(int, wchar_t **)
{
 &lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2004/05/20/135841.aspx"&gt;CCoInitialize&lt;/A&gt; init;
 &lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2008/05/28/8555658.aspx"&gt;ProcessReference&lt;/A&gt; ref;
 CComPtr&amp;lt;IShellFolder&amp;gt; spsf;
 &lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2011/08/30/10202076.aspx"&gt;BindToCsidl&lt;/A&gt;(CSIDL_MYDOCUMENTS, IID_PPV_ARGS(&amp;amp;spsf));
 CComPtr&amp;lt;IEnumIDList&amp;gt; speidl;
 spsf-&amp;gt;EnumObjects(nullptr, SHCONTF_NONFOLDERS, &amp;amp;speidl);
 if (!speidl) return 0;
 CComHeapPtr&amp;lt;ITEMID_CHILD&amp;gt; spidl1;
 CComHeapPtr&amp;lt;ITEMID_CHILD&amp;gt; spidl2;
 if (speidl-&amp;gt;Next(1, &amp;amp;spidl1, nullptr) != S_OK) return 0;
 if (speidl-&amp;gt;Next(1, &amp;amp;spidl2, nullptr) != S_OK) return 0;
 PCUITEMID_CHILD rgpidl[2] = { spidl1, spidl2 };
 CComPtr&amp;lt;IContextMenu&amp;gt; spcm;
 GetUIObjectOf(spsf, nullptr, 2, rgpidl, IID_PPV_ARGS(&amp;amp;spcm));
 if (!spcm) return 0;
 InvokeCommandByVerb(spcm, "properties");
 return 0;
}
&lt;/PRE&gt;
&lt;P&gt;
Because everybody freaks out if I write code that doesn't
run on Windows&amp;nbsp;XP,
I used the
&lt;CODE&gt;Bind&amp;shy;To&amp;shy;CSIDL&lt;/CODE&gt; function
instead of one of its more modern equivalents
to get access to the My Documents folder.
&lt;/P&gt;
&lt;P&gt;
Once we have My Documents,
we ask to enumerate its non-folders.
If the enumeration fails or says that there are no items (by returning
&lt;CODE&gt;S_FALSE&lt;/CODE&gt;), then we bail immediately.
&lt;/P&gt;
&lt;P&gt;
Next, we enumerate two items from the folder.
If we can't get both, then we bail.
&lt;/P&gt;
&lt;P&gt;
We then create a two-item array and
get the &lt;CODE&gt;IContext&amp;shy;Menu&lt;/CODE&gt; UI object
for the collection.
&lt;/P&gt;
&lt;P&gt;
Finally, we invoke the &lt;CODE&gt;"properties"&lt;/CODE&gt; verb on the context menu.
&lt;/P&gt;
&lt;P&gt;
And that's it.
If you run this program, you'll see a context menu for the first
two files in your My Documents folder.
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10426275" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Code/">Code</category></item><item><title>A big little program: Monitoring Internet Explorer and Explorer windows, part 3: Tracking creation and destruction</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2013/06/14/10425806.aspx</link><pubDate>Fri, 14 Jun 2013 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10425806</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>9</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10425806</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2013/06/14/10425806.aspx#comments</comments><description>&lt;P&gt;
Last time, we
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2013/06/13/10425505.aspx"&gt;
listener for window navigations&lt;/A&gt;.
Today we'll learn about tracking window creation and destruction.
&lt;/P&gt;
&lt;P&gt;
The events to listen to are the
&lt;A HREF="http://msdn.microsoft.com/library/cc836565"&gt;
&lt;CODE&gt;DShell&amp;shy;Windows&amp;shy;Events&lt;/CODE&gt;&lt;/A&gt;.
The
&lt;CODE&gt;Window&amp;shy;Registered&lt;/CODE&gt; event fires
when a new window is created, and the
&lt;CODE&gt;Window&amp;shy;Revoked&lt;/CODE&gt; event fires
when a window is destroyed.
&lt;/P&gt;
&lt;P&gt;
The bad news is that the parameter to those events is a cookie,
which is not useful for much,
so we just use the events to tell us that it's time to
kick off a new enumeration to see what changed.
This will also catch the case where something fell out of sync
because a window closed without unregistering (say,
because the application crashed).
&lt;/P&gt;
&lt;P&gt;
Take our program from last time and make these changes:
&lt;/P&gt;
&lt;PRE&gt;
&lt;FONT COLOR=blue&gt;LONG g_lCounter;&lt;/FONT&gt;

struct ItemInfo
{
 ItemInfo(HWND hwnd, IDispatch *pdisp)
  : hwnd(hwnd), &lt;FONT COLOR=blue&gt;lCounter(g_lCounter)&lt;/FONT&gt; { ... }
 ...

 HWND hwnd;
 CComPtr&amp;lt;CWebBrowserEventsSink&amp;gt; spSink;
 &lt;FONT COLOR=blue&gt;LONG lCounter;&lt;/FONT&gt;
};
&lt;/PRE&gt;
&lt;P&gt;
The counter is used to detect stale windows when we re-enumerate.
&lt;/P&gt;
&lt;PRE&gt;
HRESULT BuildWindowList()
{
 CComPtr&amp;lt;IUnknown&amp;gt; spunkEnum;
 HRESULT hr = g_spWindows-&amp;gt;_NewEnum(&amp;amp;spunkEnum);
 if (FAILED(hr)) return hr;

 &lt;FONT COLOR=blue&gt;++g_lCounter;&lt;/FONT&gt;

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

  HWND hwnd;
  CComHeapPtr&amp;lt;WCHAR&amp;gt; spszLocation;
  if (FAILED(GetBrowserInfo(svar.pdispVal,
             &amp;amp;hwnd, &amp;amp;spszLocation))) continue;

  ItemInfo *pii = &lt;FONT COLOR=blue&gt;GetItemByWindow(hwnd, nullptr);
  if (pii) { pii-&amp;gt;lCounter = g_lCounter; continue; }
  pii =&lt;/FONT&gt; 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&amp;lt;LPARAM&amp;gt;(pii);
  int iItem = ListView_InsertItem(g_hwndChild, &amp;amp;item);
  if (iItem &amp;lt; 0) delete pii;
 }

 &lt;FONT COLOR=blue&gt;int iItem = ListView_GetItemCount(g_hwndChild);
 while (--iItem &amp;gt;= 0) {
  ItemInfo *pii = GetItemByIndex(iItem);
  if (pii-&amp;gt;lCounter != g_lCounter) {
   ListView_DeleteItem(g_hwndChild, iItem);
  }
 }&lt;/FONT&gt;

 return S_OK;
}&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;
Building the window list is now a two-step process,
since what we are really doing is &lt;I&gt;updating&lt;/I&gt;
the window list.
First, we enumerate
the contents of the &lt;CODE&gt;IShell&amp;shy;Windows&lt;/CODE&gt;.
For each window, we get its window handle and see if there
is already an item for that window.
If so, then we update the counter for that item.
If there is not already an item for that window,
then we create one like we did before.
&lt;/P&gt;
&lt;P&gt;
After we've processed all the windows that exist,
we go look for the deletion by walking through all
our items and deleting any whose counter was not updated
by the previous loop.
&lt;/P&gt;
&lt;P&gt;
Okay, but so far we haven't actually done anything new.
Here's the new stuff:
&lt;/P&gt;
&lt;PRE&gt;
&lt;FONT COLOR=blue&gt;class CShellWindowsEventsSink :
    public CDispInterfaceBase&amp;lt;DShellWindowsEvents&amp;gt;
{
public:
 HRESULT SimpleInvoke(
    DISPID dispid, DISPPARAMS *pdispparams, VARIANT *pvarResult)
 {
  switch (dispid) {
  case DISPID_WINDOWREGISTERED:
  case DISPID_WINDOWREVOKED:
   BuildWindowList();
   break;
  }
  return S_OK;
 }
};

CComPtr&amp;lt;CShellWindowsEventsSink&amp;gt; g_spShellSink;&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;
This is the object that listens for changes to the window list.
And whether the change is that a window arrived or a window
departed, the response is the same: Refresh the window list.
&lt;/P&gt;
&lt;P&gt;
All that's left to do is hook up this event sink (and clean it up):
&lt;/P&gt;
&lt;PRE&gt;
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();

 &lt;FONT COLOR=blue&gt;g_spShellSink.Attach(new CShellWindowsEventsSink());
 g_spShellSink-&amp;gt;Connect(g_spWindows);&lt;/FONT&gt;

 return TRUE;
}

void OnDestroy(HWND hwnd)
{
 g_spWindows.Release();
 &lt;FONT COLOR=blue&gt;if (g_spShellSink) {
  g_spShellSink-&amp;gt;Disconnect();
  g_spShellSink.Release();
 }&lt;/FONT&gt;
 PostQuitMessage(0);
}
&lt;/PRE&gt;
&lt;P&gt;
We now have a program that
displays all the
Internet Explorer and Explorer windows, updates
their locations as you navigate,
and adds and removes them as new windows are created
or existing ones are closed.
&lt;/P&gt;
&lt;P&gt;
&lt;B&gt;Reminder&lt;/B&gt;: This is a Little Program,
which means that there is little to no error checking,
and the design may be somewhat suboptimal.
(For example, I use global variables everywhere
because I'm lazy.)
But it should give you enough of a head start so you can
write a more robust version.
&lt;/P&gt;
&lt;P&gt;
&lt;B&gt;Exercise&lt;/B&gt;:
There is still a subtle bug in &lt;CODE&gt;Build&amp;shy;Window&amp;shy;List&lt;/CODE&gt;.
Identify it and discuss how you would address it.
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10425806" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Code/">Code</category></item><item><title>A big little program: Monitoring Internet Explorer and Explorer windows, part 2: Tracking navigations</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2013/06/13/10425505.aspx</link><pubDate>Thu, 13 Jun 2013 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10425505</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>8</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10425505</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2013/06/13/10425505.aspx#comments</comments><description>&lt;P&gt;
Okay, it's been a while since we
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2013/06/10/10424662.aspx"&gt;
set aside our Little Program&lt;/A&gt;
to learn a bit about
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2013/06/11/10424940.aspx"&gt;
connection points&lt;/A&gt;
and
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2013/06/12/10425215.aspx"&gt;
using dispatch interfaces as connection point interfaces&lt;/A&gt;.
Now we can put that knowledge to use.
&lt;/P&gt;
&lt;P&gt;
Internet Explorer and Explorer windows fire a group of events known as
&lt;A HREF="http://msdn.microsoft.com/library/aa768309"&gt;
&lt;CODE&gt;DWeb&amp;shy;Browser&amp;shy;Events&lt;/CODE&gt;&lt;/A&gt;,
so we just need to listen on those events to follow
the window as it navigates around.
&lt;/P&gt;
&lt;P&gt;
Take our 
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2003/07/23/54576.aspx"&gt;
scratch program&lt;/A&gt;
and make these changes:
&lt;/P&gt;
&lt;PRE&gt;
&lt;FONT COLOR=blue&gt;#define &lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2004/07/15/184076.aspx"&gt;UNICODE&lt;/A&gt;
#define &lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2004/02/12/71851.aspx"&gt;_UNICODE&lt;/A&gt;&lt;/FONT&gt;
#define STRICT
&lt;FONT COLOR=blue&gt;#define &lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2013/01/24/10387757.aspx"&gt;STRICT_TYPED_ITEMIDS&lt;/A&gt;&lt;/FONT&gt;
#include &amp;lt;windows.h&amp;gt;
#include &amp;lt;windowsx.h&amp;gt;
#include &amp;lt;ole2.h&amp;gt;
#include &amp;lt;commctrl.h&amp;gt;
#include &amp;lt;shlwapi.h&amp;gt;

&lt;FONT COLOR=blue&gt;#include &amp;lt;shlobj.h&amp;gt;
#include &amp;lt;atlbase.h&amp;gt;
#include &amp;lt;atlalloc.h&amp;gt;
#include &amp;lt;exdisp.h&amp;gt;
#include &amp;lt;exdispid.h&amp;gt;&lt;/FONT&gt;

...
// &lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2013/06/11/10424940.aspx"&gt;DispInterfaceBase&lt;/A&gt; incorporated by reference

&lt;FONT COLOR=blue&gt;void UpdateText(HWND hwnd, PCWSTR pszText);

class CWebBrowserEventsSink :
    public CDispInterfaceBase&amp;lt;DWebBrowserEvents&amp;gt;

public:
 CWebBrowserEventsSink(HWND hwnd) : m_hwnd(hwnd) { }

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

  case DISPID_QUIT:
   UpdateText(m_hwnd, L"&amp;lt;exited&amp;gt;");
   Disconnect();
   break;
  }
  return S_OK;
 };

private:
 HWND m_hwnd;
};&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;
Our event sink class listens for
&lt;CODE&gt;DISPID_&lt;WBR&gt;NAVIGATE&amp;shy;COMPLETE&lt;/CODE&gt;
and
&lt;CODE&gt;DISPID_&lt;WBR&gt;QUIT&lt;/CODE&gt;
and updates the text with the new navigation location
or the string &lt;CODE&gt;L"&amp;lt;exited&amp;gt;"&lt;/CODE&gt; if the
window exited.
In the exit case, we also disconnect from the connection
point to break the circular reference.
&lt;/P&gt;
&lt;P&gt;
The IDL file for &lt;CODE&gt;Navigate&amp;shy;Complete&lt;/CODE&gt; says
&lt;/P&gt;
&lt;PRE&gt;
[id(DISPID_NAVIGATECOMPLETE), helpstring("...")]
void NavigateComplete([in] BSTR URL );
&lt;/PRE&gt;
&lt;P&gt;
Therefore, we know that the URL parameter arrives as
a &lt;CODE&gt;VT_&lt;WBR&gt;BSTR&lt;/CODE&gt; in position zero,
so we can access it as
&lt;CODE&gt;pdispparams-&amp;gt;&lt;WBR&gt;rgvarg[0].&lt;WBR&gt;bstrVal&lt;/CODE&gt;.
&lt;/P&gt;
&lt;P&gt;
That class is basically the guts of the program.
&lt;A HREf="http://blogs.msdn.com/b/oldnewthing/archive/2003/11/12/55659.aspx"&gt;
The rest is scaffolding&lt;/A&gt;.
Like hooking up this guy to a listview item
so it can report its findings somewhere.
&lt;/P&gt;
&lt;PRE&gt;
struct ItemInfo
{
 ItemInfo(HWND hwnd, IDispatch *pdisp)
  : hwnd(hwnd) {
  spSink.Attach(new(std::nothrow) CWebBrowsrEventsSink(hwnd));
  if (spSink) spSink-&gt;Connect(pdisp);
 }
 ~ItemInfo() { if (spSink) spSink-&gt;Disconnect(); }

 HWND hwnd;
 CComPtr&amp;lt;CWebBrowserEventsSink&amp;gt; spSink;
};

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

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

void UpdateText(HWND hwnd, PCWSTR pszText)
{
 int iItem;
 if (GetItemByWindow(hwnd, &amp;iItem)) {
  ListView_SetItemText(g_hwndChild, iItem, 0,
                       const_cast&amp;lt;PWSTR&amp;gt;(pszText));
 }
}
&lt;/PRE&gt;
&lt;P&gt;
Attached to each listview item is an
&lt;CODE&gt;Item&amp;shy;Info&lt;/CODE&gt; structure
which remembers the browser window it is associated with
and the event sink that is listening for events.
&lt;/P&gt;
&lt;PRE&gt;
// GetLocationFromView, GetLocationFromBrowser, and GetBrowserInfo
// &lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2013/06/10/10424662.aspx"&gt;incorporated by reference&lt;/A&gt;

CComPtr&amp;lt;IShellWindows&amp;gt; g_spWindows;

// rename DumpWindows to BuildWindowList
HRESULT &lt;FONT COLOR=blue&gt;BuildWindowList&lt;/FONT&gt;()
{
 CComPtr&amp;lt;IUnknown&amp;gt; spunkEnum;
 HRESULT hr = g_spWindows-&amp;gt;_NewEnum(&amp;amp;spunkEnum);
 if (FAILED(hr)) return hr;

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

  HWND hwnd;
  CComHeapPtr&amp;lt;WCHAR&amp;gt; spszLocation;
  if (FAILED(GetBrowserInfo(svar.pdispVal,
             &amp;amp;hwnd, &amp;amp;spszLocation))) continue;

  &lt;FONT COLOR=blue&gt;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&amp;lt;LPARAM&amp;gt;(pii);
  int iItem = ListView_InsertItem(g_hwndChild, &amp;amp;item);
  if (iItem &amp;lt; 0) delete pii;
 }
 return S_OK;
}&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;
To build the window list, we enumerate
the contents of the &lt;CODE&gt;IShell&amp;shy;Windows&lt;/CODE&gt;.
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
&lt;CODE&gt;Item&amp;shy;Info&lt;/CODE&gt;.
&lt;/P&gt;
&lt;PRE&gt;
BOOL
OnCreate(HWND hwnd, LPCREATESTRUCT lpcs)
{
 &lt;FONT COLOR=blue&gt;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();&lt;/FONT&gt;
 return TRUE;
}
&lt;/PRE&gt;
&lt;P&gt;
Our creation function creates a child listview
and fills it with stuff.
&lt;/P&gt;
&lt;P&gt;
And of course we clean up our objects when the items
are deleted and when the window is destroyed.
&lt;/P&gt;
&lt;PRE&gt;
&lt;FONT COLOR=blue&gt;LRESULT OnNotify(HWND hwnd, int idFrom, NMHDR *pnm)
{
 switch (idFrom) {
 case 1:
  switch (pnm-&amp;gt;code) {
  case LVN_DELETEITEM:
   {
    auto pnmlv = CONTAINING_RECORD(pnm, NMLISTVIEW, hdr);
    delete reinterpret_cast&amp;lt;ItemInfo *&amp;gt;(pnmlv-&amp;gt;lParam);
   }
   break;
  }
 }
 return 0;
}&lt;/FONT&gt;

void OnDestroy(HWND hwnd)
{
 &lt;FONT COLOR=blue&gt;g_spWindows.Release();&lt;/FONT&gt;
 PostQuitMessage(0);
}

 &lt;FONT COLOR=blue&gt;HANDLE_MSG(hwnd, WM_NOTIFY, OnNotify);&lt;/FONT&gt;
&lt;/PRE&gt;
&lt;P&gt;
And there we have it, a program that displays all the
Internet Explorer and Explorer windows and updates
their locations as you navigate.
&lt;/P&gt;
&lt;P&gt;
Note, however, that our program doesn't notice when
new windows are created.
We'll hook that up next time.
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10425505" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Code/">Code</category></item><item><title>Dispatch interfaces as connection point interfaces</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2013/06/12/10425215.aspx</link><pubDate>Wed, 12 Jun 2013 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10425215</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>18</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10425215</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2013/06/12/10425215.aspx#comments</comments><description>&lt;P&gt;
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2013/06/11/10424940.aspx"&gt;
Last time&lt;/A&gt;,
we learned about how connection points work.
One special case of this is where the connection interface
is a dispatch interface.
&lt;/P&gt;
&lt;P&gt;
Dispatch interfaces are, as the name suggests,
COM interfaces based on &lt;CODE&gt;IDispatch&lt;/CODE&gt;.
The &lt;CODE&gt;IDispatch&lt;/CODE&gt; interface is the base interface
for OLE automation objects,
and if you want your connection point interface to be usable
from script,
you probably should make it a dispatch interface.
&lt;/P&gt;
&lt;P&gt;
I'm assuming you know how &lt;CODE&gt;IDispatch&lt;/CODE&gt; works.
The short version is that script that wants to invoke
a method or property calls
&lt;CODE&gt;Get&amp;shy;IDs&amp;shy;Of&amp;shy;Names&lt;/CODE&gt; to get the
&lt;I&gt;dispatch ID&lt;/I&gt; for the method or property it wants
to access,
and it uses the type library to figure out
things like the parameters and return value.
Once the scripting engine figures out how the method or property
expects to be called,
it can call
&lt;CODE&gt;IDispatch::&lt;WBR&gt;Invoke&lt;/CODE&gt;
passing the dispatch ID and a &lt;CODE&gt;DISPPARAMS&lt;/CODE&gt; structure
that holds the parameters.
&lt;/P&gt;
&lt;P&gt;
Nowadays, this sort of thing goes by the fancy name of &lt;I&gt;reflection&lt;/I&gt;,
but back in the OLE Automation days,
it was simply all in a day's work.
&lt;I&gt;You kids think you invented everything&lt;/I&gt;.
&lt;/P&gt;
&lt;P&gt;
Just like as with regular connection point interfaces,
a dispatch interface used as a connection point interface
consists of events which are formally implemented as methods.
&lt;/P&gt;
&lt;PRE&gt;
dispinterface DWidgetEvents
{
 [id(WDISPID_RENAMED)]
 HRESULT Renamed([in] BSTR oldName, [in] BSTR newName);
...
};
&lt;/PRE&gt;
&lt;P&gt;
You declare that your object is a source of events for this interface
by noting it in your object declaration.
(Thanks, Medinoc for
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2013/06/12/10425215.aspx#10425408"&gt;
noting the error in the original version of this article&lt;/A&gt;.)
&lt;/P&gt;
&lt;PRE&gt;
coclass Widget
{
 [default] interface IWidget;
 &lt;FONT COLOR=blue&gt;[default, source] dispinterface DWidgetEvents;&lt;/FONT&gt;
}
&lt;/PRE&gt;
&lt;P&gt;
A client registers with the connection point with the
&lt;CODE&gt;DIID_&lt;WBR&gt;DWidget&amp;shy;Events&lt;/CODE&gt; interface.
By convention, dispatch interfaces usually end
with the word &lt;CODE&gt;Events&lt;/CODE&gt;
and are often prefixed with the letter &lt;CODE&gt;D&lt;/CODE&gt;,
and the interface ID symbol begins with &lt;CODE&gt;DIID&lt;/CODE&gt;
rather than simply &lt;CODE&gt;IID&lt;/CODE&gt;.
These conventions are not universally adhered-to,
so don't freak out if you see people who don't follow them.
(If you declare your dispatch interface in an IDL file,
then the MIDL compiler will
generate the dispatch interface ID with
the &lt;CODE&gt;DIID&lt;/CODE&gt; prefix for you.)
&lt;/P&gt;
&lt;P&gt;
Now, formally, when the connection point wants to invoke
the &lt;CODE&gt;Renamed&lt;/CODE&gt; method, it calls
&lt;CODE&gt;Get&amp;shy;IDs&amp;shy;Of&amp;shy;Names&lt;/CODE&gt; to get the ID
for the method called &lt;CODE&gt;L"Renamed"&lt;/CODE&gt;, and asks
for the type library to figure out what the parameters are.
But this is frequently just pointless busy-work:
The connection point often already knows the answer,
since the connection point already knows what interface
it is talking to.
It doesn't need to do any "reflection" since the connection
point already knows what the IDs and calling conventions are.
In the same way, your C# code doesn't need to use reflection
to call a method on an object whose assembly you already have
referenced in your project.
(The &lt;CODE&gt;Get&amp;shy;IDs&amp;shy;Of&amp;shy;Names&lt;/CODE&gt; exists not for
connection points, but rather to assist
dynamically-typed languages, where you can try to invoke any method
on any object, and the method is looked up at run time.)
&lt;/P&gt;
&lt;P&gt;
In other words, the connection point already knows that
the ID for the method &lt;CODE&gt;Rename&lt;/CODE&gt; is
&lt;CODE&gt;WDISPID_&lt;WBR&gt;RENAMED&lt;/CODE&gt;, and that it takes two
&lt;CODE&gt;BSTR&lt;/CODE&gt; parameters,
because that was part of the contract for registering with
the connection point in the first place.
&lt;/P&gt;
&lt;P&gt;
This means that in practice, the only method on the
client that is ever called is
&lt;CODE&gt;IDispatch::&lt;WBR&gt;Invoke&lt;/CODE&gt;.
&lt;/P&gt;
&lt;P&gt;
Here is a template base class that I use for my connection point interface
implementations of dispatch interfaces.
We'll discuss the pieces afterwards:
&lt;/P&gt;
&lt;PRE&gt;
template&amp;lt;typename DispInterface&amp;gt;
class CDispInterfaceBase : public DispInterface
{
public:
 CDispInterfaceBase() : m_cRef(1), m_dwCookie(0) { }

 /* IUnknown */
 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&amp;lt;DispInterface *&amp;gt;
          (static_cast&amp;lt;IDispatch*&amp;gt;(this));
   AddRef();
   hr = S_OK;
  }
  return hr;
 }

 IFACEMETHODIMP_(ULONG) AddRef()
 {
  return InterlockedIncrement(&amp;amp;m_cRef);
 }

 IFACEMETHODIMP_(ULONG) Release()
 {
  LONG cRef = InterlockedDecrement(&amp;amp;m_cRef);
  if (cRef == 0) 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 SimpleInvoke(dispid, pdispparams, pvarResult);
 }

 // Derived class must implement SimpleInvoke
 virtual HRESULT SimpleInvoke(DISPID dispid,
    DISPPARAMS *pdispparams, VARIANT *pvarResult) = 0;

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

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

private:
 LONG m_cRef;
 CComPtr&amp;lt;IConnectionPoint&amp;gt; m_spcp;
 DWORD m_dwCookie;
};
&lt;/PRE&gt;
&lt;P&gt;
First, a distraction: Our &lt;CODE&gt;Query&amp;shy;Interface&lt;/CODE&gt;
implementation performs a double-cast of &lt;CODE&gt;this&lt;/CODE&gt;
to &lt;CODE&gt;IDispatch&lt;/CODE&gt;, then to the templated interface.
This ensures that the templated interface pointer
and &lt;CODE&gt;IDispatch&lt;/CODE&gt; are compatible.
It would be bad if somebody tried to use this
&lt;CODE&gt;Query&amp;shy;Interface&lt;/CODE&gt; implementation
with something unrelated to &lt;CODE&gt;IDispatch&lt;/CODE&gt;.
(Yes, I could've used &lt;CODE&gt;std::is_base_of&lt;/CODE&gt;,
but I'm an old-timer who grew up before TR1.)
&lt;/P&gt;
&lt;P&gt;
The bulk of the class merely stubs out all the methods
of &lt;CODE&gt;IDispatch&lt;/CODE&gt;,
save for
&lt;CODE&gt;IDispatch::&lt;WBR&gt;Invoke&lt;/CODE&gt;, which does a little
grunt work (initializing the result &lt;CODE&gt;VARIANT&lt;/CODE&gt;)
and then leaves the derived class to do the heavy lifting.
&lt;/P&gt;
&lt;P&gt;
Finally, there are two public methods
&lt;CODE&gt;Connect&lt;/CODE&gt; and &lt;CODE&gt;Disconnect&lt;/CODE&gt;.
These perform the &lt;CODE&gt;Advise&lt;/CODE&gt; and
&lt;CODE&gt;Unadvise&lt;/CODE&gt; calls we saw yesterday.
To simplify things for our caller,
we save the &lt;CODE&gt;IConnection&amp;shy;Pointer&lt;/CODE&gt;
we registered against so that the caller doesn't
have to pass it back in when disconnecting.
&lt;/P&gt;
&lt;P&gt;
&lt;B&gt;Exercise&lt;/B&gt;:
Is the &lt;CODE&gt;m_spcp.Release()&lt;/CODE&gt; call
in &lt;CODE&gt;Disconnect&lt;/CODE&gt;
really necessary?
(Assuming that &lt;CODE&gt;Connect&lt;/CODE&gt; is called at most once.)
&lt;/P&gt;
&lt;P&gt;
This helper template class makes writing dispatch interface
connection point clients really simple,
since all you have to do is implement &lt;CODE&gt;Simple&amp;shy;Invoke&lt;/CODE&gt;
in the form of a &lt;CODE&gt;switch&lt;/CODE&gt; statement on the
dispatch IDs you care about:
&lt;/P&gt;
&lt;PRE&gt;
class CWidgetClient : public CDispInterfaceBase&lt;DWidgetEvents&gt;
{
public:
 CWidgetClient() { }

 HRESULT SimpleInvoke(
    DISPID dispid, DISPPARAMS *pdispparams, VARIANT *pvarResult)
{
 switch (dispid) {
 case WDISPID_RENAMED:
  HeyLookItGotRenamed(pdispparams-&amp;gt;rgvarg[0].bstrVal,
                      pdispparams-&amp;gt;rgvarg[1].bstrVal);
  break;
 }
 return S_OK;
};
&lt;/PRE&gt;
&lt;P&gt;
In the &lt;CODE&gt;Simple&amp;shy;Invoke&lt;/CODE&gt; method,
we switch on the dispatch ID,
and if we see one we like, we extract the parameters from the
&lt;CODE&gt;pdispparams&lt;/CODE&gt;.
&lt;/P&gt;
&lt;P&gt;
&lt;B&gt;Update&lt;/B&gt;: Commenter parkrrr
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2013/06/12/10425215.aspx#10425376"&gt;
points out&lt;/A&gt; a huge gotcha with the
&lt;CODE&gt;DISP&amp;shy;PARAMS&lt;/CODE&gt; structure:
The parameters are passed in &lt;I&gt;reverse&lt;/I&gt; order.
I don't know why.
They just are.
&lt;/P&gt;
&lt;P&gt;
Next time, we'll start hooking up events to our Little Program
so it can update when the user navigates an Explorer or
Internet Explorer window.
&lt;/P&gt;
&lt;P&gt;
&lt;B&gt;Warning! Managed code!&lt;/B&gt;
The CLR
understands the connection point/&lt;WBR&gt;dispatch interface
convention and exposes a dispatch event
to managed code
&lt;A HREF="http://msdn.microsoft.com/library/66ahbe6y"&gt;
in the form of a CLR event and corresponding delegate&lt;/A&gt;.
For example, our &lt;CODE&gt;Renamed&lt;/CODE&gt; event is
exposed as an event called &lt;CODE&gt;Renamed&lt;/CODE&gt;,
with delegate type
&lt;CODE&gt;DWidget&amp;shy;Events_&lt;WBR&gt;Renamed&amp;shy;Event&amp;shy;Handler&lt;/CODE&gt;.
You can listen on the event the way you listen
to any other CLR event:
&lt;CODE&gt;widget.Renamed += this.OnRenamed;&lt;/CODE&gt;.
&lt;/P&gt;
&lt;P&gt;
&lt;B&gt;Note&lt;/B&gt;: I completely ignored the subject of dual interfaces.
You can read about those if you like,
but we won't need to know about them for the job at hand.
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10425215" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Code/">Code</category></item><item><title>An introduction to COM connection points</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2013/06/11/10424940.aspx</link><pubDate>Tue, 11 Jun 2013 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10424940</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>16</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10424940</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2013/06/11/10424940.aspx#comments</comments><description>&lt;P&gt;
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2013/06/10/10424662.aspx"&gt;
Last time&lt;/A&gt;,
we saw how to enumerate all the Internet Explorer and
Explorer Windows and see what they are viewing.
But that program printed static information.
It didn't track the changes to the windows if the user
clicked to another Web page or navigated to a different folder.
&lt;/P&gt;
&lt;P&gt;
In order to hook that up, we
need to understand the connection point model and the
way events are expressed in dispatch interfaces.
First, let's look at the connection point model.
These topics confused me when I first met them
(in part because I didn't do a good job of mentally
separating them into two topics and instead treated it
as one big topic),
so I'm going to spend a few days
trying to explain how it works,
and then later this week, we'll actually hook things up.
(And actually hooking it up is a lot easier than explaining it.)
&lt;/P&gt;
&lt;P&gt;
Today, the connection point model.
&lt;/P&gt;
&lt;P&gt;
Suppose you have a widget which can have multiple clients.
The clients can communicate with the widget by invoking methods
on the widget, like
&lt;CODE&gt;IWidget::&lt;WBR&gt;Set&amp;shy;Color&lt;/CODE&gt;.
but how does the widget communicate with its clients?
Well, since this is COM, the first thing you need is an interface,
say,
&lt;CODE&gt;IWidget&amp;shy;Client&lt;/CODE&gt;.
The idea is that each client implements
&lt;CODE&gt;IWidget&amp;shy;Client&lt;/CODE&gt;,
and when the widget needs to, say, notify each client that
the color changed,
it can invoke
&lt;CODE&gt;IWidget&amp;shy;Client::&lt;WBR&gt;On&amp;shy;Color&amp;shy;Changed&lt;/CODE&gt;
on each one.
Each client can register with the widget for notifications.
&lt;/P&gt;
&lt;P&gt;
The COM interface for standardizing the registration mechanism
is &lt;CODE&gt;IConnection&amp;shy;Point&lt;/CODE&gt;.
A &lt;I&gt;connection point&lt;/I&gt;
acts as a middle-man between
the widget and all its clients:
Whenever the widget needs to notify all its clients,
it tells the connection point to do it.
&lt;/P&gt;
&lt;TABLE&gt;
&lt;TR&gt;
&lt;TABLE BORDER=0 CELLPADDING=0 CELLSPACING=0
       SUMMARY="To the left is the widget. An arrow goes from the widget to the connection point in the center. Three arrows go from the connection point to clients A, B, and C on the right."&gt;
&lt;TR&gt;
    &lt;TD ROWSPAN=5 ALIGN=center STYLE="border: solid black .75pt; padding: 3pt"&gt;
    Widget&lt;/TD&gt;
    &lt;TD&gt;&lt;/TD&gt;
    &lt;TD ROWSPAN=5 ALIGN=center STYLE="border: solid black .75pt; padding: 3pt"&gt;
    Connection&lt;BR&gt;Point&lt;/TD&gt;
    &lt;TD&gt;&amp;rarr;&lt;/TD&gt;
    &lt;TD ALIGN=center STYLE="border: solid black .75pt; padding: 3pt"&gt;
    Client&amp;nbsp;A&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR STYLE="height: 1ex"&gt;
    &lt;TD&gt;&lt;/TD&gt;
    &lt;TD&gt;&lt;/TD&gt;
    &lt;TD&gt;&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
    &lt;TD&gt;&amp;rarr;&lt;/TD&gt;
    &lt;TD&gt;&amp;rarr;&lt;/TD&gt;
    &lt;TD ALIGN=center STYLE="border: solid black .75pt; padding: 3pt"&gt;
    Client&amp;nbsp;B&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR STYLE="height: 1ex"&gt;
    &lt;TD&gt;&lt;/TD&gt;
    &lt;TD&gt;&lt;/TD&gt;
    &lt;TD&gt;&lt;/TD&gt;
&lt;/TR&gt;
&lt;TR&gt;
    &lt;TD&gt;&lt;/TD&gt;
    &lt;TD&gt;&amp;rarr;&lt;/TD&gt;
    &lt;TD ALIGN=center STYLE="border: solid black .75pt; padding: 3pt"&gt;
    Client&amp;nbsp;C&lt;/TD&gt;
&lt;/TR&gt;
&lt;/TABLE&gt;
&lt;P&gt;
A client registers with a connection point by calling
&lt;CODE&gt;IConnection&amp;shy;Point::&lt;WBR&gt;Advise&lt;/CODE&gt;,
and it unregisters by calling
&lt;CODE&gt;IConnection&amp;shy;Point::&lt;WBR&gt;Unadvise&lt;/CODE&gt;.
&lt;/P&gt;
&lt;P&gt;
Okay, that's great,
but how do clients find the connection point so they can register with it?
&lt;/P&gt;
&lt;P&gt;
The widget exposes an interface known as
&lt;CODE&gt;IConnection&amp;shy;Point&amp;shy;Container&lt;/CODE&gt;
which provides access to an object's connection points.
The client can call the
&lt;CODE&gt;IConnection&amp;shy;Point&amp;shy;Container::&lt;WBR
&gt;Find&amp;shy;Connection&amp;shy;Point&lt;/CODE&gt; method
to get access to a specific connection point.
&lt;/P&gt;
&lt;P&gt;
Here's how the pieces fit together:
&lt;/P&gt;
&lt;PRE&gt;
// error checking elided for expository purposes

void IUnknown_FindConnectionPoint(IUnknown *punk,
                                  REFIID riid,
                                  IConnectionPoint **ppcp)
{
 // get the IConnectionPointContainer interface
 CComQIPtr&amp;lt;IConnectionPointContainer&amp;gt; spcpc(punk);

 // Locate the connection point
 spcpc-&amp;gt;FindConnectionPoint(riid,  ppcp);
}

class CClient : public IWidgetClient
{
...
 IWidget *m_pWidget;
 DWORD m_dwCookie;
};

CClient::RegisterWidgetClient()
{
 // Find the IWidgetClient connection point
 CComPtr&amp;lt;IConnectionPoint&amp;gt; spcp;
 IUnknown_FindConnectionPoint(m_pWidget,
                              IID_IWidgetClient, &amp;amp;spcp);

 // register with it
 spcp-&amp;gt;Advise(this, &amp;amp;m_dwCookie);
}

CClient::UnregisterWidgetClient()
{
 // Find the IWidgetClient connection point
 CComPtr&amp;lt;IConnectionPoint&amp;gt; spcp;
 IUnknown_FindConnectionPoint(m_pWidget,
                              IID_IWidgetClient, &amp;amp;spcp);

 // unregister from it
 spcp-&amp;gt;Unadvise(m_dwCookie);
}
&lt;/PRE&gt;
&lt;P&gt;
After registering as a widget client,
the &lt;CODE&gt;CClient&lt;/CODE&gt; object will receive
method calls on its &lt;CODE&gt;IWidget&amp;shy;Client&lt;/CODE&gt;
until it unregisters.
&lt;/P&gt;
&lt;P&gt;
Now the widget and clients have two-way communication.
If the clients want to initiate the communuication,
it can call a method on &lt;CODE&gt;IWidget&lt;/CODE&gt;.
If the widget wants to initiate the communication,
it can call a method on &lt;CODE&gt;IWidget&amp;shy;Client&lt;/CODE&gt;.
&lt;/P&gt;
&lt;P&gt;
Note that we've created a giant circular reference.
The widget has a reference to its connection point
(so it can tell it to fire a notification to all its clients),
and the connection point has a reference to the widget
client
(so it can forward the notification along),
and the widget client has a reference to the widget
in its &lt;CODE&gt;m_pWidget&lt;/CODE&gt; member.
In order to break this cycle,
you have to remember to explicitly call
&lt;CODE&gt;Unregister&amp;shy;Widget&amp;shy;Client&lt;/CODE&gt;
when you are no longer interested in receiving
widget notifications.
&lt;/P&gt;
&lt;P&gt;
Note that even though the arrows in the diagram above
flow from left to right (from widget to clients),
that doesn't mean that the
information flow is strictly left-to-right.
You can pass information in the other direction
via return values or output parameters.
&lt;/P&gt;
&lt;P&gt;
For example, there might be a method on
the &lt;CODE&gt;IWidget&amp;shy;Client&lt;/CODE&gt; interface
called &lt;CODE&gt;Get&amp;shy;Color&lt;/CODE&gt;:
&lt;/P&gt;
&lt;PRE&gt;
interface IWidgetClient : IUnknown
{
 ...
 HRESULT GetColor([out] COLORREF *pclr);
 ...
};
&lt;/PRE&gt;
&lt;P&gt;
Since there can be multiple clients, the widget
needs to have some sort of rule for deciding which
client gets to choose the color.
It might decide to ask each client in turn for a color,
until one of them returns &lt;CODE&gt;S_OK&lt;/CODE&gt;,
and that client's color is used and no further clients
are notified.
&lt;/P&gt;
&lt;P&gt;
Or maybe there's a method called
&lt;CODE&gt;On&amp;shy;Save&lt;/CODE&gt;:
&lt;/P&gt;
&lt;PRE&gt;
interface IWidgetClient : IUnknown
{
 ...
 HRESULT OnSave([in] IPropertyStorage *pps);
 ...
};
&lt;/PRE&gt;
&lt;P&gt;
The convention here might be that all clients
will be notified of the Save operation and they
can write any additional information to the
&lt;CODE&gt;IProperty&amp;shy;Storage&lt;/CODE&gt; while handing
the notification.
&lt;/P&gt;
&lt;P&gt;
Those are just examples.
Feel free to make up your own.
The point is that just because the arrows go from the
widget to the clients doesn't mean that information
can't flow back the other way.
&lt;/P&gt;
&lt;P&gt;
Most of the time, you have the simple case where
a widget will expose a single connection point.
In that case, the generality of the
&lt;CODE&gt;IConnection&amp;shy;Point&amp;shy;Container&lt;/CODE&gt;
may seem unnecessary.
But it allows you to add new connection points later.
For example, you might have multiple client interfaces
for different types of clients.
You could have
&lt;CODE&gt;IWidget&amp;shy;Color&amp;shy;Client&lt;/CODE&gt;
for clients that are interested only in color changes,
and
&lt;CODE&gt;IWidget&amp;shy;Network&amp;shy;Client&lt;/CODE&gt;
for clients that are interested only in monitoring the
widget's network activity.
&lt;/P&gt;
&lt;P&gt;
Or maybe you didn't plan on having multiple connection points
originally,
but in the second version of your product,
you want to add additional methods to
&lt;CODE&gt;IWidget&amp;shy;Client&lt;/CODE&gt;,
so you need to create
&lt;CODE&gt;IWidget&amp;shy;Client2&lt;/CODE&gt;,
which means that you also need a new connection point for it.
&lt;/P&gt;
&lt;P&gt;
Next time, a look at the special case where
the client interface is a dispatch interface.
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10424940" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Code/">Code</category></item><item><title>Unexpected complexity of Swedish pronouns, and escaping the resulting embarrassment</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2013/06/10/10424663.aspx</link><pubDate>Mon, 10 Jun 2013 14:00:01 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10424663</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>13</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10424663</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2013/06/10/10424663.aspx#comments</comments><description>&lt;P&gt;
I dreamed that
Swedish had separate third-person-plural pronouns based on gender.
They were formed from
&lt;I LANG=sv&gt;han&lt;/I&gt;
and
&lt;I LANG=sv&gt;hon&lt;/I&gt;
by adding a common suffix,
but the pattern broke down for
&lt;I LANG=sv&gt;det&lt;/I&gt;,
and I got stuck trying to finish a sentence without knowing the correct word.
&lt;/P&gt;
&lt;P&gt;
I was able to escape from this embarrassing situation by using
a technique available only in dreams:
I woke up.
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10424663" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Non_2D00_Computer/">Non-Computer</category><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Dream/">Dream</category></item><item><title>A big little program: Monitoring Internet Explorer and Explorer windows, part 1: Enumeration</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2013/06/10/10424662.aspx</link><pubDate>Mon, 10 Jun 2013 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10424662</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>18</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10424662</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2013/06/10/10424662.aspx#comments</comments><description>&lt;P&gt;
Normally, Monday is the day for Little Programs,
but this time I'm going to spend a few days
on a single Little Program.
Now, this might very well disqualify it from the name &lt;I&gt;Little Program&lt;/I&gt;,
but the concepts are still little;
all I'm doing is
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2009/08/04/9856634.aspx"&gt;
snapping blocks together&lt;/A&gt;.
(Plus, it's my Web site, so you can just suck it.)
&lt;/P&gt;
&lt;P&gt;
The goal of our Little Program is to monitor Internet Explorer
and Explorer windows as they are created, navigate to new locations,
and are destroyed.
(In principle, other Web browsers can participate in this protocol,
but I don't know of any that do, so I'll assume that only Explorer
and Internet Explorer
register with the &lt;CODE&gt;Shell&amp;shy;Windows&lt;/CODE&gt; object.)
&lt;/P&gt;
&lt;P&gt;
The key to all this is the
&lt;CODE&gt;Shell&amp;shy;Windows&lt;/CODE&gt; object,
which we've
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2013/04/22/10412906.aspx"&gt;
spent time&lt;/A&gt;
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2013/03/18/10403054.aspx"&gt;
playing with&lt;/A&gt;
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2005/07/05/435657.aspx"&gt;
in the past&lt;/A&gt;.
&lt;/P&gt;
&lt;P&gt;
Today we're going to write a helper function that takes an object
returned by the 
&lt;CODE&gt;Shell&amp;shy;Windows&lt;/CODE&gt; object
and extract the window handle and current location.
This is the guts of our Little Program,
so I'm basically doing the cool stuff up front,
and then leaving the annoying bits for later.
&lt;/P&gt;
&lt;PRE&gt;
#define &lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2004/07/15/184076.aspx"&gt;UNICODE&lt;/A&gt;
#define &lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2004/02/12/71851.aspx"&gt;_UNICODE&lt;/A&gt;
#define STRICT
#define &lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2013/01/24/10387757.aspx"&gt;STRICT_TYPED_ITEMIDS&lt;/A&gt;
#include &amp;lt;windows.h&amp;gt;
#include &amp;lt;ole2.h&amp;gt;
#include &amp;lt;iostream&amp;gt;

#include &amp;lt;shlobj.h&amp;gt;
#include &amp;lt;atlbase.h&amp;gt;
#include &amp;lt;atlalloc.h&amp;gt;
&lt;/PRE&gt;
&lt;P&gt;
Now that we got the preliminary header file goop out of the way,
we can write the exciting function.
&lt;/P&gt;
&lt;PRE&gt;
HRESULT GetBrowserInfo(IUnknown *punk, HWND *phwnd,
                       PWSTR *ppszLocation)
{
 HRESULT hr;

 CComPtr&amp;lt;IShellBrowser&amp;gt; spsb;
 hr = IUnknown_QueryService(punk, SID_STopLevelBrowser,
                            IID_PPV_ARGS(&amp;amp;spsb));
 if (FAILED(hr)) return hr;

 hr = spsb-&amp;gt;GetWindow(phwnd);
 if (FAILED(hr)) return hr;

 hr = GetLocationFromView(spsb, ppszLocation);
 if (SUCCEEDED(hr)) return hr;

 return GetLocationFromBrowser(punk, ppszLocation);
}
&lt;/PRE&gt;
&lt;P&gt;
Awfully short for what purported to be an exciting function,
but that's because I hid the exciting parts in helper functions.
&lt;/P&gt;
&lt;P&gt;
First, we take the object and ask to locate the top-level browser,
since that's where some of the interesting information hangs out.
We ask for the &lt;CODE&gt;IShell&amp;shy;Browser&lt;/CODE&gt; so we can get the
window handle via the base class method
&lt;CODE&gt;IOle&amp;shy;Window::&lt;WBR&gt;Get&amp;shy;Window&lt;/CODE&gt;.
That's the easy part.
&lt;/P&gt;
&lt;P&gt;
Getting the current location is tricky,
because Explorer windows do it one way,
and Internet Explorer does it another way.
That's because Explorer windows browse the shell namespace,
whereas Internet Explorer windows browse the Internet.
Shell namespace locations are represented by pidls,
whereas Internet locations are represented by URLs.
&lt;/P&gt;
&lt;P&gt;
First, the Explorer way:
&lt;/P&gt;
&lt;PRE&gt;
HRESULT GetLocationFromView(IShellBrowser *psb,
                            PWSTR *ppszLocation)
{
 HRESULT hr;

 *ppszLocation = nullptr;

 CComPtr&amp;lt;IShellView&amp;gt; spsv;
 hr = psb-&amp;gt;QueryActiveShellView(&amp;amp;spsv);
 if (FAILED(hr)) return hr;

 CComQIPtr&amp;lt;IPersistIDList&amp;gt; sppidl(spsv);
 if (!sppidl) return E_FAIL;

 CComHeapPtr&amp;lt;ITEMIDLIST_ABSOLUTE&amp;gt; spidl;
 hr = sppidl-&amp;gt;GetIDList(&amp;amp;spidl);
 if (FAILED(hr)) return hr;

 CComPtr&amp;lt;IShellItem&amp;gt; spsi;
 hr = SHCreateItemFromIDList(spidl, IID_PPV_ARGS(&amp;amp;spsi));
 if (FAILED(hr)) return hr;

 hr = spsi-&amp;gt;GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING,
                           ppszLocation);
 return hr;
}
&lt;/PRE&gt;
&lt;P&gt;
The maze we navigate here is to start from the
&lt;CODE&gt;IShell&amp;shy;Browser&lt;/CODE&gt; and get to the
&lt;CODE&gt;IShell&amp;shy;View&lt;/CODE&gt; by calling
&lt;CODE&gt;IShell&amp;shy;Browser::&lt;WBR&gt;Query&amp;shy;Active&amp;shy;Shell&amp;shy;View&lt;/CODE&gt;.
It's rather annoying that the
&lt;CODE&gt;IShell&amp;shy;Browser::&lt;WBR&gt;Query&amp;shy;Active&amp;shy;Shell&amp;shy;View&lt;/CODE&gt;
method always returns you an
&lt;CODE&gt;IShell&amp;shy;View&lt;/CODE&gt; rather than being forward-looking and
letting you pass a &lt;CODE&gt;riid&lt;/CODE&gt;/&lt;CODE&gt;ppv&lt;/CODE&gt; pair.
(The shell has for the most part learned this lesson, and new
object creation or retrieval functions tend to take the
&lt;CODE&gt;riid&lt;/CODE&gt;/&lt;CODE&gt;ppv&lt;/CODE&gt; pair so you can specify
your ring size when you place the order instead of always getting
a size&amp;nbsp;6 ring and then having to resize it.)
Since
&lt;CODE&gt;IShell&amp;shy;Browser::&lt;WBR&gt;Query&amp;shy;Active&amp;shy;Shell&amp;shy;View&lt;/CODE&gt;
doesn't let us specify the desired interface, we have to
do the &lt;CODE&gt;Query&amp;shy;Interface&lt;/CODE&gt; ourselves
to convert the &lt;CODE&gt;IShell&amp;shy;View&lt;/CODE&gt; into what we really
want: The &lt;CODE&gt;IPersist&amp;shy;ID&amp;shy;List&lt;/CODE&gt;.
&lt;/P&gt;
&lt;P&gt;
From the &lt;CODE&gt;IPersist&amp;shy;ID&amp;shy;List&lt;/CODE&gt; we ask for the pidl,
which now tells us what the Explorer window is looking at.
For display purposes, we convert it into a string by
converting the pidl into an &lt;CODE&gt;IShell&amp;shy;Item&lt;/CODE&gt;
(notice the handy
&lt;CODE&gt;riid&lt;/CODE&gt;/&lt;CODE&gt;ppv&lt;/CODE&gt; pair produced by the
type-checking
&lt;CODE&gt;IID_&lt;WBR&gt;PPV_&lt;WBR&gt;ARGS&lt;/CODE&gt; macro)
and then asking the shell item for its parsing name.
&lt;/P&gt;
&lt;P&gt;
(We saw techniques similar to this
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2004/07/20/188696.aspx"&gt;
a few years ago&lt;/A&gt;.)
&lt;/P&gt;
&lt;P&gt;
If it turns out we don't have an Explorer window, then we try
again using the Web browser interfaces:
&lt;/P&gt;
&lt;PRE&gt;
HRESULT GetLocationFromBrowser(IUnknown *punk,
                               PWSTR *ppszLocation)
{
 HRESULT hr;

 CComQIPtr&amp;lt;IWebBrowser2&amp;gt; spwb2(punk);
 if (!spwb2) return E_FAIL;

 CComBSTR sbsLocation;
 hr = spwb2-&amp;gt;get_LocationURL(&amp;amp;sbsLocation);
 if (FAILED(hr)) return hr;

 return SHStrDupW(sbsLocation, ppszLocation);
}
&lt;/PRE&gt;
&lt;P&gt;
We turn the object into an &lt;CODE&gt;IWeb&amp;shy;Browser2&lt;/CODE&gt; and ask
for the &lt;CODE&gt;Location&amp;shy;URL&lt;/CODE&gt; property.
The annoyance here is that
&lt;CODE&gt;IWeb&amp;shy;Browser2&lt;/CODE&gt; is an automation interface,
so it uses &lt;CODE&gt;BSTR&lt;/CODE&gt; for passing strings around,
which is different from
&lt;CODE&gt;IShell&amp;shy;Item::&lt;WBR&gt;Get&amp;shy;Display&amp;shy;Name&lt;/CODE&gt;
which uses &lt;CODE&gt;Co&amp;shy;Task&amp;shy;Mem&amp;shy;Alloc&lt;/CODE&gt;,
since that is the convention for non-dispatch COM interfaces.
We therefore have to convert the &lt;CODE&gt;BSTR&lt;/CODE&gt;
to a task-allocated
&lt;CODE&gt;PWSTR&lt;/CODE&gt; before returning,
so that the return value is consistent with
&lt;CODE&gt;Get&amp;shy;Location&amp;shy;From&amp;shy;View&lt;/CODE&gt;.
&lt;/P&gt;
&lt;P&gt;
Finally, we call the function in a loop to test that it actually works:
&lt;/P&gt;
&lt;PRE&gt;
CComPtr&amp;lt;IShellWindows&amp;gt; g_spWindows;

HRESULT DumpWindows()
{
 CComPtr&amp;lt;IUnknown&amp;gt; spunkEnum;
 HRESULT hr = g_spWindows-&amp;gt;_NewEnum(&amp;amp;spunkEnum);
 if (FAILED(hr)) return hr;

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

  HWND hwnd;
  CComHeapPtr&amp;lt;WCHAR&amp;gt; spszLocation;
  if (FAILED(GetBrowserInfo(svar.pdispVal, &amp;amp;hwnd,
                            &amp;amp;spszLocation))) continue;

   std::wcout &amp;lt;&amp;lt; hwnd
              &amp;lt;&amp;lt; L" "
              &amp;lt;&amp;lt; static_cast&amp;lt;PCWSTR&amp;gt;(spszLocation)
              &amp;lt;&amp;lt; std::endl;
 }
 return S_OK;
}

int __cdecl wmain(int, PWSTR argv[])
{
 &lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2004/05/20/135841.aspx"&gt;CCoInitialize&lt;/A&gt; init;
 g_spWindows.CoCreateInstance(CLSID_ShellWindows);
 DumpWindows();
 g_spWindows.&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2004/05/20/135841.aspx"&gt;Release()&lt;/A&gt;;

 return 0;
}
&lt;/PRE&gt;
&lt;P&gt;
Yes, I stupidly made &lt;CODE&gt;g_spWindows&lt;/CODE&gt;
a global variable, but it'll come in handy later.
(It's still stupid, but at least there's a reason for
the stupidity.)
&lt;/P&gt;
&lt;P&gt;
Okay, we can take this program for a spin.
When you run it, it should print the window handles and
locations of all your Explorer and Internet Explorer windows.
&lt;/P&gt;
&lt;P&gt;
Before we can start hooking up events to keep this list up to date,
we need to learn a bit about connection points and using
dispatch interfaces as connection point interfaces.
We'll spend a few days on those topics,
then return to our program.
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10424662" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Code/">Code</category></item><item><title>Sharing an input queue takes what used to be asynchronous and makes it synchronous, like focus changes</title><link>http://blogs.msdn.com/b/oldnewthing/archive/2013/06/07/10424279.aspx</link><pubDate>Fri, 07 Jun 2013 14:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:10424279</guid><dc:creator>Raymond Chen - MSFT</dc:creator><slash:comments>19</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://blogs.msdn.com/b/oldnewthing/rsscomments.aspx?WeblogPostID=10424279</wfw:commentRss><comments>http://blogs.msdn.com/b/oldnewthing/archive/2013/06/07/10424279.aspx#comments</comments><description>&lt;P&gt;
As I noted earlier in the series,
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2013/06/04/10423296.aspx"&gt;
attaching input queues puts you back into the
world of co&amp;ouml;perative multitasking&lt;/A&gt;,
where the two attached threads need to work together to get anything done.
&lt;/P&gt;
&lt;P&gt;
Back in the old 16-bit days,
when input was synchronous,
there was only one active window,
only one focus window,
only one window with capture,
only one caret,
only one cursor show count,
only one keyboard state,
only one input state.
Furthermore, if you called
&lt;CODE&gt;Set&amp;shy;Focus&lt;/CODE&gt;,
you had to wait until the previous focus
window responded to the
&lt;CODE&gt;WM_&lt;WBR&gt;KILL&amp;shy;FOCUS&lt;/CODE&gt; message
before your
&lt;CODE&gt;Set&amp;shy;Focus&lt;/CODE&gt; call returned.
&lt;/P&gt;
&lt;P&gt;
With asynchronous input,
these sorts of operations are now local to your input queue.
If you call
&lt;CODE&gt;Set&amp;shy;Focus&lt;/CODE&gt;,
then that steals focus only from other windows which belong
to your input queue.
Windows which belong to other input queues are unaffected.
(Conversely, you can set focus only to windows which belong
to your input queue,
since those are the only windows your input queue has access to.)
&lt;/P&gt;
&lt;P&gt;
This is probably not very exciting,
until you look at the one thing that can reach across
input queues: The foreground window.
&lt;/P&gt;
&lt;P&gt;
The concept of the foreground window was introduced when
input was desynchronized in order to express the
"really global active window",
as opposed to &lt;CODE&gt;Set&amp;shy;Active&amp;shy;Window&lt;/CODE&gt;,
which continued to refer to the local active window.
It's something that was originally intended to be used
only in emergencies
since it violates the isolation of input queues,
but as we learned before,
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2008/10/06/8969399.aspx"&gt;
eventually nothing is special any more&lt;/A&gt;,
and what used to be the special function for stepping outside the box
has become the function you use every day for getting things done.
&lt;/P&gt;
&lt;P&gt;
What most people don't realize is that
&lt;CODE&gt;Set&amp;shy;Foreground&amp;shy;Window&lt;/CODE&gt;
is still subject to the rules on synchronous input.
If you call
&lt;CODE&gt;Set&amp;shy;Foreground&amp;shy;Window&lt;/CODE&gt;,
and the previous foreground window also belongs to your input queue,
then your call to
&lt;CODE&gt;Set&amp;shy;Foreground&amp;shy;Window&lt;/CODE&gt;
will wait until the previous foreground window
processes its
&lt;CODE&gt;WM_&lt;WBR&gt;ACTIVATE(&lt;WBR&gt;WA_&lt;WBR&gt;INACTIVE)&lt;/CODE&gt; message.
&lt;/P&gt;
&lt;P&gt;
A lot of people use &lt;CODE&gt;Attach&amp;shy;Thread&amp;shy;Input&lt;/CODE&gt;
thinking that it's a Get Out of Jail Free card,
letting them manipulate windows of other programs and bypass
the normal rules for focus and activation.
But in fact it's a &lt;I&gt;Get Into the Same Jail&lt;/I&gt; card,
because you tied your thread's fate to that other thread.
If that thread has stopped responding to messages,
then your thread will also stop responding to messages,
since you are sharing the same input queue
and operations within an input queue are synchronous.
&lt;/P&gt;
&lt;P&gt;
&lt;B&gt;Bonus reminder&lt;/B&gt;:
If two windows are related by a parent/child relationship
or owner/owned relationship, then their input queues
are automatically attached.
For example, if you do a &lt;CODE&gt;Set&amp;shy;Parent&lt;/CODE&gt; where
the parent and child are in different threads,
you have just synchronized the two threads.
This sort of cross-thread relationship is
&lt;A HREF="http://blogs.msdn.com/b/oldnewthing/archive/2013/04/12/10410454.aspx"&gt;
technically legal&lt;/A&gt;,
but
it is very difficult to manage correctly,
so it should be avoided unless you really know what you're doing.
And if you are doing cross-thread or cross-process between
windows that were not designed to participate in cross-thread
or cross-process parenting,
you are almost certainly doomed.
&lt;/P&gt;
&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=10424279" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/b/oldnewthing/archive/tags/Code/">Code</category></item></channel></rss>