다음을 통해 공유


인쇄 설정을 사용자 지정하는 방법(UWP 디바이스 앱)

Windows 8.1에서 UWP 디바이스 앱을 사용하면 프린터 제조업체가 고급 인쇄 설정을 표시하는 플라이아웃을 사용자 지정할 수 있습니다. 이 항목에서는 고급 인쇄 설정 플라이아웃을 소개하고 인쇄 설정 및 인쇄 알림 샘플의 C# 버전이 기본 플라이아웃을 사용자 지정 플라이아웃으로 바꾸는 방법을 보여 줍니다. 일반적으로 UWP 디바이스 앱에 대한 자세한 내용은 UWP 디바이스 앱 모임을 참조 하세요.

인쇄 설정 및 인쇄 알림 샘플의 C# 버전은 Preferences.xaml 페이지를 사용하여 고급 인쇄 설정에 대한 사용자 지정 플라이아웃의 UI를 보여 줍니다. 인쇄 도우미 클래스는 디바이스 컨텍스트(IPrinterExtensionContext)를 만들고 디바이스 쿼리를 수행하는 데 사용됩니다. PrinterHelperClass.cs 파일은 DeviceAppForPrintersLibrary 프로젝트에 있으며 PrinterExtensionLibrary 프로젝트에 정의된 API를 사용합니다. 프린터 확장 라이브러리는 v4 인쇄 드라이버의 프린터 확장 인터페이스에 액세스하는 편리한 방법을 제공합니다. 자세한 내용은 프린터 확장 라이브러리 개요참조하세요.

참고 항목

이 항목에 표시된 코드 예제는 인쇄 설정 및 인쇄 알림 샘플의 C# 버전을 기반으로 합니다 . 이 샘플은 JavaScript 및 C++에서도 사용할 수 있습니다. C++는 COM에 직접 액세스할 수 있으므로 샘플의 C++ 버전에는 코드 라이브러리 프로젝트가 포함되지 않습니다. 샘플을 다운로드하여 최신 버전의 코드를 확인합니다.

고급 인쇄 설정

고급 인쇄 설정 환경은 사용자가 인쇄 창에서 제공되지 않는 인쇄 설정을 선택하려는 경우 프린터에서 제공하는 기능입니다. 인쇄 창의 추가 설정 링크를 통해 액세스할 수 있습니다. 전체 화면 환경은 아니지만 플라이아웃 내에 표시됩니다. 이 컨트롤은 사용자가 외부를 클릭하거나 탭할 때 해제되는 가볍고 상황에 맞는 사용자 인터페이스를 표시하기 위한 컨트롤입니다.

이 환경을 사용하여 문서 페이지에 워터마크를 적용하거나, 안전한 인쇄 옵션 또는 이미지 향상 옵션을 제공하는 기능과 같은 프린터의 차별화된 기능을 강조 표시할 수 있습니다.

프린터용 UWP 디바이스 앱이 설치되지 않은 경우 Windows는 기본 인쇄 설정 환경을 제공합니다. Windows에서 UWP 디바이스 앱이 프린터용으로 설치되어 있고 앱이 확장에 옵트인(opt in)되었음을 감지하면 앱이 Windows에서 windows.printTaskSettings 제공하는 기본 환경을 대체합니다.

고급 인쇄 설정에 대한 플라이아웃을 호출하려면 다음을 수행합니다.

  1. 인쇄를 지원하는 UWP 앱 열기

  2. 화면 오른쪽에서 살짝 밀거나 Windows 로고 키 + C를 사용하여 참에 액세스합니다.

  3. 디바이스 참 탭

  4. 인쇄 탭

  5. 프린터 탭

  6. 인쇄 창이 열립니다.

  7. 인쇄 창에서 기타 설정 링크를 클릭합니다.

  8. 고급 인쇄 설정 플라이아웃이 열립니다.

    • 프린터에 대한 UWP 디바이스 앱이 설치되지 않은 경우 기본 플라이아웃 이 나타납니다.

    • 프린터용 UWP 디바이스 앱이 설치되면 사용자 지정 플라이아웃 이 나타납니다.

examples of the default and custom flyouts for advanced print settings.

필수 조건

시작하기 전에 다음을 수행합니다.

  1. v4 인쇄 드라이버를 사용하여 프린터가 설치되어 있는지 확인합니다. 자세한 내용은 v4 인쇄 드라이버 개발을 참조 하세요.

  2. 개발 PC를 설정합니다. 도구 다운로드 및 개발자 계정 만들기에 대한 자세한 내용은 시작 정보를 참조하세요.

  3. 스토어와 앱을 연결합니다. 자세한 내용은 UWP 디바이스 앱 만들기를 참조하세요.

  4. 프린터를 앱과 연결하는 디바이스 메타데이터를 만듭니다. 자세한 내용은 디바이스 메타데이터 만들기를 참조하세요.

  5. 앱의 기본 페이지에 대한 UI를 빌드합니다. 모든 UWP 디바이스 앱은 시작에서 시작할 수 있으며 여기에서 전체 화면으로 표시됩니다. 시작 환경을 사용하여 디바이스의 특정 브랜딩 및 기능과 일치하는 방식으로 제품 또는 서비스를 강조 표시합니다. 사용할 수 있는 UI 컨트롤 유형에는 특별한 제한이 없습니다. 전체 화면 환경의 디자인을 시작하려면 Microsoft Store 디자인 원칙을 참조하세요.

  6. C# 또는 JavaScript로 앱을 작성하는 경우 PrinterExtensionLibraryDeviceAppForPrintersLibrary 프로젝트를 UWP 디바이스 앱 솔루션에 추가합니다. 인쇄 설정 및 인쇄 알림 샘플에서 이러한 각 프로젝트를 찾을 수 있습니다 .

