UWP 사진 편집기 샘플 앱(C++/WinRT)의 Windows 앱 SDK 마이그레이션

이 항목은 C++/WinRT UWP Photo Editor 샘플 앱을 가져와 Windows 앱 SDK로 마이그레이션하는 사례 연구입니다.

Important

마이그레이션 프로세스에 접근하기 위한 고려 사항 및 전략, 마이그레이션을 위한 개발 환경 설정 방법은 전체 마이그레이션 전략을 참조하세요.

Windows 앱 SDK용 도구 설치

개발 컴퓨터를 설정하려면 Windows 앱 SDK용 도구 설치를 참조하세요.

Important

Windows 앱 SDK 릴리스 채널 항목과 함께 릴리스 정보 항목을 찾을 수 있습니다. 각 채널에 대한 릴리스 정보가 있습니다. 해당 릴리스 정보에서 제한 사항 및 알려진 문제를 확인합니다. 이러한 사항은 이 사례 연구를 따르거나 마이그레이션된 앱을 실행한 결과에 영향을 미칠 수 있기 때문입니다.

새 프로젝트 만들기

  • Visual Studio에서 Blank App, Packaged(데스크톱의 WinUI 3) 프로젝트 템플릿에서 새 C++/WinRT 프로젝트를 만듭니다. 프로젝트 이름을 PhotoEditor로 지정하고 같은 디렉터리에 솔루션 및 프로젝트 배치를 선택 취소합니다. 클라이언트 운영 체제의 최신 릴리스(미리 보기 아님)를 대상으로 지정할 수 있습니다.

참고 항목

샘플 프로젝트(해당 리포지토리에서 복제한 프로젝트)의 UWP 버전을 원본 솔루션/프로젝트로 참조할 예정입니다. Windows 앱 SDK 버전을 대상 솔루션/프로젝트라고 합니다.

코드를 마이그레이션하는 순서

MainPage는 앱에서 중요하고 눈에 띄는 부분입니다. 그러나 마이그레이션을 시작한다면 MainPageDetailPage 보기에 종속된다는 것을 곧 알게 될 것입니다. DetailPage에는 Photo 모델에 대한 종속성이 있습니다. 따라서 이 연습에서는 이 접근 방식을 사용합니다.

  • 자산 파일을 복사하는 것으로 시작할 예정입니다.
  • 그런 다음, Photo 모델을 마이그레이션합니다.
  • 다음으로 App 클래스를 마이그레이션할 것입니다(DetailPageMainPage가 종속되는 일부 구성원이 클래스에 추가되어야 하기 때문).
  • 그런 다음, 먼저 DetailPage부터 시작하여 보기 마이그레이션을 시작합니다.
  • MainPage 보기를 마이그레이션하는 것으로 마무리할 예정입니다.

전체 소스 코드 파일을 복사합니다.

이 연습에서는 파일 탐색기를 사용하여 소스 코드 파일을 복사합니다. 파일 콘텐츠를 복사하려는 경우 이 항목(Photo에 대해 이를 수행하는 방법의 예)의 끝부분에 있는 부록: Photo 모델 파일의 콘텐츠 복사 섹션에서 예제를 참조하세요.(그런 다음, 프로젝트의 다른 유형에 유사한 절차를 적용할 수 있음). 하지만 이 옵션에는 훨씬 더 많은 단계가 있습니다.

자산 파일 복사

  1. 소스 프로젝트의 복제본에서 파일 탐색기에서 Windows-appsample-photo-editor>PhotoEditor>Assets 폴더를 찾습니다. 이 폴더에는 8개의 자산 파일이 있습니다. 이 8개 파일을 선택하고 클립보드에 복사합니다.

  2. 또한 파일 탐색기에서 만든 대상 프로젝트의 해당 폴더를 찾습니다. 해당 폴더의 경로는 PhotoEditor>PhotoEditor>Assets입니다. 해당 폴더에 방금 복사한 자산 파일을 붙여넣고 대상에 이미 있는 7개의 파일을 바꾸라는 메시지를 수락합니다.

  3. Visual Studio의 대상 프로젝트에 있는 솔루션 탐색기에서 Assets 폴더를 확장합니다. 방금 붙여넣은 기존 bg1.png 자산 파일을 해당 폴더에 추가합니다. 자산 파일 위에 마우스 포인터를 놓을 수 있습니다. 각각에 대해 썸네일 미리 보기가 나타나 자산 파일을 올바르게 교체/추가했는지 확인합니다.

