"Invalid window handle" error when using FileOpenPicker from C++/WinRT without UWP

3

I am trying to use C++/WinRT to write something interesting. Having very little experience in Windows programming and no experience in C++/CX, I started out by trying sample program (OCR).

The sample program is about optical character recognition, I modified it to be face detector (console-based). It worked very well.

I want to convert getting file from command-line to file dialog, so I ported the following snippet from C#:

  FileOpenPicker picker = FileOpenPicker();
  picker.ViewMode(PickerViewMode::Thumbnail);
  picker.SuggestedStartLocation(PickerLocationId::PicturesLibrary);
  picker.FileTypeFilter().Append(L".jpg");
  picker.FileTypeFilter().Append(L".jpeg");
  picker.FileTypeFilter().Append(L".png");

  StorageFile file = co_await picker.PickSingleFileAsync();

No compile error, but when I run the program, I get this error message:

hresult_error: (0x80070578) Invalid window handle.

I think the error occurs because it is a console-based program (wmain), not wWinMain.

I tried to find a solution online, but they are all about UWP. Please provide a solution that does not involve UWP and must be able to compile from cl.exe directly.

Note:

According to UWP APIs callable from a classic desktop app, if an API has DualApiPartitionAttribute attribute, it will work in classic desktop app, otherwise it won't. For example, Geolocator has this attribute so it will work.

However, even though FaceDetector does not have this attribute it still works proven in my toy program.

Anything from Windows::UI definitely requires UWP (although there is https://aka.ms/windowsui/inwin32). FileOpenPicker does not have this attribute but it is not under Windows::UI, so there might be a chance it can be workaround.

Complete code:

#pragma comment(lib, "windowsapp")

#include <winrt/Windows.Storage.Pickers.h>
#include <winrt/Windows.Storage.Streams.h>
#include <winrt/Windows.Graphics.Imaging.h>
#include <winrt/Windows.Media.FaceAnalysis.h>

using namespace winrt;
using namespace std::chrono;

using namespace Windows::Foundation;
using namespace Windows::Storage;
using namespace Windows::Storage::Pickers;
using namespace Windows::Storage::Streams;
using namespace Windows::Graphics::Imaging;
using namespace Windows::Media::FaceAnalysis;

using Windows::Foundation::Collections::IVector;

IAsyncOperation<int> AsyncSample() {
  FileOpenPicker picker = FileOpenPicker();
  picker.ViewMode(PickerViewMode::Thumbnail);
  picker.SuggestedStartLocation(PickerLocationId::PicturesLibrary);
  picker.FileTypeFilter().Append(L".jpg");
  picker.FileTypeFilter().Append(L".jpeg");
  picker.FileTypeFilter().Append(L".png");

  StorageFile file = co_await picker.PickSingleFileAsync();
  //StorageFile file = co_await StorageFile::GetFileFromPathAsync(
  //    L"C:\\Users\\user\\Pictures\\20170318_202325.jpg");
  IRandomAccessStream stream = co_await file.OpenAsync(FileAccessMode::Read);

  BitmapDecoder decoder = co_await BitmapDecoder::CreateAsync(stream);
  SoftwareBitmap bitmap = co_await decoder.GetSoftwareBitmapAsync();

  FaceDetector detector = co_await FaceDetector::CreateAsync();

  SoftwareBitmap converted =
      SoftwareBitmap::Convert(bitmap, BitmapPixelFormat::Nv12);

  IVector<DetectedFace> result = co_await detector.DetectFacesAsync(converted);
  printf("Detection done\n");
  for (auto& face : result) {
    BitmapBounds box = face.FaceBox();
    printf("[%u %u %u %u]\n", box.X, box.Y, box.Width, box.Height);
  }
  printf("Printing done\n");

  return 0;
}

int wmain() {
  init_apartment();

  try {
    int res = AsyncSample().get();
    printf("%d\n", res);
  } catch (hresult_error& e) {
    printf("hresult_error: (0x%8X) %ls\n", e.code(), e.message().c_str());
  }

  return 0;
}
c++
visual-c++
windows-runtime
visual-studio-2017
asked on Stack Overflow Nov 8, 2017 by John London • edited Nov 8, 2017 by John London

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0