참고 항목

C++는 COM에 직접 액세스할 수 있으므로 C++ 앱은 COM 기반 프린터 디바이스 컨텍스트를 사용하기 위해 별도의 라이브러리가 필요하지 않습니다.

1단계: 확장 등록

Windows에서 앱이 고급 인쇄 설정에 대한 사용자 지정 플라이아웃을 제공할 수 있음을 인식하려면 인쇄 작업 설정 확장을 등록해야 합니다. 이 확장은 요소에서 Extension 선언되며 특성은 Categorywindows.printTaskSettings으로 설정됩니다. C# 및 C++ 샘플 Executable 에서 특성이 설정 $targetnametoken$.exe 되고 특성이 EntryPoint .로 DeviceAppForPrinters.App설정됩니다.

Microsoft Visual Studio에서 매니페스트 디자이너의 선언 탭에서 인쇄 작업 설정 확장을 추가할 수 있습니다. XML(텍스트) 편집기를 사용하여 앱 패키지 매니페스트 XML을 수동으로 편집할 수도 있습니다. 편집 옵션을 보려면 솔루션 탐색기 Package.appxmanifest 파일을 마우스 오른쪽 단추로 클릭합니다.

이 예제에서는 앱 패키지 매니페스트 파일 Package.appxmanifest에 표시되는 요소의 인쇄 작업 설정 확장 Extension 프로그램을 보여 줍니다.

<?xml version="1.0" encoding="utf-8"?>
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest">
  <Identity Name="Microsoft.SDKSamples.DeviceAppForPrinters.CS" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" Version="1.0.0.0" />
  <Properties>
    <DisplayName>Device App For Printers C# sample</DisplayName>
    <PublisherDisplayName>Microsoft Corporation</PublisherDisplayName>
    <Logo>Assets\storeLogo-sdk.png</Logo>
  </Properties>
  <Prerequisites>
    <OSMinVersion>6.3.0</OSMinVersion>
    <OSMaxVersionTested>6.3.0</OSMaxVersionTested>
  </Prerequisites>
  <Resources>
    <Resource Language="x-generate" />
  </Resources>
  <Applications>
    <Application Id="DeviceAppForPrinters" Executable="$targetnametoken$.exe" EntryPoint="DeviceAppForPrinters.App">
      <VisualElements DisplayName="Device App For Printers C# sample" Logo="Assets\squareTile-sdk.png" SmallLogo="Assets\smallTile-sdk.png" Description="DeviceAppForPrinters C# sample" ForegroundText="light" BackgroundColor="#00b2f0" ToastCapable="true">
<DefaultTile ShowName="allLogos" ShortName="App4PrinterCS" WideLogo="Assets\tile-sdk.png" />
<SplashScreen Image="Assets\splash-sdk.png" BackgroundColor="#00b2f0" />
      </VisualElements>
      <Extensions>
<Extension Category="windows.backgroundTasks" EntryPoint="BackgroundTask.PrintBackgroundTask">
  <BackgroundTasks>
    <Task Type="systemEvent" />
  </BackgroundTasks>
</Extension>
<Extension Category="windows.printTaskSettings" Executable="$targetnametoken$.exe" EntryPoint="DeviceAppForPrinters.App" />
      </Extensions>
    </Application>
  </Applications>
</Package>

2단계: UI 빌드

앱을 빌드하기 전에 디자이너 및 마케팅 팀과 협력하여 사용자 환경을 디자인해야 합니다. 사용자 환경은 회사의 브랜딩 측면을 투영하고 사용자와의 연결을 구축하는 데 도움이 되어야 합니다.

디자인 지침

사용자 지정 플라이아웃을 디자인하기 전에 UWP 앱 플라이아웃 지침을 검토해야 합니다. 지침은 플라이아웃이 다른 UWP 앱과 일치하는 직관적인 환경을 제공하는 데 도움이 됩니다.

앱의 기본 페이지에서 Windows 8.1은 여러 앱을 단일 모니터에 다양한 크기로 표시할 수 있습니다. 화면 크기, 창 크기 및 방향 간에 앱이 정상적으로 재배치되는 방법에 대한 자세한 내용은 다음 지침을 참조하세요.

플라이아웃 차원

고급 인쇄 설정을 표시하는 플라이아웃은 너비가 646픽셀이고 높이가 768픽셀 이상입니다(실제 높이는 사용자의 화면 해상도에 따라 다름). 플라이아웃의 제목 영역에 있는 뒤로 단추는 Windows에서 제공합니다. "앱 제목" 텍스트는 앱 매니페스트의 앱 제목입니다. 제목 영역의 높이가 80픽셀이며 사용자 지정 플라이아웃의 볼 수 있는 영역에는 688픽셀이 남습니다.