사진 모델 마이그레이션

Photo은 사진을 나타내는 런타임 클래스입니다. 이는 모델입니다(모델, 보기 및 보기 모델의 의미에서).

사진 소스 코드 파일 복사

  1. 소스 프로젝트의 복제본에서 파일 탐색기에서 Windows-appsample-photo-editor>PhotoEditor 폴더를 찾습니다. 해당 폴더에서 3개의 소스 코드 파일 Photo.idl, Photo.hPhoto.cpp을 찾을 수 있습니다. 이러한 파일은 Photo 런타임 클래스를 함께 구현합니다. 이 3개 파일을 선택하고 클립보드에 복사합니다.

  2. Visual Studio에서 대상 프로젝트 노드를 마우스 오른쪽 단추로 클릭하고 파일 탐색기에서 폴더 열기를 클릭합니다. 그러면 파일 탐색기에서 대상 프로젝트 폴더가 열립니다. 방금 복사한 3개의 파일을 해당 폴더에 붙여넣습니다.

  3. 대상 프로젝트 노드를 선택한 상태로 솔루션 탐색기로 돌아가서 모든 파일 표시가 켜져 있는지 확인합니다. 방금 붙여넣은 3개의 파일을 마우스 오른쪽 단추로 클릭하고 프로젝트에 포함을 클릭합니다. 모든 파일 표시를 끕니다.

  4. 소스 프로젝트의 솔루션 탐색기에서 Photo.h.cppPhoto.idl 아래에 중첩되어 여기에서 생성되었음을 나타냅니다. 이 배열이 마음에 들면 \PhotoEditor\PhotoEditor\PhotoEditor\PhotoEditor.vcxproj를 수동으로 편집하여 대상 프로젝트에서 동일한 작업을 수행할 수 있습니다(먼저 Visual Studio에서 모두 저장해야 함). 다음을 찾습니다:

    <ClInclude Include="Photo.h" />
    

    그리고 이것을 다음과 같이 바꿉니다.

    <ClInclude Include="Photo.h">
      <DependentUpon>Photo.idl</DependentUpon>
    </ClInclude>
    

    Photo.cpp에 대해 이를 반복하고 프로젝트 파일을 저장하고 닫습니다. 포커스를 Visual Studio로 다시 설정하면 다시 로드를 클릭합니다.

사진 소스 코드 마이그레이션

  1. Photo.idl에서 네임스페이스 이름 Windows.UI.Xaml(UWP XAML의 네임스페이스)를 검색하고 이를 Microsoft.UI.Xaml(WinUI XAML의 네임스페이스)으로 변경합니다.

참고 항목

