4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

4-1-2. 実装しよう(①~②まで)

Last updated at Posted at 2024-08-14

1. まずは新規作成

・Visual Studio 2022の「新しいプロジェクトの作成」→「空のアプリ、パッケージ化(デスクトップのWinUI 3)」を選んで新規作成してください。
1-1 - コピー.png

・名前は「PicViewer」としておきます。

2. ①インストールしなくても、起動できるようにする。

2-1. 「.vcxproj」を編集しよう

・基本的にはMSのページの7と8に書かれていることをやります。

・一度VS2022を終了し、「.vcxproj」を適当なテキストエディタで開きます。今回は「PicViewer.vcxproj」をメモ帳で開きます。

・「<PropertyGroup Label="Globals">」タグを探してください。その中からさらに<AppxPackage>タグを探してください。その値は最初「true」になっているので「false」へ変更し、その上に「<WindowsPackageType>None</WindowsPackageType>を追加します。以下に画像で

変更前
2-10.png

変更後
2-11.png


・ここまで出来たら、一旦念のためリリースモードでビルドし実行してください。
・x64\Releaseの中にある「PicViewer」フォルダを適当なフォルダへコピーし、以下の3ファイル以外はすべて削除。それでも実行できるはずです。
 ●Microsoft.WindowsAppRuntime.Bootstrap.dll
 ●PicViewer.exe
 ●resources.pri
・つまり、この3ファイルさえあればどこに置いても実行可能となります(別のライブラリ等が必要な場合は除く)
・これで①は終了です。後はいらないボタンとプロパティを削除します。

2-2. 一度WinUI3とC++/WinRTの違いを見てみよう。

2-2-1. ファイル構成

・大きなところではC++/WinRTは「MainPage.xaml」だったものが、WinUI3では「MainWindow.xaml」へ変更になっています。
・C++/WinRT
2-20.png

・WinUI3
2-21.png

2-2-2. Main.cpp

・UIへアクセスするnamespaceがC++/WinRTは「winrt::Windows~」だったものが、WinUI3では「winrt::Microsoft~」へ変更になっています。違うところでも書いた気がするけど「Microsoft::~」というnamespaceのライブラリもあるので、それらを使用するときはバッティングしてコンパイルエラーとなります。
・そのときは「using namespace winrt;」を削除して「winrt::Microsoft::~」で書いてください。そんなアホなことにならないようにnamespaceがあるはずなんだけどorz
・UI関連以外は「winrt::Windows~」のnamespaceにあるものが多く、UIに渡すときに間違えて「Windows~」のまま渡してコンパイルエラーとなるときもあるのでかなり鬱陶しいです。もっとちゃんと作らないとますます使われ無くなるぞMS!

MainPage.cpp(C++/WinRT)
#include "pch.h"
#include "MainPage.h"
#include "MainPage.g.cpp"

using namespace winrt;
using namespace Windows::UI::Xaml;

namespace winrt::Test0001::implementation
{
}

MainWindow.xaml.cpp(WinUI3)
#include "pch.h"
#include "MainWindow.xaml.h"
#if __has_include("MainWindow.g.cpp")
#include "MainWindow.g.cpp"
#endif

using namespace winrt;
using namespace Microsoft::UI::Xaml;


namespace winrt::PicViewer::implementation
{
}


3. ②メニューから「File→Exit」でアプリを終了するか聞いてくるダイアログを表示する。

3-1 メニューバーを配置

・メニューバーをどうやって配置するのか、WinUI 3 Galleryを見て確認してみます(UI関連は参考になるのでwinui3.0を使うのならインストールした方が良いですよ)。
2-22.png
見た感じそんなに難しくなさそうなので、さっくりMainWindowを変更しましょう。

・メニューを追加して「File→Open」と「File→Exit」も追加しました。
・それぞれ、クリックと「Ctrl+O」と「Ctrl+E」のショートカットも作成しています。

MainWindow.xaml

<?xml version="1.0" encoding="utf-8"?>
<Window
    x:Class="PicViewer.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:PicViewer"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid RequestedTheme="Default" >

        <Grid.RowDefinitions>
            <RowDefinition Height="auto" />

        </Grid.RowDefinitions>
        <MenuBar Background="LightGray" BorderBrush="Black" BorderThickness="1" CornerRadius="5">
            <MenuBarItem Title="File">
                
                <MenuFlyoutItem Text="Open" Click="Open_Click">
                    <MenuFlyoutItem.KeyboardAccelerators>
                        <KeyboardAccelerator Modifiers="Control" Key="O"/>
                    </MenuFlyoutItem.KeyboardAccelerators>
                </MenuFlyoutItem>

                <MenuFlyoutItem Text="Exit" Click="Exit_Click">
                    <MenuFlyoutItem.KeyboardAccelerators>
                        <KeyboardAccelerator Modifiers="Control" Key="E"/>
                    </MenuFlyoutItem.KeyboardAccelerators>
                </MenuFlyoutItem>
                
            </MenuBarItem>
        </MenuBar>

        
    </Grid>