flyout dimensions for advanced printer settings.

참고 항목

사용자 지정 플라이아웃 높이가 688픽셀을 초과하는 경우 사용자가 슬라이드하거나 스크롤하여 보기 가능한 영역 위 또는 아래에 있는 플라이아웃의 일부를 볼 수 있습니다.

앱 제목 색 및 아이콘 정의

제목, 배경색, 텍스트 색 및 사용자 지정 플라이아웃의 작은 로고는 앱 패키지 매니페스트 파일의 VisualElements 요소에서 가져옵니다.

이 예제에서는 요소에 VisualElements 정의된 대로 앱 패키지 매니페스트 파일(Package.appxmanifest)에 있는 제목과 아이콘을 보여 줍니다.

      <VisualElements DisplayName="Device App For Printers C# sample" Logo="Assets\squareTile-sdk.png" SmallLogo="Assets\smallTile-sdk.png" Description="DeviceAppForPrinters C# sample" ForegroundText="light" BackgroundColor="#00b2f0" ToastCapable="true">
        <DefaultTile ShowName="allLogos" ShortName="App4PrinterCS" WideLogo="Assets\tile-sdk.png" />
        <SplashScreen Image="Assets\splash-sdk.png" BackgroundColor="#00b2f0" />
      </VisualElements>

모범 사례

  • 같은 모양과 느낌을 유지합니다. 글꼴, 색 및 컨트롤과 같은 요소를 포함하여 시작 환경(앱의 기본 페이지)에 대한 디자인에 사용자 지정 플라이아웃을 맞춥니다. 앱은 어디에서 호출하는지에 관계없이 사용자에게 친숙한 느낌을 주어야 합니다.

  • 상호 작용을 단순하게 유지합니다. 시간이 많이 걸리거나 복잡한 상호 작용을 방지합니다. 대부분의 경우 프린터 설정, 상태 보기, 잉크 주문 및 문제 해결과 같은 작업은 시작 환경 내에서 가장 잘 수행됩니다.

  • 탐색을 최소한으로 유지합니다. 사용자가 사용자 지정 플라이아웃의 여러 페이지 간에 앞뒤로 이동하지 않도록 합니다. 대신 점진적 공개 컨트롤, 드롭다운 및 인라인 오류 메시지와 같은 세로 스크롤 또는 인라인 컨트롤을 사용합니다.

  • 가벼운 해제 플라이아웃을 사용하지 마세요. 인쇄 환경에서는 이미 라이트 해제 플라이아웃을 사용하고 있습니다. 사용자 지정 플라이아웃에 다른 light dismiss 요소를 포함하면 사용자가 혼동할 수 있습니다.

  • 사용자가 인쇄 환경에서 벗어나는 링크를 사용하지 않도록 설정합니다. 사용자가 콘텐츠를 인쇄할 때 인쇄 컨텍스트에서 기본 있는지 확인하는 단계를 수행해야 합니다. 예를 들어 앱의 다른 영역(예: 홈페이지 또는 잉크 구매 페이지)으로 이어지는 링크가 앱에 있는 경우 사용자가 고급 인쇄 설정 환경을 실수로 남기지 않도록 사용하지 않도록 설정해야 합니다.

3단계: 활성화 처리

앱에서 인쇄 작업 설정 확장을 선언한 경우 앱 활성화 이벤트를 처리하는 메서드를 구현 OnActivated 해야 합니다. 앱 활성화는 앱이 시작될 때 시작할 페이지를 선택할 수 있는 경우입니다. 인쇄 작업 설정 확장을 선언한 앱의 경우 Windows는 활성화된 이벤트 인수인 Windows.ApplicationModel.Activation.IActivatedEventArgs에서 인쇄 작업 확장 컨텍스트를 전달합니다.

UWP 디바이스 앱은 이벤트 인수의 kind 속성이 Windows.ApplicationModel.Activation.ActivationKind.printTask와 같은 경우 활성화가 고급 인쇄 설정(다른 사용자가 인쇄 설정 대화 상자에서 추가 옵션을한 경우)을 위한 것임을 확인할 수 있습니다설정.

참고 항목

경우에 따라 사용자가 앱이 시작된 직후에 앱을 해제하는 경우 활성화 처리기 내에서 예외가 throw될 수 있습니다. 이를 방지하려면 활성화 처리기가 효율적으로 완료되고 리소스 집약적 처리를 수행하지 않는지 확인합니다.

이 예제에서는 메서드의 활성화 이벤트 처리기가 OnActivated Constants.cs 파일에 나타나는 것을 보여 줍니다. 그런 다음 이벤트 인수는 Windows.ApplicationModel.Activation.PrintTask설정ActivatedEventArgs로 캐스팅됩니다. 샘플에는 Constants.cs 파일에 이 코드가 포함되어 있지만 실제로는 App.xaml.cs 파일에 정의된 App 클래스의 일부입니다.