UWP API를 Windows 앱 SDK에 매핑 항목에서는 UWP API를 해당하는 Windows 앱 SDK에 매핑하는 방법을 제공합니다. 위에서 변경한 내용은 마이그레이션 프로세스 중에 필요한 네임스페이스 이름 변경의 예입니다.

  1. Photo.cpp에서 #include "Photo.h" 바로 뒤에 있는 기존 포함 지시문에 #include "Photo.g.cpp"를 추가합니다. 이는 UWP와 Windows 앱 SDK 프로젝트 간에 알아야 할 폴더 및 파일 이름 차이(C++/WinRT) 중 하나입니다.

  2. 방금 복사하여 붙여넣은 파일의 모든 소스 코드 콘텐츠에서 다음 찾기/바꾸기(대소문자 및 전체 단어)를 만듭니다.

    • Windows::UI::Xaml =>Microsoft::UI::Xaml
  3. 소스 프로젝트의 pch.h에서 다음 포함 항목을 복사하여 대상 프로젝트의 pch.h에 붙여넣습니다. 이것은 소스 프로젝트에 포함된 헤더 파일의 하위 집합입니다. 이것들은 지금까지 마이그레이션한 코드를 지원하는 데 필요한 헤더일 뿐입니다.

    #include <winrt/Microsoft.UI.Xaml.Media.Imaging.h>
    #include <winrt/Windows.Storage.h>
    #include <winrt/Windows.Storage.FileProperties.h>
    #include <winrt/Windows.Storage.Streams.h>
    
  4. 이제 대상 솔루션을 빌드할 수 있는지 확인합니다(아직 실행하지는 않음).

App 클래스 마이그레이션

대상 프로젝트의 App.idlApp.xaml를 변경할 필요가 없습니다. 그러나 App 클래스에 일부 새 멤버를 추가하려면 App.xaml.h 및 App.xaml.cpp을 수정해야 합니다. 각 섹션 다음에 빌드할 수 있는 방식으로 수행할 것입니다(App::OnLaunched에 대한 마지막 섹션 제외).

주 창 개체를 사용할 수 있도록 만들기

이 단계에서는 Windows.UI.Xaml.Window.Current를 App.Window로 변경에 설명된 대로 변경합니다.

대상 프로젝트에서 은 주 창 개체를 프라이빗 데이터 멤버인 window에 저장합니다. 나중에 마이그레이션 프로세스에서(소스 프로젝트의 Window.Current 사용을 마이그레이션할 때) 해당 window 데이터 멤버가 정적인 경우 편리하며, 접근자 기능을 통해서도 사용할 수 있습니다. 따라서 이 사항을 다음에 변경하겠습니다.

  • window를 정적으로 만들고 있으므로 코드가 현재 사용 중인 기본 멤버 이니셜라이저를 통하지 않고 App.xaml.cpp에서 초기화해야 합니다. 다음은 App.xaml.hApp.xaml.cpp의 변경 내용입니다.

    // App.xaml.h
    ...
    struct App : AppT<App>
    {
         ...
         static winrt::Microsoft::UI::Xaml::Window Window(){ return window; };
    
    private:
         static winrt::Microsoft::UI::Xaml::Window window;
    };
    ...
    
    // App.xaml.cpp
    ...
    winrt::Microsoft::UI::Xaml::Window App::window{ nullptr };
    ...
    

App::OnNavigationFailed

사진 편집기 샘플 앱은 탐색 논리를 사용하여 MainPageDetailPage 사이를 이동합니다. 탐색이 필요한 Windows 앱 SDK 앱(및 그렇지 않은 앱)에 대한 자세한 내용은 페이지 탐색을 구현해야 하나요?를 참조하세요.

따라서 다음 몇 섹션에서 마이그레이션할 멤버는 모두 앱 내 탐색을 지원하기 위해 존재합니다.

  1. 먼저 OnNavigationFailed 이벤트 처리기를 마이그레이션해 보겠습니다. 소스 프로젝트에서 해당 멤버 함수의 선언과 정의를 복사하여 대상 프로젝트(App.xaml.hApp.xaml.cpp)에 붙여넣습니다.

  2. App.xaml.h에 붙여넣은 코드에서 Windows::UI::XamlMicrosoft::UI::Xaml으로 변경합니다.

App::CreateRootFrame

  1. 소스 프로젝트에는 App::CreateRootFrame이라는 도우미 함수가 포함되어 있습니다. 소스 프로젝트에서 해당 도우미 함수의 선언과 정의를 복사하여 대상 프로젝트(App.xaml.hApp.xaml.cpp)에 붙여넣습니다.

  2. App.xaml.h에 붙여넣은 코드에서 Windows::UI::XamlMicrosoft::UI::Xaml으로 변경합니다.

  3. App.xaml.cpp에 붙여넣은 코드에서 Window::Current()의 두 항목을 window(앞서 본 App 클래스의 데이터 멤버 이름)으로 변경합니다.

