{"id":96595,"date":"2017-07-13T07:00:00","date_gmt":"2017-07-13T21:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/?p=96595"},"modified":"2019-03-13T01:14:05","modified_gmt":"2019-03-13T08:14:05","slug":"20170713-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20170713-00\/?p=96595","title":{"rendered":"Customizing the window handle for item enumeration in IShellItem"},"content":{"rendered":"<p>Some time ago, I showed how to <a HREF=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20150126-00\/?p=44833\">customize the enumeration flags used when enumerating items with <code>IShell&shy;Item<\/code><\/a>. This controls the <code>grfFlags<\/code> parameter passed to <a HREF=\"https:\/\/msdn.microsoft.com\/library\/windows\/desktop\/bb775066(v=vs.85).aspx\">the <code>IShell&shy;Folder::<\/code><code>Enum&shy;Objects<\/code> method<\/a>, but what about the <code>hwndOwner<\/code> parmaeter? How to do you customize the window handle? <\/p>\n<p>The window handle for the enumeration comes from the site of the enumerator. <\/p>\n<p>There&#8217;s no real reason you were expected to know this. <\/p>\n<p>Here&#8217;s a Little Program that demonstrates. It is basically the program we used <a HREF=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20150126-00\/?p=44833\">last time<\/a>, but translated from ATL to WRL (because that lets me <a HREF=\"https:\/\/msdn.microsoft.com\/library\/jj822931.aspx\">use the <code>Runtime&shy;Class<\/code> template<\/a>.) <\/p>\n<pre>\n#define STRICT\n#include &lt;windows.h&gt;\n#include &lt;shlobj.h&gt;\n#include &lt;shlwapi.h&gt;\n#include &lt;knownfolders.h&gt;\n#include &lt;wrl\/client.h&gt;\n#include &lt;wrl\/implements.h&gt;\n#include &lt;stdio.h&gt;    \/\/ Horrors! Mixing stdio and C++!\n\nnamespace wrl = Microsoft::WRL;\n\nclass COleWindow : public wrl::RuntimeClass&lt;\n    wrl::RuntimeClassFlags&lt;wrl::ClassicCom&gt;, IOleWindow&gt;\n{\npublic:\n  HRESULT RuntimeClassInitialize(HWND hwnd)\n  {\n    m_hwnd = hwnd;\n    return S_OK;\n  }\n\n  STDMETHODIMP GetWindow(_Out_ HWND* phwnd)\n  {\n    *phwnd = m_hwnd;\n    return S_OK;\n  }\n\n  STDMETHODIMP ContextSensitiveHelp(BOOL \/* fEnterMode *\/)\n  {\n    return E_NOTIMPL;\n  }\n\nprivate:\n  HWND m_hwnd;\n};\n<\/pre>\n<p>The <code>COleWindow<\/code> class is a simple object which implements the <code>IOleWindow<\/code> interface. It coughs up the window handle you gave it at initialization. <\/p>\n<p>We can use this object to provide a window for enumeration. Remember that Little Programs do little to no error checking. <\/p>\n<pre>\nint __cdecl wmain(int argc, wchar_t** argv)\n{\n  <a HREF=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20110830-00\/?p=9773\">CCoInitialize<\/a> init;\n\n  if (argc &lt; 2) return 0;\n\n  HWND hwnd = CreateWindowW(L\"static\", L\"Title\",\n      WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,\n      CW_USEDEFAULT, CW_USEDEFAULT,\n      nullptr, nullptr, <a HREF=\"https:\/\/devblogs.microsoft.com\/oldnewthing\/\">HINST_THISCOMPONENT<\/a>, 0);\n\n  wrl::ComPtr&lt;IShellItem&gt; folder;\n  SHCreateItemFromParsingName(argv[1], nullptr,\n                              IID_PPV_ARGS(&amp;folder));\n\n  wrl::ComPtr&lt;IEnumShellItems&gt; enumerator;\n  folder-&gt;BindToHandler(nullptr, BHID_EnumItems,\n                           IID_PPV_ARGS(&amp;enumerator));\n\n  wrl::ComPtr&lt;IUnknown&gt; site;\n  wrl::MakeAndInitialize&lt;COleWindow&gt;(&amp;site, hwnd);\n  IUnknown_SetSite(enumerator.Get(), site.Get());\n\n  wrl::ComPtr&lt;IShellItem&gt; item;\n  while (enumerator-&gt;Next(1, item.ReleaseAndGetAddressOf(),\n                             nullptr) == S_OK) {\n    PWSTR name;\n    item-&gt;GetDisplayName(SIGDN_NORMALDISPLAY, &amp;name);\n    wprintf(L\"%s\\n\", name);\n    CoTaskMemFree(name);\n  }\n\n  return 0;\n}\n<\/pre>\n<p>First, we create a window so we have something to pass to <code>IShell&shy;Folder::<\/code><code>Enum&shy;Objects<\/code>. In real life, this is the window you want to use for any UI that is displayed as part of the enumeration. <\/p>\n<p>Next, we take the path from the command line and convert it to an <code>IShellItem<\/code>. This is not new. <\/p>\n<p>Once we have the folder as an <code>IShellItem<\/code>, we ask for its enumerator. If you wanted to customize the flags passed to the <code>IShell&shy;Folder::<\/code><code>Enum&shy;Objects<\/code> method, here&#8217;s where you would <a HREF=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20150126-00\/?p=44833\">pass a customizing <code>IBindCtx<\/code><\/a>. <\/p>\n<p>And then the new part: Before calling any enumeration methods, we create a <code>COleWindow<\/code> object and set it as the enumerator&#8217;s site. This tells the enumerator where to get its window from. <\/p>\n<p>We have nothing else interesting in our site, but in a real program, your site would probably implement <code>IService&shy;Provider<\/code> in order to be a full-fledged site chain. <\/p>\n<p>Finally, we use the enumerator in the usual manner and (for demonstration purposes) print out the names of the resulting objects. <\/p>\n","protected":false},"excerpt":{"rendered":"<p>It&#8217;s on the site.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-96595","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>It&#8217;s on the site.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/96595","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=96595"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/96595\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=96595"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=96595"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=96595"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}