1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

MFCでもWinRTその1. メッセージダイアログとAsync/co_wait

Last updated at Posted at 2022-01-09

#1. 今回やること
・MFCアプリからWinRTのIAsyncAction()とMessageDialogを呼び出すことをやります。
・非同期関数を使用できて、ダイアログだけでもWinRTを利用できれば、なんとモダンな!って感じがしませんか?
・UWPのコントロールを表示させるわけではないので、ダイアログベースで作成します。
デスクトップ アプリで Windows ランタイム API を呼び出すデスクトップ アプリでサポートされていない Windows ランタイム APIに書かれているような内容をやります。

以下のことをやっていきます。
①重複するマクロの削除と、必要なヘッダの読み込み
②プロパティーの変更(C++17への変更と/awaitの追加)
③コードの追加

#2. プロジェクトの作成
・VS2019を立ち上げて、「新しいプロジェクトの作成」→「MFCアプリ」で次へ
1.png

・プロジェクト名は「MFCWinRTDlg」としました。そして作成(「_」や「-」がプロジェクト名にあるとエラーが出るので注意)
・アプリケーションの種類は「ダイアログベース」にして完了。
2.png

・確認のため何もせず実行すると、以下のダイアログベースのアプリが立ち上がります。
3.png


#3. 重複するマクロの削除と、必要なヘッダの読み込み
・ソリューションエクスプローラーから「pch.h」を読み込んで、「GetCurrentTime」と「TRY」を#undef。
・必要なヘッダを読み込みます。必要なヘッダは以下の4種類
 ①winrt/base.h:これは必ず必要
 ②winrt/Windows.Foundation.h:IAsyncに必要
 ③winrt/Windows.UI.Popups.h:ダイアログの表示に必要
 ④winrt/Windows.System.Threading.Core.h:スレッドプールも使用するので必要
・というわけで「pch.h」は以下のように変更しました。

4.png

pch.h(変更後)

#ifndef PCH_H
#define PCH_H

// プリコンパイルするヘッダーをここに追加します
#include "framework.h"

//名前がバッティングするのでundef
#undef GetCurrentTime
#undef TRY

//必要なヘッダの読み込み
#include <winrt/base.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.UI.Popups.h>
#include <winrt/Windows.System.Threading.Core.h>

#endif //PCH_H

#4. プロパティの変更
・「プロジェクト」→「MFCWinRTDlgのプロパティ」より以下の変更を行います
・「全般」からC++言語標準を「ISO C++17標準」へ変更
5.png

・「C/C++」→「コマンドライン」へ/awaitの追加
6.png

#5. コードの追加
・ここまで来たら、後はコードを追加してメッセージダイアログを表示させるだけです。
・リソースビューでボタンを2個追加します。
・右クリックからまずは「Button1」のイベントハンドラを追加します。
7.png

・MFCWinRTDlgDlg.hを開き、「afx_msg void OnBnClickedButton1()」の後に「winrt::Windows::Foundation::IAsyncAction AsyncButton1()」を追加します。winrt/Windows.Foundation.hを読み込むだけで非同期関数は使えるので追加するだけです。
・そして、cppファイルに定義を追加します。
8.png

IInitializeWithWindow を使用するクラスを参考に「MFCWinRTDlgDlg.cpp」を以下のように変更しました。
IInitializeWithWindow interfaceにも書かれていますが、各種pickerやメッセージダイアログはIInitializeWithWindowで初期化すれば使えます。なので、以下のように、宣言して、初期化して、表示しています。

MFCWinRTDlgDlg.cpp(変更後)

//ここまで略
void CMFCWinRTDlgDlg::OnBnClickedButton1()
{
	AsyncButton1();
}

winrt::Windows::Foundation::IAsyncAction CMFCWinRTDlgDlg::AsyncButton1()
{
	auto msgdlg = winrt::Windows::UI::Popups::MessageDialog(L"Hello MFC WinRT");
	msgdlg.as<IInitializeWithWindow>()->Initialize(m_hWnd);
	msgdlg.Content(L"Hello MFC WinRT");
	co_await msgdlg.ShowAsync();
}

・ビルドすると以下のようにメッセージダイアログが表示されます。
9.png






・Button2では5秒後にメッセージダイアログを表示させるようにしてみます。以前やったようにスレッドプールを使用して。

MFCWinRTDlgDlg.cpp(変更後)

//ここまで略
void CMFCWinRTDlgDlg::OnBnClickedButton2()
{
	AsyncButton2();
}

winrt::Windows::Foundation::IAsyncAction CMFCWinRTDlgDlg::AsyncButton2()
{
	co_await winrt::Windows::System::Threading::ThreadPool::RunAsync([&](winrt::Windows::Foundation::IAsyncAction const& workItem)
		{
			Sleep(5000);
		});

	auto msgdlg = winrt::Windows::UI::Popups::MessageDialog(L"Hello MFC WinRT wait 5S");
	msgdlg.as<IInitializeWithWindow>()->Initialize(m_hWnd);
	msgdlg.Content(L"Hello MFC WinRT wait 5S");
	co_await msgdlg.ShowAsync();
}

・どうです。かなり簡単にMFCからスレッドプールを使用した非同期関数が利用できるでしょ?
・PPL等でも利用可能ですが、お手軽に利用可能な手段が増えるのはとてもいいものです。

#6. まとめ
・今回はMFCアプリからWinRTの非同期関数とメッセージダイアログを使用してみました。
・簡単にUWP風味が味わえるでしょう?

githubはここに

やっぱり変更してWinRT APIの使用(OCR)をやります。

目次

1
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?