App::OnLaunched

대상 프로젝트에는 이미 OnLaunched 이벤트 처리기의 구현이 포함되어 있습니다. 해당 매개 변수는 Microsoft::UI::Xaml::LaunchActivatedEventArgs에 대한 상수 참조이며, 이는 Windows 앱 SDK에 적합합니다(Windows::ApplicationModel ::Activation::LaunchActivatedEventArgs를 사용하는 소스 프로젝트와는 대조적으로, UWP에 적합함).

  • 대상 프로젝트의 App.xaml.cpp에 있는 App::OnLaunched가 아래 목록과 같이 보이도록 OnLaunched의 두 정의(원본 및 대상)를 병합하기만 하면 됩니다. UWP 버전처럼 Window::Current() 대신 window를 사용합니다.

    void App::OnLaunched(LaunchActivatedEventArgs const&)
    {
         window = make<MainWindow>();
    
         Frame rootFrame = CreateRootFrame();
         if (!rootFrame.Content())
         {
             rootFrame.Navigate(xaml_typename<PhotoEditor::MainPage>());
         }
    
         window.Activate();
    }
    

위의 코드는 AppMainPage에 대한 종속성을 제공하므로 이 시점부터 DetailPageMainPage를 마이그레이션할 때까지 빌드할 수 없습니다. 다시 빌드할 수 있게 되면 알려드리겠습니다.

DetailPage 보기 마이그레이션

DetailPage는 사진 편집기 페이지를 나타내는 클래스로, 여기서 Win2D 효과가 토글, 설정 및 연결됩니다. MainPage에서 사진 축소판을 선택하면 사진 편집기 페이지로 이동합니다. DetailPage는 모델, 보기 및 보기 모델의 의미에서 보기입니다.

Win2D NuGet 패키지 참조

DetailPage에서 코드를 지원하기 위해 소스 프로젝트는 Microsoft.Graphics.Win2D에 종속됩니다. 따라서 대상 프로젝트에서 Win2D에 대한 종속성도 필요합니다.

  • Visual Studio의 대상 솔루션에서 도구>NuGet 패키지 관리자>솔루션용 NuGet 패키지 관리...>찾아보기를 클릭합니다. 시험판 포함이 선택 해제되어 있는지 확인하고 검색 창에 Microsoft.Graphics.Win2D를 입력하거나 붙여넣습니다. 검색 결과에서 올바른 항목을 선택하고 PhotoEditor 프로젝트를 확인한 다음, 설치를 클릭하여 패키지를 설치합니다.

DetailPage 소스 코드 파일 복사

  1. 소스 프로젝트의 복제본에서 파일 탐색기에서 Windows-appsample-photo-editor>PhotoEditor 폴더를 찾습니다. 해당 폴더에서 4개의 소스 코드 파일 DetailPage.idl, DetailPage.xaml, DetailPage.hDetailPage.cpp를 찾을 수 있습니다. 이러한 파일은 DetailPage 보기를 함께 구현합니다. 이 4개 파일을 선택하고 클립보드에 복사합니다.

  2. Visual Studio에서 대상 프로젝트 노드를 마우스 오른쪽 단추로 클릭하고 파일 탐색기에서 폴더 열기를 클릭합니다. 그러면 파일 탐색기에서 대상 프로젝트 폴더가 열립니다. 방금 복사한 4개의 파일을 해당 폴더에 붙여넣습니다.

  3. 파일 탐색기에서 DetailPage.hDetailPage.cpp의 이름을 각각 DetailPage.xaml.hDetailPage.xaml.cpp으로 변경합니다. 이는 UWP와 Windows 앱 SDK 프로젝트 간에 알아야 할 폴더 및 파일 이름 차이(C++/WinRT) 중 하나입니다.

  4. 대상 프로젝트 노드를 선택한 상태로 솔루션 탐색기로 돌아가서 모든 파일 표시가 켜져 있는지 확인합니다. 방금 붙여넣은(이름을 변경한) 4개의 파일을 마우스 오른쪽 단추로 클릭하고 프로젝트에 포함을 클릭합니다. 모든 파일 표시를 끕니다.

  5. 소스 프로젝트의 솔루션 탐색기에서 DetailPage.idlDetailPage.xaml 아래에 중첩됩니다. 이 배열이 마음에 들면 \PhotoEditor\PhotoEditor\PhotoEditor\PhotoEditor.vcxproj를 수동으로 편집하여 대상 프로젝트에서 동일한 작업을 수행할 수 있습니다(먼저 Visual Studio에서 모두 저장해야 함). 다음을 찾습니다:

    <Midl Include="DetailPage.idl" />
    

    그리고 이것을 다음과 같이 바꿉니다.

    <Midl Include="DetailPage.idl">
      <DependentUpon>DetailPage.xaml</DependentUpon>
    </Midl>
    