</Window>




・MainWindow.xaml.hは各メンバ関数の定義と、コンストラクタでタイトルを変更します。変更しないと「WinUI Desktop」ってデフォルトのファイル名のままになってしまいますから。
・Open_Clickはまだ中身を追加しないのでvoidのまま、Exit_ClickはIAsyncActionへと変更します。
MSのページに書いてありますが、メッセージダイアログやピッカーを使用する場合HWNDを取得する必要があります。このため、getHwnd()も追加しました。

MainWindow.xaml.h

#pragma once

#include "MainWindow.g.h"

namespace winrt::PicViewer::implementation
{
    struct MainWindow : MainWindowT<MainWindow>
    {
        MainWindow()
        {
            //タイトル名の変更        
            this->Title(L"PicViewer");
        }

        //HWND取得関数
        HWND getHwnd();

        //Openがクリックされたよ!
        void Open_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
        
        //Exitがクリックされたよ! -ここは非同期へ変更       
        winrt::Windows::Foundation::IAsyncAction Exit_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e);
    };
}

namespace winrt::PicViewer::factory_implementation
{
    struct MainWindow : MainWindowT<MainWindow, implementation::MainWindow>
    {
    };
}



・mainWindow.xaml.cppでgetHwndとExit_Clickの実装を行います。Exitをクリックすると「Yes」「No」「Cancel」の三つのボタンを表示するContentDialogを表示します。
・「Yes」はそのままアプリを終了。
・「No」はMessageDialogを表示して続行。
・「Cancel」は何も表示せず続行。
・各種ダイアログを表示したいだけだったけど、なんでContentDialogとMessageDialogで諸々違うの...

MainWindow.xaml.cpp

#include "pch.h"
#include "MainWindow.xaml.h"
#if __has_include("MainWindow.g.cpp")
#include "MainWindow.g.cpp"
#endif

using namespace winrt;
using namespace Microsoft::UI::Xaml;

//::IWindowNativeと::IInitializeWithWindowを使うのにmicrosoft.ui.xaml.window.h、Shobjidl.hが必要
//MessageDialogを使うのにWindows.UI.Popups.hが必要
#include <microsoft.ui.xaml.window.h>
#include <winrt/Windows.UI.Popups.h>
#include <Shobjidl.h>


namespace winrt::PicViewer::implementation
{
	
}



HWND winrt::PicViewer::implementation::MainWindow::getHwnd()
{
	auto windowNative{ this->m_inner.as<::IWindowNative>() };
	HWND hWnd{ 0 };
	windowNative->get_WindowHandle(&hWnd);

	return hWnd;
}

void winrt::PicViewer::implementation::MainWindow::Open_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e)
{
}


winrt::Windows::Foundation::IAsyncAction winrt::PicViewer::implementation::MainWindow::Exit_Click(winrt::Windows::Foundation::IInspectable const& sender, winrt::Microsoft::UI::Xaml::RoutedEventArgs const& e)
{
	//ContentDialogはwinrt::Microsoft...となる。必要なのはXamlRoot
	Microsoft::UI::Xaml::Controls::ContentDialog isenddialog{};
	isenddialog.XamlRoot(this->Content().XamlRoot());
	isenddialog.Title(box_value(L"Do you want to close?"));
	isenddialog.PrimaryButtonText(L"Yes");
	isenddialog.SecondaryButtonText(L"No");
	isenddialog.CloseButtonText(L"Cancel");

	auto result = co_await isenddialog.ShowAsync();
 
	if (result == Microsoft::UI::Xaml::Controls::ContentDialogResult::Primary)
	{
 		//アプリ終了
		Application::Current().Exit();
	}
	else if (result == Microsoft::UI::Xaml::Controls::ContentDialogResult::Secondary)
	{
		//MessageDialogはwinrt::Windows...となる。必要なのはHWND
		auto showdialog{ Windows::UI::Popups::MessageDialog(L"Continue without closing this application") };
		showdialog.as<::IInitializeWithWindow>()->Initialize(getHwnd());

		co_await showdialog.ShowAsync();
	}
}



・これでメニューの追加、アプリの終了処理まで終了しました。
・実行すると以下のようになります。
2-23.png

次へ

目次へ

4
5
0

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
4
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?