partial class App : Application
{
    protected override void OnActivated(IActivatedEventArgs args)
    {
        if (args.Kind == ActivationKind.PrintTaskSettings)
        {
            Frame rootFrame = new Frame();
            if (null == Window.Current.Content)
            {
                rootFrame.Navigate(typeof(MainPage));
                Window.Current.Content = rootFrame;
            }
            Window.Current.Activate();

            MainPage mainPage = (MainPage)rootFrame.Content;

            // Load advanced printer preferences scenario
            mainPage.LoadAdvancedPrintSettingsContext((PrintTaskSettingsActivatedEventArgs)args);
        }
    }
}

4단계: 설정 표시

메서드가 LoadAdvancedPrintSettingsContext 호출되면 인쇄 작업 구성 컨텍스트가 MainPage 클래스의 변수에 할당됩니다. 이렇게 하면 사용자 지정 플라이아웃이 시작될 때 인쇄 설정에 액세스할 수 있습니다.

메서드에 LoadAdvancedPrintSettingsContext 전달되는 이벤트 인수는 프린터에 액세스하고 제어하기 위한 속성을 노출합니다.

  • args.configuration 속성은 Windows.Devices.Printers.Extensions.PrintTaskConfiguration 형식의 개체를 제공합니다. 이 개체는 인쇄 작업 확장 컨텍스트에 대한 액세스를 제공하며, 인쇄 티켓을 업데이트하는 이벤트 처리기를 추가할 수도 있습니다.
  • args.configuration.printerExtensionContext 속성은 Windows.Devices.Printers.Extensions.PrinterExtensionContext 형식의 개체를 제공합니다. 이 개체는 인쇄 스키마, PrintTicket 및 인쇄 큐 정보에 대한 PrinterExtensionLibrary 인터페이스에 대한 포인터입니다. 인터페이스가 노출되지 않으면 null이 됩니다. 자세한 내용은 프린터 확장 라이브러리 개요를 참조하세요.

이 예제에서는 Constants.cs 파일에 표시되는 메서드를 보여 LoadAdvancedPrintSettingsContext 줍니다.

public PrintTaskConfiguration Config;
public Object Context;

public void LoadAdvancedPrintSettingsContext(PrintTaskSettingsActivatedEventArgs args)
{
    Config = args.Configuration;
    Context = Config.PrinterExtensionContext;
    LoadScenario(typeof(DeviceAppForPrinters.Preferences));
}

Preferences.xaml.cs 사용자 지정 플라이아웃 페이지에서 명명된 rootPage 클래스는 인쇄 작업 확장 컨텍스트 및 프린터 장치 컨텍스트에 플라이아웃에서 액세스할 수 있도록 MainPage 클래스에 대한 포인터 역할을 합니다.

이 예제에서는 Preferences.xaml.cs 파일의 클래스 부분에 Preferences 있는 포인터를 보여줍니다. 인쇄 설정 및 인쇄 알림 샘플을 다운로드하여 전체 코드를 확인합니다.

public sealed partial class Preferences : SDKTemplate.Common.LayoutAwarePage
{
    // A pointer back to the main page.  
    MainPage rootPage = MainPage.Current;

    // To listen for save requests.
    PrintTaskConfiguration configuration;

    // To create the printer device context.
    Object printerExtensionContext;
    PrintHelperClass printHelper;

    // The features in this sample were chosen because they're available on a wide range of printer drivers.
    private string[] features = { "PageOrientation", "PageOutputColor", "PageMediaSize", "PageMediaType" };
    private string[] selections = { null, null, null, null };