프로젝트 파일을 저장한 후 닫습니다. 포커스를 Visual Studio로 다시 설정하면 다시 로드를 클릭합니다.

DetailPage 소스 코드 마이그레이션

  1. DetailPage.idl에서 Windows.UI.Xaml을 검색하고 Microsoft.UI.Xaml으로 변경합니다.

  2. 에서 . DetailPage.xaml.cpp로 변경 #include "DetailPage.h" 합니다 #include "DetailPage.xaml.h".

  3. 바로 아래에 #include "DetailPage.g.cpp"를 추가합니다.

  4. DetailPage.xaml.cpp에서 추가하려는 정적 App::Window 메서드를 호출하여 컴파일하려면 #include "Photo.h" 바로 앞에 #include "App.xaml.h"를 추가합니다.

  5. 방금 복사하여 붙여넣은 파일의 소스 코드 콘텐츠에서 다음 찾기/바꾸기(대소문자 및 전체 단어)를 만듭니다.

    • DetailPage.xaml.h.xaml.cpp에서 Windows::UI::Composition =>Microsoft::UI::Composition
    • DetailPage.xaml.h.xaml.cpp에서 Windows::UI::Xaml =>Microsoft::UI::Xaml
    • DetailPage.xaml.cpp에서 Window::Current() =>App::Window()
  6. 소스 프로젝트의 pch.h에서 다음 포함 항목을 복사하여 대상 프로젝트의 pch.h에 붙여넣습니다.

    #include <winrt/Windows.Graphics.Effects.h>
    #include <winrt/Microsoft.Graphics.Canvas.Effects.h>
    #include <winrt/Microsoft.Graphics.Canvas.UI.Xaml.h>
    #include <winrt/Microsoft.UI.Composition.h>
    #include <winrt/Microsoft.UI.Xaml.Input.h>
    #include <winrt/Windows.Graphics.Imaging.h>
    #include <winrt/Windows.Storage.Pickers.h>
    
  7. 또한 pch.h 맨 위의 #pragma once 바로 뒤에 다음을 추가합니다.

    // This is required because we are using std::min and std::max, otherwise 
    // we have a collision with min and max macros being defined elsewhere.
    #define NOMINMAX
    

아직 빌드할 수 없지만 MainPage(다음 단계)를 마이그레이션한 후에는 빌드할 수 있습니다.

MainPage 보기 마이그레이션

앱의 메인 페이지는 앱을 실행할 때 가장 먼저 보게 되는 뷰를 나타냅니다. 사진 라이브러리에서 사진을 로드하고 타일식 썸네일 보기를 표시하는 페이지입니다.

