【问题标题】:"Invalid window handle" error when using FileOpenPicker from C++/WinRT without UWP在没有 UWP 的情况下从 C++/WinRT 使用 FileOpenPicker 时出现“无效的窗口句柄”错误
【发布时间】:2022-04-02 07:22:10
【问题描述】:

我正在尝试使用C++/WinRT 来写一些有趣的东西。我在 Windows 编程方面的经验很少,也没有 C++/CX 方面的经验,所以我开始尝试sample program (OCR)

示例程序是关于光学字符识别的,我将其修改为面部检测器(基于控制台)。效果很好。

我想将获取文件从命令行转换为文件对话框,所以我移植了以下 sn-p 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();

没有编译错误,但是当我运行程序时,我收到以下错误消息:

hresult_error: (0x80070578) Invalid window handle.

我认为发生错误是因为它是基于控制台的程序 (wmain),而不是 wWinMain。

我试图在网上找到解决方案,但都是关于 UWP 的。请提供不涉及UWP且必须能够直接从cl.exe编译的解决方案。

注意

根据UWP APIs callable from a classic desktop app,如果API 具有DualApiPartitionAttribute 属性,它将在经典桌面应用程序中工作,否则不会。例如,Geolocator 有这个属性,所以它会起作用。

然而,即使FaceDetector 确实没有 有这个属性,它仍然在我的玩具程序中得到证明。

来自Windows::UI 的任何东西都肯定需要UWP(尽管有https://aka.ms/windowsui/inwin32)。 FileOpenPicker 没有这个属性,但它不在Windows::UI 下,所以它可能是一种解决方法。

完整代码:

#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;
}

【问题讨论】:

  • 也许它需要应用程序视图才能正常工作,就像大多数处理 UI 的 UWP API 一样?
  • FileOpenPicker 不在Windows::UI 之下,所以我希望我可以避免应用程序视图。请参阅上面我编辑的注释。
  • 非常感谢,现在可以使用了! (哇,传奇的 Raymond Chen!)
  • 嘿,我如何使用 c# 实现相同的效果。我在做这件事时遇到了困难。我添加的代码行是 picker.As&lt;Windows.UI.Core.IInitializeWithCoreWindow&gt;().Initialize(CoreWindow);.

标签: c++ visual-c++ windows-runtime visual-studio-2017


【解决方案1】:

所以这是需要的修改:

IAsyncOperation<int> AsyncSample() {
  HWND hwnd = GetConsoleWindow(); // #include <windows.h>

  FileOpenPicker picker = FileOpenPicker();
  picker.as<IInitializeWithWindow>()->Initialize(hwnd);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多