    // . . .
    // . . .
    // . . .

Preferences.xaml.cs 대한 페이지 생성자가 호출되면 인쇄 작업 확장 컨텍스트(명명된 개체) 및 프린터 디바이스 컨텍스트(PrintTaskConfiguration명명configurationprintHelper개체)에 대한 개체가 PrintHelperClass 만들어집니다.

이러한 개체를 만든 후에는 이 메서드에서 프린터 디바이스 컨텍스트를 DisplaySettings 사용하여 TextBlocks 및 ComboBoxes를 로드합니다. JavaScript와 달리 선택 영역의 변경 내용은 앱의 나머지 부분과 동일한 스레드에서 발생하지 않습니다. 나중에 사용할 사용자 선택 영역의 로컬 캐시를 기본.

이 예제에서는 사용자 지정 플라이아웃 페이지 생성자 DisplaySettings및 Preferences.xaml.cs 파일의 다른 도우미 메서드를 보여 줍니다.

public Preferences()
{
    this.InitializeComponent();

    configuration = rootPage.Config;
    printerExtensionContext = rootPage.Context;
    printHelper = new PrintHelperClass(printerExtensionContext);

    // Disable scenario navigation by hiding the scenario list UI elements
    ((UIElement)rootPage.FindName("Scenarios")).Visibility = Windows.UI.Xaml.Visibility.Collapsed;
    ((UIElement)rootPage.FindName("ScenarioListLabel")).Visibility = Windows.UI.Xaml.Visibility.Collapsed;
    ((UIElement)rootPage.FindName("DescriptionText")).Visibility = Windows.UI.Xaml.Visibility.Collapsed;

    DisplaySettings();
}


private void DisplaySettings(bool constraints=false)
{
    PrintOptions.Visibility = Windows.UI.Xaml.Visibility.Visible;
    WaitPanel.Visibility = Windows.UI.Xaml.Visibility.Collapsed;

    // Fill in the drop-down select controls for some common printing features.
    TextBlock[] featureLabels = { PageOrientationLabel, PageOutputColorLabel, PageMediaSizeLabel, PageMediaTypeLabel };
    ComboBox[] featureBoxes = { PageOrientationBox, PageOutputColorBox, PageMediaSizeBox, PageMediaTypeBox };

    for (int i = 0; i < features.Length; i++)
    {
        // Only display a feature if it exists
        featureLabels[i].Visibility = Windows.UI.Xaml.Visibility.Collapsed;
        featureBoxes[i].Visibility = Windows.UI.Xaml.Visibility.Collapsed;

        string feature = features[i];

        // Check whether the currently selected printer's capabilities include this feature.
        if (!printHelper.FeatureExists(feature))
        {
            continue;
        }

        // Fill in the labels so that they display the display name of each feature.
        featureLabels[i].Text = printHelper.GetFeatureDisplayName(feature);
        string[] index = printHelper.GetOptionInfo(feature, "Index");
        string[] displayName = printHelper.GetOptionInfo(feature, "DisplayName");
        string selectedOption = printHelper.GetSelectedOptionIndex(feature);

        // Unless specified, do not get constraints
        bool[] constrainedList = constraints ? printHelper.GetOptionConstraints(feature) : new bool[index.Length];

        // Populate the combo box with the options for the current feature.
        PopulateBox(featureBoxes[i], index, displayName, selectedOption, constrainedList);
        selections[i] = selectedOption;

        // Every time the selection for a feature changes, we update our local cached set of selections.
        featureBoxes[i].SelectionChanged += OnFeatureOptionsChanged;

        // Show existing features
        featureLabels[i].Visibility = Windows.UI.Xaml.Visibility.Visible;
        featureBoxes[i].Visibility = Windows.UI.Xaml.Visibility.Visible;
    }
}

void PopulateBox(ComboBox box, string[] index, string[] displayName, string selectedOption, bool[] constrainedList)
{
    // Clear the combobox of any options from previous UI refresh before repopulating it.
    box.SelectionChanged -= OnFeatureOptionsChanged;
    box.Items.Clear();
    // There should be only one displayName for each possible option.
    if (index.Length == displayName.Length)
    {
        for (int i = 0; i < index.Length; i++)
        {
            // Create a new DisplayItem so the user will see the friendly displayName instead of the index.
            ComboBoxItem newItem = new ComboBoxItem();
            newItem.Content = displayName[i];
            newItem.DataContext = index[i];
            newItem.Foreground = constrainedList[i] ? new SolidColorBrush(Colors.Red) : new SolidColorBrush(Colors.Black);
            box.Items.Add(newItem);

            // Display current selected option as selected in the combo box.
            if (selectedOption == index[i])
            {
                box.SelectedIndex = i;
                box.Foreground = newItem.Foreground;
            }
        }
    }
}

private void OnFeatureOptionsChanged(object sender, SelectionChangedEventArgs args)
{
    ComboBox comboBox = sender as ComboBox;

    for (int i = 0; i < features.Length; i++)
    {
        if (features[i] + "Box" == comboBox.Name)
        {
            selections[i] = (comboBox.SelectedItem as ComboBoxItem).DataContext as string;
        }
    }
}

5단계: 설정 저장

사용자가 고급 인쇄 설정 설정을 완료하면 사용자가 인쇄 창으로 돌아가기 전에 Microsoft Store 장치 앱에서 변경 내용을 저장해야 합니다. 이렇게 하려면 사용자가 뒤로 단추를 탭할 때(사용자 지정 플라이아웃 페이지에서) 앱이 수신 대기해야 합니다. 이 경우 SaveRequested 인쇄 작업 확장 컨텍스트( configuration 개체)의 이벤트가 트리거됩니다.

이 예제에서는 사용자 지정 플라이아웃의 이벤트 처리기에서 OnNavigatedTo Preferences.xaml.cs 파일에 추가되는 이벤트 수신기SaveRequested 보여 줍니다. SaveRequested 이벤트가 트리거되면 메서드가 OnSaveRequested 호출됩니다(해당 메서드도 Preferences.xaml.cs 파일에 있음).

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    if (null == configuration)
    {
        rootPage.NotifyUser("Configuration arguments cannot be null", NotifyType.ErrorMessage);
        return;
    }

    // Add an event listener for saverequested (the back button of the flyout is pressed).
    configuration.SaveRequested += OnSaveRequested;
}

OnSaveRequested 이 메서드에서 앱은 먼저 개체를 printHelper 사용하여 프린터 확장 컨텍스트의 각 기능에 대해 현재 선택된 옵션을 설정합니다. 그런 다음 메서드에 Saverequest 인수로 전달되는 개체의 메서드를 호출합니다 OnSaveRequested . Windows.Devices.Printers.Extensions.PrintTaskConfigurationSaveRequest 클래스의 메서드는 Save 프린터 확장 컨텍스트를 사용하여 인쇄 티켓의 유효성을 검사하고 인쇄 작업 구성을 저장합니다.