MainPage 소스 코드 파일 복사

  1. DetailPage에서 수행한 작업과 유사하게 이제 MainPage.idl, MainPage.xaml, MainPage.hMainPage.cpp를 복사합니다.

  2. .h.cpp 파일의 이름을 각각 .xaml.h.xaml.cpp로 바꿉니다.

  3. 이전과 같이 대상 프로젝트에 4개의 파일을 모두 포함합니다.

  4. 소스 프로젝트의 솔루션 탐색기에서 MainPage.idlMainPage.xaml 아래에 중첩됩니다. 해당 배열이 마음에 들면 \PhotoEditor\PhotoEditor\PhotoEditor\PhotoEditor.vcxproj를 수동으로 편집하여 대상 프로젝트에서 동일한 작업을 수행할 수 있습니다. 다음을 찾습니다:

    <Midl Include="MainPage.idl" />
    

    그런 다음 이 코드 줄을 다음과 같이 바꿉니다.

    <Midl Include="MainPage.idl">
      <DependentUpon>MainPage.xaml</DependentUpon>
    </Midl>
    

MainPage 소스 코드 마이그레이션

  1. MainPage.idl에서 Windows.UI.Xaml을 검색하고 두 항목을 모두 Microsoft.UI.Xaml로 변경합니다.

  2. 에서 . MainPage.xaml.cpp로 변경 #include "MainPage.h" 합니다 #include "MainPage.xaml.h".

  3. 바로 아래에 #include "MainPage.g.cpp"를 추가합니다.

  4. MainPage.xaml.cpp에서 추가하려는 정적 App::Window 메서드를 호출하여 컴파일하려면 #include "Photo.h" 바로 앞에 #include "App.xaml.h"를 추가합니다.

다음 단계에서는 ContentDialog 및 Popup에 설명된 대로 변경할 예정입니다.

  1. 따라서 MainPage.xaml.cpp에서 MainPage::GetItemsAsync 메서드의 ContentDialog unsupportedFilesDialog{};행 바로 뒤에 이 코드 줄을 추가합니다.

    unsupportedFilesDialog.XamlRoot(this->Content().XamlRoot());
    
  2. 방금 복사하여 붙여넣은 파일의 소스 코드 콘텐츠에서 다음 찾기/바꾸기(대소문자 및 전체 단어)를 만듭니다.

    • MainPage.xaml.h.xaml.cpp에서 Windows::UI::Composition =>Microsoft::UI::Composition
    • MainPage.xaml.h.xaml.cpp에서 Windows::UI::Xaml =>Microsoft::UI::Xaml
    • MainPage.xaml.cpp에서 Window::Current() =>App::Window()
  3. 소스 프로젝트의 pch.h에서 다음 포함 항목을 복사하여 대상 프로젝트의 pch.h에 붙여넣습니다.

    #include <winrt/Microsoft.UI.Xaml.Hosting.h>
    #include <winrt/Microsoft.UI.Xaml.Media.Animation.h>
    #include <winrt/Windows.Storage.Search.h>
    

대상 솔루션을 빌드할 수 있는지 확인합니다(아직 실행하지는 않음).

MainWindow 업데이트

  1. MainWindow에 UI가 필요하지 않으므로 MainWindow.xaml에서 StackPanel 및 해당 콘텐츠를 삭제합니다. 그러면 빈 Window 요소만 남게 됩니다.

  2. MainWindow.idl에서 자리 표시자 Int32 MyProperty;를 삭제하고 생성자만 남겨둡니다.

  3. MainWindow.xaml.hMainWindow.xaml.cpp에서 자리 표시자 MyPropertymyButton_Click의 선언 및 정의를 삭제하고 생성자만 남겨둡니다.

스레딩 모델 차이에 필요한 마이그레이션 변경 내용

이 섹션의 두 가지 변경 내용은 ASTA에서 STA로의 스레딩 모델에 설명된 대로 UWP와 Windows 앱 SDK 간의 스레딩 모델 차이로 인해 필요합니다. 다음은 문제의 원인에 대한 간략한 설명과 각 문제를 해결하는 방법입니다.

MainPage

