Many objects in the Windows Runtime can be used from desktop apps. For today’s example, we’ll use the FileÂOpenÂPicker
. This is a rather artificial example because you could just use the IFileÂDialog
interface to get equivalent functionality in a desktop app, but I just picked it for use as an example.
Start with our scratch program and make these changes:
#include <winrt/windows.storage.pickers.h> winrt::Windows::Foundation::IAsyncAction ShowFilePickerAsync(HWND hwnd) { auto picker = winrt::Windows::Storage::Pickers::FileOpenPicker(); picker.FileTypeFilter().Append(L".jpg"); auto file = co_await picker.PickSingleFileAsync(); } winrt::fire_and_forget OnChar(HWND hwnd, TCHAR ch, int cRepeat) { co_await ShowFilePickerAsync(hwnd); } // Add to WndProc HANDLE_MSG(hwnd, WM_CHAR, OnChar);
Run this program and press a key. The program will crash because the FileÂOpenÂPicker
looks for a CoreÂWindow
on the current thread to serve as the owner of the dialog. But we are a Win32 desktop app without a CoreÂWindow
.
The solution is to use the IInitializeÂWithÂWindow
interface. Many Windows Runtime objects which infer the CoreÂWindow
from the current thread support the IInitializeÂWithÂWindow
interface to allow a Win32 desktop app to specify an explicit window.
Make the following changes to the program:
#include <shobjidl.h> #include <winrt/windows.storage.pickers.h> winrt::Windows::Foundation::IAsyncAction ShowFilePickerAsync(HWND hwnd) { auto picker = winrt::Windows::Storage::Pickers::FileOpenPicker(); picker.as<IInitializeWithWindow>()->Initialize(hwnd); picker.FileTypeFilter().Append(L".jpg"); auto file = co_await picker.PickSingleFileAsync(); }
This time, the File Open dialog opens because we explicitly provided a window handle to use as the owner.
The IInitializeÂWindowÂWindow
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 some time ago.
I actually might use this – the UWP File Picker is a lot nicer for any case involving cloud providers, and is potentially more secure for some cases.
is the as method specific to the picker (or some base class) or is it a c++ thing (ala. extension method)?
how is it diffetent from regular cast?
As you may know, the UWP API is based upon COM. The pickers themselves are implemented as a bunch of interfaces. All COM interfaces, even UWP interfaces, inherit from IUnknown (UWP interfaces inherit from IInspectable which inherits from IUnknown).
Now, the C++/WinRT library wraps this and names it after the logical class. But because this is a COM API then it wraps interfaces to the underlying object that implement this behaviour and these interfaces derive...
If you are trying this at home. The needed headers include:
#include <shobjidl_core.h>
#include <winrt/windows.storage.pickers.h>
And the library to link with:
runtimeobject.lib
More convenient is to link with the umbrella library
windowsapp.lib
.I inferred that pattern a few weeks ago when I was playing with the Pin to Start dialog. I wonder whether that pattern could be used in production, since MSDN doesn’t mention this pattern, nor does the documentation for FilePickers say a word on it.
For another thing, FilePickers are quite different from IFileDialog (contrary to the MSDN statement saying that desktop apps don’t need them as they already have IFileDialog and full access to...
I host all my Win32 IFileDialogs out-of-process so you not only get a dedicated UI thread for speed but can do cool stuff like automatically reopen the window if it hard crashes. Fortunately you can specify an out-of-process HWND parent and it will obey it, unlike any dialogs that have to do with the miserable IShellItem Recycle Bin. That tiny section of code needs review BTW. The Recycle Bin's implementation is such a hack, I...
This is interesting. This really helps for interoping with UWP.
I knew you could get the StorageFolder from GetFolderFromPathAsync and work from that, but knowing how to get the pickers to work really helps