Important

인쇄 티켓이 잘못된 경우 메서드는 Save 앱에서 처리해야 하는 예외를 throw합니다. 앱이 예외를 처리하지 않으면 흐름이 중지되어 사용자가 플라이아웃을 가볍게 해제하고 인쇄 흐름을 다시 시작해야 합니다.

이 예제에서는 Preferences.xaml.cs 파일의 메서드를 보여줍니다OnSaveRequested. SaveRequested 이벤트는 UI 스레드에서 발생하지 않으므로 Windows.UI.Core.CoreDispatcher를 사용하여 UI 스레드에 메시지를 게시하여 티켓의 유효성을 검사하고 저장하는 동안 적절한 메시지를 표시해야 합니다.

async private void OnSaveRequested(object sender, PrintTaskConfigurationSaveRequestedEventArgs args)
{
    if (null == printHelper || null == printerExtensionContext || null == args)
    {
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            rootPage.NotifyUser("onSaveRequested: args, printHelper, and context cannot be null", NotifyType.ErrorMessage);
        });
        return;
    }

    // Get the request object, which has the save method that allows saving updated print settings.
    PrintTaskConfigurationSaveRequest request = args.Request;

    if (null == request)
    {
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            rootPage.NotifyUser("onSaveRequested: request cannot be null", NotifyType.ErrorMessage);
        });
        return;
    }

    PrintTaskConfigurationSaveRequestedDeferral deferral = request.GetDeferral();

    // Two separate messages are dispatched to:
    // 1) put up a popup panel,
    // 2) set the each options to the print ticket and attempt to save it,
    // 3) tear down the popup panel if the print ticket could not be saved.
    await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
    {
        PrintOptions.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
        WaitPanel.Visibility = Windows.UI.Xaml.Visibility.Visible;
    });

    // Go through all the feature select elements, look up the selected
    // option name, and update the context
    // for each feature
    for (var i = 0; i < features.Length; i++)
    {
        // Set the feature's selected option in the context's print ticket.
        // The printerExtensionContext object is updated with each iteration of this loop
        printHelper.SetFeatureOption(features[i], selections[i]);
    }

    bool ticketSaved;
    try
    {
        // This save request will throw an exception if ticket validation fails.
        // When the exception is thrown, the app flyout will remain.
        // If you want the flyout to remain regardless of outcome, you can call
        // request.Cancel(). This should be used sparingly, however, as it could
        // disrupt the entire the print flow and will force the user to
        // light dismiss to restart the entire experience.
        request.Save(printerExtensionContext);

        if (configuration != null)
        {
            configuration.SaveRequested -= OnSaveRequested;
        }
        ticketSaved = true;
    }
    catch (Exception exp)
    {
        // Check if the HResult from the exception is from an invalid ticket, otherwise rethrow the exception
        if (exp.HResult.Equals(unchecked((int)0x8007000D))) // E_INVALID_DATA
        {
            ticketSaved = false;
        }
        else
        {
            throw;
        }
    }

    // If ticket isn't saved, refresh UI and notify user
    if (!ticketSaved)
    {
        await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
        {
            rootPage.NotifyUser("Failed to save the print ticket", NotifyType.ErrorMessage);
            DisplaySettings(true);
        });
    }
    deferral.Complete();
}

사용자 입력이 필요한 옵션 저장

