{"id":102413,"date":"2019-04-12T07:00:00","date_gmt":"2019-04-12T14:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/oldnewthing\/?p=102413"},"modified":"2023-08-01T16:19:07","modified_gmt":"2023-08-01T23:19:07","slug":"20190412-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20190412-00\/?p=102413\/","title":{"rendered":"How can a desktop app use a Windows Runtime object that infers UI context from its thread? The IInitializeWithWindow pattern"},"content":{"rendered":"<p>Many objects in the Windows Runtime can be used from desktop apps. For today&#8217;s example, we&#8217;ll use the <code>File\u00adOpen\u00adPicker<\/code>. This is a rather artificial example because you could just use the <code>IFile\u00adDialog<\/code> interface to get equivalent functionality in a desktop app, but I just picked it for use as an example.<\/p>\n<p>Start with our <a href=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20030723-00\/?p=43073\"> scratch program<\/a> and make these changes:<\/p>\n<pre>#include &lt;winrt\/windows.storage.pickers.h&gt;\r\n\r\nwinrt::Windows::Foundation::IAsyncAction\r\nShowFilePickerAsync(HWND hwnd)\r\n{\r\n    auto picker = winrt::Windows::Storage::Pickers::FileOpenPicker();\r\n    picker.FileTypeFilter().Append(L\".jpg\");\r\n    auto file = co_await picker.PickSingleFileAsync();\r\n}\r\n\r\nwinrt::fire_and_forget OnChar(HWND hwnd, TCHAR ch, int cRepeat)\r\n{\r\n    co_await ShowFilePickerAsync(hwnd);\r\n}\r\n\r\n\/\/ Add to WndProc\r\n    HANDLE_MSG(hwnd, WM_CHAR, OnChar);\r\n<\/pre>\n<p>Run this program and press a key. The program will crash because the <code>File\u00adOpen\u00adPicker<\/code> looks for a <code>Core\u00adWindow<\/code> on the current thread to serve as the owner of the dialog. But we are a Win32 desktop app without a <code>Core\u00adWindow<\/code>.<\/p>\n<p>The solution is to use the <code>IInitialize\u00adWith\u00adWindow<\/code> interface. <a href=\"https:\/\/docs.microsoft.com\/en-us\/windows\/desktop\/api\/shobjidl_core\/nn-shobjidl_core-iinitializewithwindow\"> Many Windows Runtime objects<\/a> which infer the <code>Core\u00adWindow<\/code> from the current thread support the <code>IInitialize\u00adWith\u00adWindow<\/code> interface to allow a Win32 desktop app to specify an explicit window.<\/p>\n<p>Make the following changes to the program:<\/p>\n<pre><span style=\"border: solid 1px currentcolor;\">#include &lt;shobjidl.h&gt;<\/span>\r\n#include &lt;winrt\/windows.storage.pickers.h&gt;\r\n\r\nwinrt::Windows::Foundation::IAsyncAction\r\nShowFilePickerAsync(HWND hwnd)\r\n{\r\n    auto picker = winrt::Windows::Storage::Pickers::FileOpenPicker();\r\n    <span style=\"border: solid 1px currentcolor;\">picker.as&lt;IInitializeWithWindow&gt;()-&gt;Initialize(hwnd);<\/span>\r\n    picker.FileTypeFilter().Append(L\".jpg\");\r\n    auto file = co_await picker.PickSingleFileAsync();\r\n}\r\n<\/pre>\n<p>This time, the File Open dialog opens because we explicitly provided a window handle to use as the owner.<\/p>\n<p>The <code>IInitialize\u00adWindow\u00adWindow<\/code> pattern is used mostly in the case where an object is simply constructed. There is another pattern for the case where an object is obtained by calling a method: The interop pattern, which I covered <a href=\"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/20170315-00\/?p=95735\"> some time ago<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Explicitly associating with a window handle.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[25],"class_list":["post-102413","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-code"],"acf":[],"blog_post_summary":"<p>Explicitly associating with a window handle.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/102413","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=102413"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/102413\/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=102413"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=102413"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=102413"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}