#1. 今回やること
・MFCアプリからWinRTのIAsyncAction()とMessageDialogを呼び出すことをやります。
・非同期関数を使用できて、ダイアログだけでもWinRTを利用できれば、なんとモダンな!って感じがしませんか?
・UWPのコントロールを表示させるわけではないので、ダイアログベースで作成します。
・デスクトップ アプリで Windows ランタイム API を呼び出す、デスクトップ アプリでサポートされていない Windows ランタイム APIに書かれているような内容をやります。
以下のことをやっていきます。
①重複するマクロの削除と、必要なヘッダの読み込み
②プロパティーの変更(C++17への変更と/awaitの追加)
③コードの追加
#2. プロジェクトの作成
・VS2019を立ち上げて、「新しいプロジェクトの作成」→「MFCアプリ」で次へ
・プロジェクト名は「MFCWinRTDlg」としました。そして作成(「_」や「-」がプロジェクト名にあるとエラーが出るので注意)
・アプリケーションの種類は「ダイアログベース」にして完了。
・確認のため何もせず実行すると、以下のダイアログベースのアプリが立ち上がります。
#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」は以下のように変更しました。
#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. コードの追加
・ここまで来たら、後はコードを追加してメッセージダイアログを表示させるだけです。
・リソースビューでボタンを2個追加します。
・右クリックからまずは「Button1」のイベントハンドラを追加します。
・MFCWinRTDlgDlg.hを開き、「afx_msg void OnBnClickedButton1()」の後に「winrt::Windows::Foundation::IAsyncAction AsyncButton1()」を追加します。winrt/Windows.Foundation.hを読み込むだけで非同期関数は使えるので追加するだけです。
・そして、cppファイルに定義を追加します。
・IInitializeWithWindow を使用するクラスを参考に「MFCWinRTDlgDlg.cpp」を以下のように変更しました。
・IInitializeWithWindow interfaceにも書かれていますが、各種pickerやメッセージダイアログはIInitializeWithWindowで初期化すれば使えます。なので、以下のように、宣言して、初期化して、表示しています。
//ここまで略
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();
}
・ビルドすると以下のようにメッセージダイアログが表示されます。
・Button2では5秒後にメッセージダイアログを表示させるようにしてみます。以前やったようにスレッドプールを使用して。
//ここまで略
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)をやります。
目次へ