인쇄 설정 및 인쇄 알림 샘플에서는 대부분의 인쇄 옵션을 다루는 정의된 기능을 설정하는 방법을 보여 줍니다. 그러나 일부 옵션에는 사용자 지정 값을 얻으려면 사용자 지정 UI가 필요합니다. 예를 들어 앱이 고급 인쇄 설정을 사용하여 사용자 지정 페이지 크기를 지정하는 경우 다음 단계를 수행하여 사용자 지정 값을 저장합니다.

  1. 앱 활성화 중에 인쇄 티켓을 검색합니다. 인쇄 설정에 대한 앱 활성화는 3단계: 활성화 처리의 앞부분에서 설명합니다.

  2. 페이지 크기 옵션이 지정되었는지 확인합니다. C# 또는 JS 앱에서 인쇄 도우미 클래스는 이 옵션에 대해 검사 수 있습니다. C++ 앱에서 IPrintSchemaOption에서 QueryInterface를 호출하여 IPrintSchemaPageMediaSizeOption을 검색합니다.

    다음은 페이지 크기 옵션이 지정된 경우 검사 인쇄 도우미 클래스의 메서드를 보여 주는 예제입니다.

    public bool ShouldShowCustomUI(string index)
    {
        if (null != index)
        {
            string feature = "PageMediaSize";
            int i = int.Parse(index);
            IPrintSchemaOption selectedOption = GetCachedFeatureOptions(feature)[i];
            if (selectedOption.Name.Equals("CustomMediaSize", StringComparison.CurrentCulture)
                || selectedOption.Name.Equals("PSCustomMediaSize", StringComparison.CurrentCulture))
            {
                return true;
            }
        }
        return false;
    }
    
  3. 사용자 지정 플라이아웃에서 사용자에게 페이지 높이와 너비를 요청하는 사용자 지정 UI를 표시하고 IPrintSchemaPageMediaSizeOption에서 사용자가 지정한 높이와 너비를 검색합니다.

    이 예제에서는 사용자에게 페이지 높이와 너비를 요청하는 사용자 지정 플라이아웃에 대한 메서드를 보여 줍니다.

    private void ShowCustomPageMediaSizeUI(string index, bool keepValue)
    {
        //Hide custom media size UI unless needed
        if (IsCustomSizeSelected(index))
        {
           if (keepValue && (!customWidth.Equals("")) && (!customHeight.Equals("")))
           {
                        CustomWidthBox.Text = customWidth;
                        CustomHeightBox.Text = customHeight;
           }
           else
           {
              // Use a helper function from the WinRT helper component
              CustomWidthBox.Text = printHelper.GetCustomWidth(index);
              CustomHeightBox.Text = printHelper.GetCustomHeight(index);
           }
           CustomUIPanel.Visibility = Windows.UI.Xaml.Visibility.Visible;
           CustomWidthBox.KeyDown += OnCustomValueEntered;
           CustomHeightBox.KeyDown += OnCustomValueEntered;
        }
        else
        {
           CustomUIPanel.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
           CustomWidthBox.KeyDown -= OnCustomValueEntered;
           CustomHeightBox.KeyDown -= OnCustomValueEntered;
        }
    }
    
  4. 개체를 IPrintSchemaPageMediaSizeOption 사용자 지정 값으로 업데이트하고 높이와 너비가 사용자 지정 값과 일치하는지 확인합니다.

    다음은 프린터 도우미 클래스에서 개체를 업데이트하는 IPrintSchemaPageMediaSizeOption 도우미 메서드입니다. OnSaveRequested 사용자 지정 플라이아웃의 처리기는 사용자 지정 페이지 크기 옵션이 요청된 것으로 확인되면 이 함수를 호출합니다.

    public void SetCustomMediaSizeDimensions(string width, string height)
    {
      if ((null == width) && (null == height) && (null == Capabilities))
      {
                    return;
      }
      try
      {
                    CheckSizeValidity(width, height);
      }
      catch (FormatException e)
      {
                    throw new ArgumentException(e.Message);
      }
      catch (OverflowException e)
      {
                    throw new ArgumentException(e.Message);
      }
    
      // The context is retrieved during app activation.
      IPrintSchemaTicket ticket = context.Ticket;
    
      //
      // Input XML as Stream
      //
      XElement ticketRootXElement = null;
      using (Stream ticketReadStream = ticket.GetReadStream())
      {
         ticketRootXElement = XElement.Load(ticketReadStream);
      }
    
      XNamespace psfNs = PrintSchemaConstants.FrameworkNamespaceUri;
      XNamespace pskNs = PrintSchemaConstants.KeywordsNamespaceUri;
      string pskPrefix = ticketRootXElement.GetPrefixOfNamespace(pskNs);
    
      // Modify the MediaSizeHeight and MediaSizeWidth
      IEnumerable<XElement> parameterInitCollection =
        from c in ticketRootXElement.Elements(psfNs + "ParameterInit")
    
      select c;
    
      foreach (XElement parameterInit in parameterInitCollection)
      {
        if (0 == String.Compare((string)parameterInit.Attribute("name"), pskPrefix + ":PageMediaSizePSWidth"))
        {
          IEnumerable<XElement> valueCollection = from c in parameterInit.Elements(psfNs + "Value")
          select c;
          valueCollection.ElementAt(0).Value = width;
        }
    
         else if (0 == String.Compare((string)parameterInit.Attribute("name"), pskPrefix + ":PageMediaSizePSHeight"))
        {
          IEnumerable<XElement> valueCollection = from c in parameterInit.Elements(psfNs + "Value")
          select c;
          valueCollection.ElementAt(0).Value = height;
         }
      }
    
      //
      // Write XLinq changes back to DOM
      //
       using (Stream ticketWriteStream = ticket.GetWriteStream())
       {
         ticketRootXElement.Save(ticketWriteStream);
       }
    }
    

테스팅

UWP 디바이스 앱을 테스트하려면 먼저 디바이스 메타데이터를 사용하여 프린터에 연결해야 합니다.

  • 디바이스 앱 정보를 추가하려면 프린터에 대한 디바이스 메타데이터 패키지의 복사본이 필요합니다. 디바이스 메타데이터가 없는 경우 UWP 디바이스 앱에 대한 디바이스 메타데이터 만들기 항목에 설명된 대로 디바이스 메타데이터 작성 마법사를 사용하여 빌드할 수 있습니다.

    참고 항목

    디바이스 메타데이터 작성 마법사를 사용하려면 이 항목의 단계를 완료하기 전에 Microsoft Visual Studio Professional, Microsoft Visual Studio Ultimate 또는 Windows 8.1용 독립 실행형 SDK를 설치해야 합니다. Windows용 Microsoft Visual Studio Express를 설치하면 마법사를 포함하지 않는 SDK 버전이 설치됩니다.