MainPagePictures 폴더에서 이미지 파일을 로드하고, StorageItemContentProperties.GetImagePropertiesAsync를 호출하여 이미지 파일의 속성을 가져오고, 각 이미지 파일의 Photo 모델 개체(데이터 멤버에 동일한 속성 저장)를 만들고 해당 Photo 개체를 컬렉션에 추가합니다. Photo 개체 컬렉션은 UI의 GridView에 데이터 바인딩됩니다. 해당 GridView를 대신하여 MainPageContainerContentChanging 이벤트를 처리하고 1단계에서는 처리기가 StorageFile.GetThumbnailAsync를 호출하는 코루틴으로 호출합니다. GetThumbnailAsync를 호출하면 메시지가 나타나고(즉시 반환되지 않고 모든 작업을 비동기식으로 수행) 재진입이 발생합니다. 결과적으로 레이아웃이 발생하는 동안 GridViewItems 컬렉션이 변경되어 충돌이 발생합니다.

StorageItemContentProperties::GetImagePropertiesAsync에 대한 호출을 주석 처리하면 충돌이 발생하지 않습니다. 그러나 실제 해결 방법은 GetThumbnailAsync를 호출하기 직전에 wil::resume_foreground를 협력하면서 대기하여 StorageFile.GetThumbnailAsync 호출을 명시적으로 비동기화하는 것입니다. 이것은 wil::resume_foregroundDispatcherQueue의 작업이 되도록 뒤에 오는 코드를 예약하기 때문에 작동합니다.

변경할 코드는 다음과 같습니다.

// MainPage.xaml.cpp
IAsyncAction MainPage::OnContainerContentChanging(ListViewBase sender, ContainerContentChangingEventArgs args)
{
    ...
    if (args.Phase() == 1)
    {
        ...
        try
        {
            co_await wil::resume_foreground(this->DispatcherQueue());
            auto thumbnail = co_await impleType->GetImageThumbnailAsync(this->DispatcherQueue());
            image.Source(thumbnail);
        }
        ...
    }
}

사진

Photo::ImageTitle 속성은 UI에 데이터 바인딩되므로 UI는 값이 필요할 때마다 해당 속성에 대한 접근자 함수를 호출합니다. 그러나 UI 스레드의 해당 접근자 함수에서 ImageProperties.Title에 액세스하려고 하면 액세스 위반이 발생합니다.

대신에, Photo의 생성자에서 해당 Title에 한 번만 액세스할 수 있으며 비어 있지 않은 경우 m_imageName 데이터 멤버에 저장할 수 있습니다. 그런 다음, Photo::ImageTitle 접근자 함수에서 m_imageName 데이터 멤버에만 액세스하면 됩니다.

변경할 코드는 다음과 같습니다.

