1.今回やること
・前回に作成したMFCWinRTThumbは仮表示させていました。
・今回はピクチャフォルダをサムネイル表示させます。以下のように。
2. UWP部分の変更
・UWP部分の変更を行います。
・基本はC++/WinRTでUWPその13やったことをそのままやります。
・何も書いていなければUWP部分のThumbViewに関わる部分の変更です。
2-1. マニフェストの変更
・「Package.appmanifest」をダブルクリックして開いて機能からピクチャライブラリにチェックを入れます。
2-2. thumbViewModelの作成
・前と同じように①StorageFile、②サムネイル画像、③ファイル名を保存するViewModelを作成します。
・ここもいつものように、「プロジェクト」→「モジュールの追加」→「Visual C++」から「View Model」を選び名前を「thumbViewModel」へ変更して「追加」します。
2-3. thumbViewModel.idl .h .cppの変更
・追加したViewModelのコードを変更します。以下のように(コピペで何も変更していません)。
namespace ThumbView
{
[Windows.UI.Xaml.Data.Bindable]
runtimeclass thumbViewModel
{
thumbViewModel();
thumbViewModel(Windows.Storage.StorageFile imagefile, Windows.UI.Xaml.Media.Imaging.BitmapImage thunbimage, String imagename);
Windows.Storage.StorageFile GetImageFile{ get; };
Windows.UI.Xaml.Media.Imaging.BitmapImage GetThumbImage{ get; };
String GetImageName{ get; };
}
}
#pragma once
#include "thumbViewModel.g.h"
namespace winrt::ThumbView::implementation
{
struct thumbViewModel : thumbViewModelT<thumbViewModel>
{
thumbViewModel() = default;
thumbViewModel(
Windows::Storage::StorageFile const& imagefile,
Windows::UI::Xaml::Media::Imaging::BitmapImage const& thumbimage,
hstring const& imagename
) :
imageFile(imagefile),
thumbImage(thumbimage),
imageName(imagename)
{}
Windows::Storage::StorageFile GetImageFile() const
{
return imageFile;
}
Windows::UI::Xaml::Media::Imaging::BitmapImage GetThumbImage() const
{
return thumbImage;
}
hstring GetImageName() const
{
return imageName;
}
private:
Windows::Storage::StorageFile imageFile{ nullptr };
Windows::UI::Xaml::Media::Imaging::BitmapImage thumbImage;
hstring imageName;
};
}
namespace winrt::ThumbView::factory_implementation
{
struct thumbViewModel : thumbViewModelT<thumbViewModel, implementation::thumbViewModel>
{
};
}
#include "pch.h"
#include "thumbViewModel.h"
#if __has_include("thumbViewModel.g.cpp")
#include "thumbViewModel.g.cpp"
#endif
namespace winrt::ThumbView::implementation
{
}
2-4. MainControl.xaml .idl .h .cppの変更
・ここも楽にコピペで行きたいところですが、いくつか注意点があります。
・C++/WinRTでUWPその13ではMainPage::OnNavigatedTo()をオーバーライドして起動時の処理(サムネイル画像の読み込み等)を記述しました。
・アプリの事前起動の処理に書いてある内容ですが、OnLaunched()をオーバーライドすると、事前起動の処理を記述できます。UWPアプリではApp.h/.cppでOnLaunched()をオーバーライドして、その中でrootFrame.Navigate()を呼んでいるので、MainPage::OnNavigatedTo()をオーバーライドすると起動時の処理として記述できました。以下のような感じで。
void App::OnLaunched(LaunchActivatedEventArgs const& e)
{
Frame rootFrame{ nullptr };
auto content = Window::Current().Content();
if (content)
{
rootFrame = content.try_as<Frame>();
}
if (rootFrame == nullptr)
{
rootFrame = Frame();
rootFrame.NavigationFailed({ this, &App::OnNavigationFailed });
if (e.PreviousExecutionState() == ApplicationExecutionState::Terminated)
{
}
if (e.PrelaunchActivated() == false)
{
if (rootFrame.Content() == nullptr)
{
// ここで呼んでます
rootFrame.Navigate(xaml_typename<thumb_pic_1::MainPage>(), box_value(e.Arguments()));
}
Window::Current().Content(rootFrame);
Window::Current().Activate();
}
}
else
{
if (e.PrelaunchActivated() == false)
{
if (rootFrame.Content() == nullptr)
{
// ここで呼んでます
rootFrame.Navigate(xaml_typename<thumb_pic_1::MainPage>(), box_value(e.Arguments()));
}
Window::Current().Activate();
}
}
}
・今回のUWP側のApp.cppは以下に書き換えました。
App.cpp(変更後)
#include "pch.h"
#include "App.h"
#include "App.g.cpp"
using namespace winrt;
using namespace Windows::UI::Xaml;
namespace winrt::ThumbView::implementation
{
App::App()
{
Initialize();
AddRef();
m_inner.as<::IUnknown>()->Release();
}
App::~App()
{
Close();
}
}
・ThumbViewではOnLaunched()をオーバーライドしていないので、MainControlでOnNavigatedTo()をオーバーライドしても起動時に呼ばれません。
・App::OnLaunched()とMainControl::OnNavigatedTo()の二つをオーバーライドするのも面倒なので、MainControlに追加する予定の
Windows::Foundation::Collections::IObservableVector<Windows::Foundation::IInspectable> thumbViewModelVecと
サムネイル関連の情報を取得するメンバ関数をstaticにして、App.cppのOnLaunched()から呼ぶようにしてしまいましょう。
・では以下にソースを。
・xamlはほぼ変更はありません。Classやlocal等細かいところが変わっているだけですね。
<UserControl
x:Class="ThumbView.MainControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:ThumbView"
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="1*" />
<RowDefinition Height="1*"/>
</Grid.RowDefinitions>
<ListView x:Name="list1" ItemsSource="{x:Bind ThumbViewModelVec}" Grid.Row="0">
<ListView.ItemTemplate>
<DataTemplate x:Name="singleLineTemplate" x:DataType="local:thumbViewModel">
<StackPanel Orientation="Horizontal" Height="160">
<Image Source="{x:Bind GetThumbImage}" Height="150" Width="150" VerticalAlignment="Center"/>
<TextBlock Text="{x:Bind Path=GetImageName}" VerticalAlignment="Center" Style="{ThemeResource BaseTextBlockStyle}" Foreground="{ThemeResource SystemControlPageTextBaseHighBrush}" Margin="12,0,0,0"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<GridView ItemsSource="{x:Bind ThumbViewModelVec}" Grid.Row="1" >
<GridView.ItemTemplate>
<DataTemplate x:Name="ImageTextDataTemplate" x:DataType="local:thumbViewModel">
<StackPanel Height="200" Width="180" Margin="12">
<Image Source="{x:Bind GetThumbImage}" Height="150" Width="150" Stretch="UniformToFill"/>
<StackPanel Margin="0,12">
<TextBlock Text="{x:Bind Path=GetImageName}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid MaximumRowsOrColumns="10" Orientation="Horizontal"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
</Grid>
</UserControl>
・ここもstaticだからといってほぼ変わりません。
import "thumbViewModel.idl";
namespace ThumbView
{
[default_interface]
runtimeclass MainControl : Windows.UI.Xaml.Controls.UserControl
{
MainControl();
Windows.Foundation.Collections.IObservableVector<IInspectable> ThumbViewModelVec{ get; };
}
}
・宣言でstaticになっているでしょ。
#pragma once
#include "MainControl.g.h"
#include "thumbViewModel.h"
namespace winrt::ThumbView::implementation
{
struct MainControl : MainControlT<MainControl>
{
MainControl();
Windows::Foundation::Collections::IObservableVector<Windows::Foundation::IInspectable> ThumbViewModelVec() const
{
return thumbViewModelVec;
}
//ここで、StorageFile、サムネイル画像、ファイル名を集めるよ static
static Windows::Foundation::IAsyncAction AppendViewModelAsync();
//サムネイル画像を取得するよ static
static Windows::Foundation::IAsyncOperation<Windows::UI::Xaml::Media::Imaging::BitmapImage> GetThumbnailAsync(Windows::Storage::StorageFile m_imageFile);
private:
//サムネイル等の保存用だよ static
static Windows::Foundation::Collections::IObservableVector<Windows::Foundation::IInspectable> thumbViewModelVec;
};
}
namespace winrt::ThumbView::factory_implementation
{
struct MainControl : MainControlT<MainControl, implementation::MainControl>
{
};
}
・staticにしたIObservableVectorの初期化を追加しただけですね。
#include "pch.h"
#include "MainControl.h"
#if __has_include("MainControl.g.cpp")
#include "MainControl.g.cpp"
#endif
#include <winrt/Windows.UI.Xaml.Media.Imaging.h>
#include <winrt/Windows.Storage.Search.h>
using namespace winrt;
using namespace Windows::UI::Xaml;
namespace winrt::ThumbView::implementation
{
//staticなので初期化を追加
Windows::Foundation::Collections::IObservableVector<Windows::Foundation::IInspectable> MainControl::thumbViewModelVec{ nullptr };
MainControl::MainControl()
{
thumbViewModelVec = winrt::single_threaded_observable_vector<IInspectable>();
InitializeComponent();
}
Windows::Foundation::IAsyncAction MainControl::AppendViewModelAsync()
{
//サーチするのは「jpg」「png」「gif」
Windows::Storage::Search::QueryOptions searchoptions{};
searchoptions.FolderDepth(Windows::Storage::Search::FolderDepth::Deep);
searchoptions.FileTypeFilter().Append(L".jpg");
searchoptions.FileTypeFilter().Append(L".png");
searchoptions.FileTypeFilter().Append(L".gif");
//ピクチャーフォルダをサーチ
Windows::Storage::StorageFolder picturesfolder = Windows::Storage::KnownFolders::PicturesLibrary();
//上記の条件に合うのを探す
auto searchresult = picturesfolder.CreateFileQueryWithOptions(searchoptions);
auto imagefiles = co_await searchresult.GetFilesAsync();
if (thumbViewModelVec.Size() != 0)
co_return;
//StorageFileからサムネイル画像とファイル名を取得して、ThumbViewModelを作成し、ThumbViewModelVecへAppend(追加)
for (auto&& file : imagefiles)
{
if (file.Provider().Id() == L"computer")
{
auto thumbimage = co_await GetThumbnailAsync(file);
auto thumbview = winrt::make<thumbViewModel>(file, thumbimage, file.DisplayName());
thumbViewModelVec.Append(thumbview);
}
}
}
Windows::Foundation::IAsyncOperation<Windows::UI::Xaml::Media::Imaging::BitmapImage> MainControl::GetThumbnailAsync(Windows::Storage::StorageFile imagefile)
{
auto thumbnail = co_await imagefile.GetThumbnailAsync(Windows::Storage::FileProperties::ThumbnailMode::PicturesView);
Windows::UI::Xaml::Media::Imaging::BitmapImage thumbnailimage{};
thumbnailimage.SetSource(thumbnail);
thumbnail.Close();
co_return thumbnailimage;
}
}
2-5. App.h .cppの変更
・というわけで、void OnLaunched()を追加します。
#pragma once
#include "App.g.h"
#include "App.base.h"
namespace winrt::ThumbView::implementation
{
class App : public AppT2<App>
{
public:
App();
~App();
//ここ追加
void OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs const&);
};
}
namespace winrt::ThumbView::factory_implementation
{
class App : public AppT<App, implementation::App>
{
};
}
・OnLaunched()でMainControl::AppendViewModelAsync()を呼び出すよ~~
#include "pch.h"
#include "App.h"
#include "App.g.cpp"
#include "MainControl.h"
using namespace winrt;
using namespace Windows::UI::Xaml;
using namespace ThumbView::implementation;
namespace winrt::ThumbView::implementation
{
App::App()
{
Initialize();
AddRef();
m_inner.as<::IUnknown>()->Release();
}
App::~App()
{
Close();
}
void App::OnLaunched(Windows::ApplicationModel::Activation::LaunchActivatedEventArgs const& e)
{
//呼び出すよ~~
MainControl::AppendViewModelAsync();
}
}
・ビルド~実行してエラーが出なければOK!
・こんな感じでピクチャフォルダをサムネイル表示してくれるはず。
・後はメモリーリークが見つかった!と言われるので、後始末をして下さい。後始末は宿題です!