다음 단계에서는 앱을 빌드하고 디바이스 메타데이터를 설치합니다.

  1. 테스트 서명을 사용하도록 설정합니다.

    1. DeviceMetadataWizard.exe 두 번 클릭하여 %ProgramFiles(x86)%\Windows Kits\8.1\bin\x86에서 디바이스 메타데이터 제작 마법사시작합니다.

    2. 도구 메뉴에서 테스트 서명 사용을 선택합니다.

  2. 컴퓨터를 다시 부팅

  3. 솔루션(.sln) 파일을 열어 솔루션을 빌드합니다. F7 키를 누르거나 샘플이 로드된 후 상단 메뉴에서 빌드> 솔루션으로 이동합니다.

  4. 프린터 연결을 끊고 제거합니다. 이 단계는 다음에 디바이스가 검색될 때 Windows에서 업데이트된 디바이스 메타데이터를 읽도록 하는 데 필요합니다.

  5. 디바이스 메타데이터를 편집하고 저장합니다. 디바이스 앱을 디바이스에 연결하려면 디바이스 앱을 디바이스와 연결해야 합니다.

    참고 항목

    디바이스 메타데이터를 아직 만들지 않은 경우 UWP 디바이스 앱에 대한 디바이스 메타데이터 만들기를 참조하세요.

    1. 디바이스 메타데이터 작성 마법사가 아직 열려 있지 않으면 DeviceMetadataWizard.exe 두 번 클릭하여 %ProgramFiles(x86)%\Windows Kits\8.1\bin\x86에서 시작합니다.

    2. 디바이스 메타데이터 편집을 클릭합니다. 이렇게 하면 기존 디바이스 메타데이터 패키지를 편집할 수 있습니다.

    3. 열기 대화 상자에서 UWP 디바이스 앱과 연결된 디바이스 메타데이터 패키지를 찾습니다. (devicemetadata-ms 파일 확장명입니다.)

    4. UWP 디바이스 앱 정보 지정 페이지의 UWP 디바이스 앱 상자에 Microsoft Store 앱 정보를 입력합니다. UWP 앱 매니페스트 파일 가져오기를 클릭하여 패키지 이름, 게시자 이름UWP 앱 ID를 자동으로 입력합니다.

    5. 앱이 프린터 알림을 등록하는 경우 알림 처리기 상자를 입력 합니다 . 이벤트 ID에서 인쇄 이벤트 처리기의 이름을 입력합니다. 이벤트 자산에서 해당 코드가 있는 파일의 이름을 입력합니다.

    6. 완료되면 마침 페이지에 도착할 때까지 다음클릭합니다.

    7. 디바이스 메타데이터 패키지 검토 페이지에서 모든 설정이 올바른지 확인하고 로컬 컴퓨터 검사 상자의 메타데이터 저장소에 디바이스 메타데이터 패키지 복사를 선택합니다. 그런 다음 Save를 클릭합니다.

  6. 디바이스가 연결될 때 Windows에서 업데이트된 디바이스 메타데이터를 읽도록 프린터를 다시 연결합니다.

문제 해결

문제: 고급 인쇄 설정에 사용자 지정 플라이아웃 대신 기본 플라이아웃이 표시됩니다.

고급 인쇄 설정 플라이아웃에 앱이 구현하는 사용자 지정 플라이아웃 대신 기본 플라이아웃이 표시되는 경우...

  • 가능한 원인: 테스트 서명이 켜져 있지 않습니다. 설정에 대한 자세한 내용은 이 항목의 디버깅 섹션을 참조하세요.

  • 가능한 원인: 앱이 올바른 패키지 패밀리 이름을 쿼리하지 않습니다. 코드에서 패키지 패밀리 이름을 확인합니다. Visual Studio에서 package.appxmanifest를 열고 쿼리하는 패키지 패밀리 이름이 패키지 패밀리 이름 필드의 패키징 탭에 있는 이름과 일치하는지 확인합니다.

  • 가능한 원인: 디바이스 메타데이터가 패키지 패밀리 이름과 연결되어 있지 않습니다. 디바이스 메타데이터 작성 마법사를 사용하여 디바이스 메타데이터를 열고 패키지 패밀리 이름을 검사. DeviceMetadataWizard.exe 두 번 클릭하여 %ProgramFiles(x86)%\Windows Kits\8.1\bin\x86에서 마법사를 시작합니다.

문제: 앱이 플라이아웃에서 시작된 다음 즉시 해제됩니다.

고급 인쇄 설정에 대한 사용자 지정 플라이아웃이 시작된 직후 사라지는 경우...

  • 가능한 원인: Windows 8에서는 플라이아웃 내에서 UWP 앱이 디버거에서 해제되는 알려진 문제가 있습니다. 활성화가 작동한다는 것을 알고 나면 디버깅을 끕니다. 인쇄 티켓 저장을 디버그해야 하는 경우 활성화 후 디버거를 연결합니다.

v4 인쇄 드라이버 개발

프린터 확장 인터페이스(v4 인쇄 드라이버)

양방향 통신

UWP 앱 시작

UWP 디바이스 앱 만들기(단계별 가이드)

UWP 디바이스 앱에 대한 디바이스 메타데이터 만들기(단계별 가이드)