// Photo.h
...
Photo(Photo(Windows::Storage::FileProperties::ImageProperties const& props,
    ...
    ) : ...
{
	if (m_imageProperties.Title() != L"")
	{
		m_imageName = m_imageProperties.Title();
	}
}
...
hstring ImageTitle() const
{
	return m_imageName;
}
...

이것이 사진 편집기 샘플 앱을 마이그레이션하기 위해 수행해야 하는 마지막 변경 내용입니다. 마이그레이션된 앱 테스트 섹션에서 단계를 올바르게 따랐는지 확인합니다.

알려진 문제

앱 유형 문제(미리 보기 3에만 적용)

Windows 앱 SDK 버전 1.0 미리 보기 3용 VSIX에서 프로젝트 템플릿을 사용하여 이 사례 연구를 따랐다면 PhotoEditor.vcxproj를 약간 수정해야 합니다. 방법은 다음과 같습니다.

Visual Studio의 솔루션 탐색기에서 프로젝트 노드를 마우스 오른쪽 단추로 클릭하고 프로젝트 업로드를 클릭합니다. 이제 편집을 위해 PhotoEditor.vcxproj가 열립니다. Project의 첫 번째 하위 항목으로 다음과 같이 PropertyGroup 요소를 추가합니다.

<Project ... >
    <PropertyGroup>
        <EnableWin32Codegen>true</EnableWin32Codegen>
    </PropertyGroup>
    <Import ... />
...

Save and close PhotoEditor.vcxproj. 프로젝트 노드를 마우스 오른쪽 단추로 클릭하고 프로젝트 다시 로드를 클릭합니다. 이제 프로젝트를 다시 빌드합니다.

마이그레이션된 앱 테스트

이제 프로젝트를 빌드하고 앱을 실행하여 테스트합니다. 이미지를 선택하고 확대/축소 수준을 설정하고 효과를 선택하고 구성합니다.

부록: Photo 모델 파일의 콘텐츠 복사

앞에서 설명한 것처럼 소스 코드 파일 자체 또는 소스 코드 파일의 콘텐츠를 복사할 수 있는 옵션이 있습니다. 소스 코드 파일 자체를 복사하는 방법은 이미 살펴보았습니다. 따라서 이 섹션에서는 파일 콘텐츠를 복사하는 예를 제공합니다.

Visual Studio의 소스 프로젝트에서 PhotoEditor(Universal Windows)>Models 폴더를 찾습니다. 이 폴더에는 Photo 런타임 클래스를 함께 구현하는 Photo.idl, Photo.hPhoto.cpp 파일이 있습니다.

IDL 추가 및 스텁 생성

Visual Studio의 대상 프로젝트에서 새 Midl 파일(.idl) 항목을 프로젝트에 추가합니다. 새 항목의 이름을 Photo.idl로 지정합니다. Photo.idl의 기본 콘텐츠를 삭제합니다.

Visual Studio의 소스 프로젝트에서 모델>Photo.idl의 콘텐츠를 복사하고 대상 프로젝트에 방금 추가한 Photo.idl 파일에 붙여넣습니다. 붙여넣은 코드에서 Windows.UI.Xaml을 검색하고 이를 Microsoft.UI.Xaml로 변경합니다.

파일을 저장합니다.

Important

대상 솔루션의 빌드를 수행하려고 합니다. 지금은 빌드가 완료될 때까지 실행되지는 않지만 필요한 작업을 수행하기에 충분할 것입니다.

이제 대상 솔루션을 빌드합니다. 완료되지는 않지만 Photo 모델 구현을 시작하는 데 필요한 소스 코드 파일(스텁)을 생성하므로 지금 빌드가 필요합니다.

Visual Studio에서 대상 프로젝트 노드를 마우스 오른쪽 단추로 클릭하고 파일 탐색기에서 폴더 열기를 클릭합니다. 그러면 파일 탐색기에서 대상 프로젝트 폴더가 열립니다. 여기서 Generated Files\sources 폴더로 이동합니다(따라서 \PhotoEditor\PhotoEditor\PhotoEditor\Generated Files\sources에 있음). 스텁 파일 Photo.h.cpp를 복사하여 프로젝트 폴더에 붙여넣습니다. 이제 \PhotoEditor\PhotoEditor\PhotoEditor에서 두 폴더 수준으로 올라갑니다.

대상 프로젝트 노드를 선택한 상태로 솔루션 탐색기로 돌아가서 모든 파일 표시가 켜져 있는지 확인합니다. 방금 붙여넣은 스텁 파일(Photo.h.cpp)을 마우스 오른쪽 단추로 클릭하고 프로젝트에 포함을 클릭합니다. 모든 파일 표시를 끕니다.

삭제해야 하는 Photo.h.cpp의 콘텐츠 상단에 static_assert가 표시됩니다.

다시 빌드할 수 있는지 확인합니다(아직 실행하지 않음).

코드를 스텁으로 마이그레이션

Photo.h.cpp의 콘텐츠를 소스 프로젝트에서 대상 프로젝트로 복사합니다.

여기에서 복사한 코드를 마이그레이션하는 나머지 단계는 Photo 소스 코드 마이그레이션 섹션에 지정 된 것과 동일 합니다.