diff options
| author | Dave Wilson <[email protected]> | 2015-03-17 19:50:07 -0700 |
|---|---|---|
| committer | Dave Wilson <[email protected]> | 2015-03-17 19:50:07 -0700 |
| commit | 97cf5197cf5b882b2c689d8dc2b555f2edf8f418 (patch) | |
| tree | 46f3701832d70b420eb0fc0eb93261f9da45db3f /print/v4PrintDriverSamples/PrinterExtensionSample | |
| parent | ef1905bf1e8825bb31120dfb27e0daf3154d859a (diff) | |
Initial publish
Diffstat (limited to 'print/v4PrintDriverSamples/PrinterExtensionSample')
27 files changed, 5418 insertions, 0 deletions
diff --git a/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/App.xaml b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/App.xaml new file mode 100644 index 00000000..f97fc473 --- /dev/null +++ b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/App.xaml @@ -0,0 +1,7 @@ +<Application x:Class="Microsoft.Samples.Printing.PrinterExtension.App" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + Startup="Application_Startup" + Exit="Application_Exit" + > +</Application> diff --git a/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/App.xaml.cs b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/App.xaml.cs new file mode 100644 index 00000000..d37585c4 --- /dev/null +++ b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/App.xaml.cs @@ -0,0 +1,146 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved +// +// +// Abstract: +// +// This file contains the entry point to the application. + +using System; +using System.Windows; +using System.Runtime; + +using Microsoft.Samples.Printing.PrinterExtension.Types; +using Microsoft.Samples.Printing.PrinterExtension.Helpers; + +using System.Windows.Interop; + +namespace Microsoft.Samples.Printing.PrinterExtension +{ + /// <summary> + /// Interaction logic for App.xaml. + /// </summary> + public partial class App : Application + { + /// <summary> + /// This is the event handler invoked on various driver events. + /// </summary> + /// <param name="sender"></param> + /// <param name="eventArgs"></param> + private static void OnDriverEvent(object sender, PrinterExtensionEventArgs eventArgs) + { + // + // Display the print preferences window. + // + + if (eventArgs.ReasonId.Equals(PrinterExtensionReason.PrintPreferences)) + { + PrintPreferenceWindow printPreferenceWindow = new PrintPreferenceWindow(); + printPreferenceWindow.Initialize(eventArgs); + + // + // Set the caller application's window as parent/owner of the newly created printing preferences window. + // + + WindowInteropHelper wih = new WindowInteropHelper(printPreferenceWindow); + wih.Owner = eventArgs.WindowParent; + + // + // Display a modal/non-modal window based on the 'WindowModal' parameter. + // + + if (eventArgs.WindowModal) + { + printPreferenceWindow.ShowDialog(); + } + else + { + printPreferenceWindow.Show(); + + // Flash the window to draw the user's attention. This is required + // because the printer extension may be drawn behind the parent window. + // The return value of FlashWindow can be safely ignored if there is no need + // to know if the window has focus or not. + WindowHelper.FlashWindow(wih.Handle); + } + } + else if (eventArgs.ReasonId.Equals(PrinterExtensionReason.DriverEvent)) + { + // + // Handle driver events here. + // + } + } + + /// <summary> + /// Perform initialization tasks for the printer extension in this event handler. + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void Application_Startup(object sender, StartupEventArgs e) + { + // + // It is recommended that exactly one instance of the PrinterExtensionManager be created per instance of + // the printer extension. + // + + if (manager != null) + { + return; + } + manager = new PrinterExtensionManager(); + + // + // Enable events to be received on one printer driver id. + // + // Note: The order of adding the delegate to PrinterExtensionManager.OnDriverEvent + // and invoking PrinterExtensionManager::EnableEvents is important. + // Adding the delegate should be done first. + // + + manager.OnDriverEvent += OnDriverEvent; + + // + // It is recommended that an instance of a printer extension invoke PrinterExtensionManager::EnableEvents + // for exactly one printer driver id. The printer driver id could come in from a command line argument, + // thereby allowing one application binary to dynamically invoke PrinterExtensionManager::EnableEvents against + // the appropriate printer driver id. + // + + manager.EnableEvents(Guid.Parse(PrinterDriverID)); + } + + /// <summary> + /// Perform uninitialization tasks for the printer extension in this event handler. + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void Application_Exit(object sender, ExitEventArgs e) + { + manager.OnDriverEvent -= OnDriverEvent; + manager.DisableEvents(); + + manager = null; + } + + /// <summary> + /// This is the printer driver id, as defined in the printer driver manifest file. + /// Please replace this GUID with the printer driver id from your manifest file. + /// + /// It is recommended that you invoke PrinterExtensionManager::EnableEvents() on exactly + /// one printer driver id. The id could come in from a command line argument, thereby enabling + /// one application binary to work with multiple printer driver ids. + /// </summary> + private const string PrinterDriverID = "{E0691E8D-F7CC-456E-A7B5-D1FC19BA2279}"; + + /// <summary> + /// Instance of the PrinterExtensionManager. It is recommended that you have only instance + /// of the PrinterExtensionManager per application instance. + /// </summary> + private static PrinterExtensionManager manager = null; + } +} diff --git a/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/BidiHelper.cs b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/BidiHelper.cs new file mode 100644 index 00000000..c975ee7c --- /dev/null +++ b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/BidiHelper.cs @@ -0,0 +1,154 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved +// +// +// Abstract: +// +// This file contains helper methods that provide a data-binding friendly way to access and parse bidi response data. + +using System; +using System.Collections.Generic; +using System.Windows.Media; +using System.Xml; + +namespace Microsoft.Samples.Printing.PrinterExtension.Helpers +{ + /// <summary> + /// Provide a data-binding friendly way to access and parse bidi response data. + /// </summary> + public class BidiHelper + { + /// <summary> + /// Parse the bidi response. + /// </summary> + /// <param name="bidiResponse">Bidi response XML data.</param> + public BidiHelper(string bidiResponse) + { + BidiResponseParser parser = new BidiResponseParser(bidiResponse); + InkLevelC = parser.GetInkLevel(Colors.Cyan); + InkLevelM = parser.GetInkLevel(Colors.Magenta); + InkLevelY = parser.GetInkLevel(Colors.Yellow); + InkLevelK = parser.GetInkLevel(Colors.Black); + } + + /// <summary> + /// Get the Cyan ink level. + /// </summary> + public double InkLevelC + { + get; + private set; + } + + /// <summary> + /// Get the Magenta ink level. + /// </summary> + public double InkLevelM + { + get; + private set; + } + + /// <summary> + /// Get the Yellow ink level. + /// </summary> + public double InkLevelY + { + get; + private set; + } + + /// <summary> + /// Get the Black ink level. + /// </summary> + public double InkLevelK + { + get; + private set; + } + } + + /// <summary> + /// This class parses bidi response xml data and provides wrapper methods that operate upon the xml. + /// </summary> + internal class BidiResponseParser + { + /// <summary> + /// Parse the bidi response. + /// </summary> + /// <param name="bidiResponse">Bidi response XML data.</param> + internal BidiResponseParser(string bidiResponse) + { + bidiData = new XmlDocument(); + bidiData.LoadXml(bidiResponse); + + namespaceManager = new XmlNamespaceManager(bidiData.NameTable); + namespaceManager.AddNamespace("bidi", "http://schemas.microsoft.com/windows/2005/03/printing/bidi"); + } + + /// <summary> + /// Get the ink level for a given color. + /// </summary> + /// <param name="color">Color</param> + /// <returns>Ink level percentage</returns> + internal double GetInkLevel(Color color) + { + XmlElement root = bidiData.DocumentElement; + XmlNode inkNode = root.SelectSingleNode(CreateInkXPathQuery(color), namespaceManager); + return double.Parse(inkNode.FirstChild.Value) / 100; + } + + /// <summary> + /// Create an XPath query that retrieves the ink level from a standard bidi response. + /// </summary> + /// <param name="color"></param> + /// <returns></returns> + private static string CreateInkXPathQuery(Color color) + { + string colorName = null; + + if (color.Equals(Colors.Black)) + { + colorName = "Black"; + } + else if (color.Equals(Colors.Red)) + { + colorName = "Red"; + } + else if (color.Equals(Colors.Green)) + { + colorName = "Green"; + } + else if (color.Equals(Colors.Blue)) + { + colorName = "Blue"; + } + else if (color.Equals(Colors.Cyan)) + { + colorName = "Cyan"; + } + else if (color.Equals(Colors.Magenta)) + { + colorName = "Magenta"; + } + else if (color.Equals(Colors.Yellow)) + { + colorName = "Yellow"; + } + else + { + throw new ArgumentException("Unsupported color"); + } + + return "/bidi:Get/Query/Schema[@name='\\Printer.Consumables." + colorName + "Ink" + ":Level']/BIDI_INT"; + } + + private XmlDocument bidiData; + private XmlNamespaceManager namespaceManager; + } + +} diff --git a/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/Fabrikam_Logo.png b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/Fabrikam_Logo.png Binary files differnew file mode 100644 index 00000000..196cd5f6 --- /dev/null +++ b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/Fabrikam_Logo.png diff --git a/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/PrintPreferenceWindow.xaml b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/PrintPreferenceWindow.xaml new file mode 100644 index 00000000..924efc21 --- /dev/null +++ b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/PrintPreferenceWindow.xaml @@ -0,0 +1,147 @@ +<Window x:Class="Microsoft.Samples.Printing.PrinterExtension.PrintPreferenceWindow" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:c="clr-namespace:Microsoft.Samples.Printing.PrinterExtension" + xmlns:sys="clr-namespace:System;assembly=mscorlib" + Title="{Binding Path=PrinterQueue.Name}" Height="405" Width="565" + ResizeMode="NoResize" + Icon="Fabrikam_Logo.png" + Closing="PrintPreferenceWindow_Closing" + > + + <Window.Resources> + <!-- Resources required to create the basic window --> + <Style x:Key="GraySingleBorder" TargetType="Border"> + <Setter Property="BorderBrush" Value="Gray" /> + </Style> + + <SolidColorBrush x:Key="InkStatusBorderBrush" Color="Black"/> + + <BitmapImage x:Key="FabrikamLogo" UriSource="Fabrikam_Logo.png" /> + + <Style x:Key="SimpleGroupBox" TargetType="GroupBox"> + <Setter Property="Margin" Value="5,5,5,5" /> + <Setter Property="Padding" Value="0,5,0,0" /> + </Style> + + <!-- + Each brush below is bound to BidiHelperSource, which provides a data-biding friendly way to + access ink levels. + --> + <LinearGradientBrush x:Key="InkBrushC" StartPoint="0, 1" EndPoint="0, 0"> + <GradientStop Color="Cyan" Offset="{Binding Path=BidiHelperSource.InkLevelC}" /> + <GradientStop Color="White" Offset="{Binding Path=BidiHelperSource.InkLevelC}" /> + </LinearGradientBrush> + <LinearGradientBrush x:Key="InkBrushM" StartPoint="0, 1" EndPoint="0, 0"> + <GradientStop Color="Magenta" Offset="{Binding Path=BidiHelperSource.InkLevelM}" /> + <GradientStop Color="White" Offset="{Binding Path=BidiHelperSource.InkLevelM}" /> + </LinearGradientBrush> + <LinearGradientBrush x:Key="InkBrushY" StartPoint="0, 1" EndPoint="0, 0"> + <GradientStop Color="Yellow" Offset="{Binding Path=BidiHelperSource.InkLevelY}" /> + <GradientStop Color="White" Offset="{Binding Path=BidiHelperSource.InkLevelY}" /> + </LinearGradientBrush> + <LinearGradientBrush x:Key="InkBrushK" StartPoint="0, 1" EndPoint="0, 0"> + <GradientStop Color="Black" Offset="{Binding Path=BidiHelperSource.InkLevelK}" /> + <GradientStop Color="White" Offset="{Binding Path=BidiHelperSource.InkLevelK}" /> + </LinearGradientBrush> + + <c:OptionConstrainedToDisplayColorConverter x:Key="OptionConstrainedToColor" /> + </Window.Resources> + + <Grid x:Name="MainGrid"> + <Grid.ColumnDefinitions> + <ColumnDefinition x:Name="LeftHalf" Width="3*"/> + <ColumnDefinition x:Name="RightHalf" Width="5*"/> + </Grid.ColumnDefinitions> + <Grid.RowDefinitions> + <RowDefinition x:Name="BrandingRow" Height="1*"/> + <RowDefinition x:Name="ContentRow" Height="2*"/> + <RowDefinition x:Name="StatusRow" /> + </Grid.RowDefinitions> + + <Border Style="{DynamicResource GraySingleBorder}" Grid.Row="0" Grid.ColumnSpan="2" BorderThickness="0,0,0,1"/> + <Border Style="{DynamicResource GraySingleBorder}" Grid.Row="1" Grid.Column="0" BorderThickness="0,0,0,1" /> + <Border Style="{DynamicResource GraySingleBorder}" Grid.Row="1" Grid.Column="1" BorderThickness="1,0,0,1" /> + <Border Style="{DynamicResource GraySingleBorder}" Grid.Row="2" Grid.Column="0" BorderThickness="0,0,0,0" /> + <Border Style="{DynamicResource GraySingleBorder}" Grid.Row="2" Grid.Column="1" BorderThickness="1,0,0,0" /> + + <Image Source="{StaticResource FabrikamLogo}" Grid.Row="0" Grid.Column="0" Stretch="None"/> + + <!-- + Display the name of the current print queue. + --> + <TextBlock FontFamily="Verdana" Grid.Row="0" Grid.Column="1" TextAlignment="Left" + VerticalAlignment="Center" FontSize="16" Foreground="DarkOrchid" Text="{Binding Path=PrinterQueue.Name}" /> + + <!-- + Lay out multiple GroupBoxes, with one ComboBox inside each. The number of GroupBoxes is determined by the number of features returned by + binding property: PrintSchemaHelperSource.Features. + + Each GroupBox Header displays the print schema feature's display name, bound to PrintSchemaFeatureHelper.DisplayName. + Each ComboBox's ItemSource property is bound to the list of valid options for that feature i.e. bound to PrintSchemaFeatureHelper.Options. + Additionally, the ComboBox is bound two-way to to PrintSchemaFeatureHelper.SelectedOption. Therefore, in addition to displaying the option + selected in the current print ticket, when the selected option is changed via UI selection, + a 'set' property is invoked on PrintSchemaFeatureHelper.SelectedOption. + + Each item in the ComboBox has the following structure: + It's displays the option name via a TextBlock, bound to the IPrintSchemaOption.DisplayName. + It's 'ForeGround' font color changes based on the IPrintSchemaOption.Constrained property. + + *Note*: Since this is an expensive operation to perfom, the data is retrieved asynchronously (IsAsync=true, below). + --> + <StackPanel Grid.Row="1" Grid.Column="1"> + <ItemsControl ItemsSource="{Binding Path=PrintSchemaHelperSource.Features, IsAsync=True}"> + <ItemsControl.ItemTemplate> + <DataTemplate> + <GroupBox Style="{DynamicResource SimpleGroupBox}" Header="{Binding Path=DisplayName}"> + <ComboBox ItemsSource="{Binding Path=Options}" SelectedItem="{Binding Path=SelectedOption}"> + <ItemsControl.ItemTemplate> + <DataTemplate> + <StackPanel Orientation="Horizontal" > + <TextBlock Text="{Binding Path=DisplayName}" Foreground="{Binding Converter={StaticResource OptionConstrainedToColor}, Path=Constrained}"/> + </StackPanel> + </DataTemplate> + </ItemsControl.ItemTemplate> + </ComboBox> + </GroupBox> + </DataTemplate> + </ItemsControl.ItemTemplate> + </ItemsControl> + </StackPanel> + + <!-- + This modal dialog prevents the user from making changes to print preferences + when print ticket validation is in progress. This dialog is hidden when validation is not in progress. + --> + <c:ValidationModalDialog x:Name="ValidationModalDialog" Grid.Row="1" Grid.Column="1" Visibility="Hidden"/> + + <!-- + This GroupBox displays ink status. There are 4 rectangles that display ink status. The brush that paints color/level is bound to code. + --> + <GroupBox Header="{Binding Path=InkStatusTitle}" Grid.Column="0" Grid.Row="2" Margin="5,0,5,5"> + <Grid> + <Grid.RowDefinitions> + <RowDefinition Height="24*"/> + <RowDefinition Height="43*"/> + </Grid.RowDefinitions> + <Grid.ColumnDefinitions> + <ColumnDefinition /> + <ColumnDefinition /> + <ColumnDefinition /> + <ColumnDefinition /> + </Grid.ColumnDefinitions> + + <Rectangle Grid.Column="0" Fill="{DynamicResource InkBrushC}" Margin="2,0,2,0" Name="InkIndicatorC" Stroke="{DynamicResource InkStatusBorderBrush}" Grid.RowSpan="2"/> + <Rectangle Grid.Column="1" Fill="{DynamicResource InkBrushM}" Margin="2,0,2,0" Name="InkIndicatorM" Stroke="{DynamicResource InkStatusBorderBrush}" Grid.RowSpan="2"/> + <Rectangle Grid.Column="2" Fill="{DynamicResource InkBrushY}" Margin="2,0,2,0" Name="InkIndicatorY" Stroke="{DynamicResource InkStatusBorderBrush}" Grid.RowSpan="2"/> + <Rectangle Grid.Column="3" Fill="{DynamicResource InkBrushK}" Margin="0,0,2,0" Name="InkIndicatorK" Stroke="{DynamicResource InkStatusBorderBrush}" HorizontalAlignment="Right" Width="43" Grid.RowSpan="2"/> + </Grid> + </GroupBox> + + <UniformGrid Grid.Row="2" Grid.Column="2" Rows="1" Columns="3" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="0,0,10,10"> + <Button Content="_Ok" Name="OkButton" Margin="0,0,5,0" Click="Button_Click" /> + <Button Content="_Cancel" Name="CancelButton" Margin="5,0,5,0" Padding="10,0,10,0" Click="Button_Click" /> + <Button Content="_Verify settings" Name="VerifyButton" Margin="5,0,0,0" Click="Button_Click" /> + </UniformGrid> + </Grid> +</Window> diff --git a/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/PrintPreferenceWindow.xaml.cs b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/PrintPreferenceWindow.xaml.cs new file mode 100644 index 00000000..a6266662 --- /dev/null +++ b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/PrintPreferenceWindow.xaml.cs @@ -0,0 +1,467 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved +// +// +// Abstract: +// +// This file contains as the interaction logic and data-binding code/sources for the WPF print preferences window. + +using System; +using System.ComponentModel; +using System.Collections.Generic; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Media; + +using System.Reflection; +using System.IO; + +using System.Xml.Linq; + +using System.Runtime.InteropServices; + +using Microsoft.Samples.Printing.PrinterExtension.Types; +using Microsoft.Samples.Printing.PrinterExtension.Helpers; + +namespace Microsoft.Samples.Printing.PrinterExtension +{ + /// <summary> + /// Interaction logic for PrintPreferenceWindow.xaml. + /// </summary> + public partial class PrintPreferenceWindow : Window, INotifyPropertyChanged + { + public PrintPreferenceWindow() + { + InitializeComponent(); + } + + /// <summary> + /// This method sets up data binding sources and performs other initialization tasks. + /// </summary> + /// <param name="eventArgs"></param> + public void Initialize(PrinterExtensionEventArgs eventArgs) + { + // + // Populate the data binding sources. + // + + DataContext = this; + + printerExtensionEventArgs = eventArgs; + PrinterQueue = eventArgs.Queue; + displayedPrintTicket = eventArgs.Ticket; + + // + // Send a bidi query requesting ink levels. + // + // Please note: As this event will fire many times, it is recommended to maintain event + // listeners for the life time of the application. Furthermore, the relationship to this + // being invoked and the calling SendBidiQuery() is not 1:1; in fact, it is *:N, where the + // listener may be called several times with bidi updates. + // + // + + PrinterQueue.OnBidiResponseReceived += OnBidiResponseReceived; + PrinterQueue.SendBidiQuery("\\Printer.consumables"); + } + + #region UI code + + /// <summary> + /// This event handler is invoked when the window is closing. It is important to Cancel or Complete the request when the window is closing. + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + void PrintPreferenceWindow_Closing(object sender, EventArgs e) + { + // Since we are a different process from the printing application we need to hand focus back when complete. + WindowHelper.SetForegroundWindow(printerExtensionEventArgs.WindowParent); + + if (!requestCompleted) + { + printerExtensionEventArgs.Request.Cancel((int)HRESULT.S_FALSE, "The user canceled the operation."); + requestCompleted = true; + } + } + + /// <summary> + /// Button click event handler. + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void Button_Click(object sender, RoutedEventArgs e) + { + Button clickedButton = (Button)sender; + + switch (clickedButton.Name) + { + case "CancelButton": + CancelRequestAndCloseWindow(); + break; + + case "OkButton": + // + // Validate the print ticket asynchronously. The event handler is invoked when the validation is completed. + // + + IPrintSchemaAsyncOperation asyncOperation = displayedPrintTicket.ValidateAsync(); + + // + // Pop up a modal dialog that prevents the user from changing selections when validation is in progress. + // Since this dialog lives as long as the parent window, it is not mandatory to unregister the delegate for the + // 'Completed' event. + // + + ValidationModalDialog.Completed += PrintTicketValidateCompleted; // This operation is idempotent. + ValidationModalDialog.StartAsyncOperation(asyncOperation); + break; + + case "VerifyButton": + // + // Force WPF Data binding to refresh the UI. This operation retrieves + // a fresh print capabilities for the print ticket based on the user selections. + // + + PropertyChanged(this, new PropertyChangedEventArgs("PrintSchemaHelperSource")); + break; + } + } + + /// <summary> + /// Close the window in a thread-safe way. + /// </summary> + private void CloseWindow() + { + this.Dispatcher.BeginInvoke(new Action(() => + { + this.Close(); + })); + } + + #endregion + + + #region Data binding sources + + /// <summary> + /// The Print queue for which this window is being displayed. + /// </summary> + public IPrinterQueue PrinterQueue { get; private set; } + + /// <summary> + /// The title for the ink status display. + /// </summary> + public string InkStatusTitle { get; private set; } + + /// <summary> + /// Retrieve a new instance of PrintSchemaHelper, based on the current print ticket being displayed. + /// PrintSchemaHelper encapsulates all the features and options required to populate the print preferences UI. + /// </summary> + public PrintSchemaHelper PrintSchemaHelperSource + { + get + { + // + // Below is the list of features that will be displayed in the print preferences window. + // The features are declared here for convenience/readability. + // + // In performant code, this array would be allocated only once per run of the application. + // + + string[] featureNames = { + "DocumentNUp", + "PageMediaSize", + "DocumentInputBin", + "PageOrientation", + "PageMediaType", + "PageBorderless", + "JobInputBin", + "PageOutputColor", + "DocumentCollate", + "DocumentDuplex" + }; + + return new PrintSchemaHelper(displayedPrintTicket, featureNames); + } + } + + /// <summary> + /// Encapsulates the information required to populate ink level. + /// </summary> + public BidiHelper BidiHelperSource { get; private set; } + + /// <summary> + /// This event is raised when a data from a binding source is modified. + /// </summary> + public event PropertyChangedEventHandler PropertyChanged; + + #endregion + + #region Ink level display + /// <summary> + /// This is the method invoked when a bidi response is received. + /// </summary> + /// <param name="sender">IPrinterQueue object.</param> + /// <param name="e">The results of the bidi response.</param> + private void OnBidiResponseReceived(object sender, PrinterQueueEventArgs e) + { + if (e.StatusHResult != (int)HRESULT.S_OK) + { + MockInkStatus(); + return; + } + + // + // Display the ink levels from the mock data. + // + + BidiHelperSource = new BidiHelper(e.Response); + if (PropertyChanged != null) + { + PropertyChanged(this, new PropertyChangedEventArgs("BidiHelperSource")); + } + InkStatusTitle = "Ink status (Live data)"; + } + + /// <summary> + /// This method is invoked when there is an error retrieving Bidi information. + /// A mock bidi response is loaded from resource and displayed. + /// </summary> + private void MockInkStatus() + { + // + // Load mock bidi response resource. + // + + Assembly a = Assembly.GetExecutingAssembly(); + Stream xmlData = a.GetManifestResourceStream("PrinterExtensionSample.bidi_Ink_mock.xml"); + StreamReader sr = new StreamReader(xmlData); + string xmlString = sr.ReadToEnd(); + + // + // Display the ink levels from the mock data. + // + + BidiHelperSource = new BidiHelper(xmlString); + if (PropertyChanged != null) + { + PropertyChanged(this, new PropertyChangedEventArgs("BidiHelperSource")); + } + InkStatusTitle = "Ink status (Mocked data)"; + } + #endregion + + #region PrintSchema-related code + /// <summary> + /// Cancel the current printer extension event and close the current window. + /// </summary> + private void CancelRequestAndCloseWindow() + { + printerExtensionEventArgs.Request.Cancel((int)HRESULT.S_FALSE, "User canceled the operation"); + requestCompleted = true; + CloseWindow(); + } + + /// <summary> + /// Invoked when asynchronous print ticket validation is complete. + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void PrintTicketValidateCompleted(object sender, PrintSchemaAsyncOperationEventArgs e) + { + // + // Print ticket validation completed successfully i.e. print ticket selections are not constrained. + // The print ticket needs to be committed, and then window can be closed. + // + + if (e.StatusHResult == (int)HRESULT.S_PT_NO_CONFLICT) + { + this.Dispatcher.Invoke(new Action(() => + { + CommitPrintTicketAsync(e.Ticket); + })); + + } + else + { + // + // The ticket selections are constrained. + // + + this.Dispatcher.Invoke(new Action(() => + { + HandleTicketConstraints(e.Ticket); + })); + } + } + + /// <summary> + /// Invoked when there are constraints in the print ticket selections. + /// </summary> + /// <param name="validatedTicket"></param> + private void HandleTicketConstraints(IPrintSchemaTicket validatedTicket) + { + // + // Retrieved localized display strings from a resource file/ + // + string selectionConflictsFound = PrinterExtensionSample.Strings.SelectionConflictsFound; + string selectionConflictsTitle = PrinterExtensionSample.Strings.SelectionConflictsTitle; + + MessageBoxResult result = MessageBox.Show( + this, + selectionConflictsFound, + selectionConflictsTitle, + MessageBoxButton.YesNoCancel); + + if (result == MessageBoxResult.Yes) + { + CommitPrintTicketAsync(validatedTicket); + } + else + { + PropertyChanged(this, new PropertyChangedEventArgs("PrintSchemaHelperSource")); + } + } + + /// <summary> + /// Commits the input print ticket asynchronously. The completed event handler is expected to close the window. + /// </summary> + /// <param name="validatedTicket"></param> + private void CommitPrintTicketAsync(IPrintSchemaTicket validatedTicket) + { + IPrintSchemaAsyncOperation commitAsyncOperation = printerExtensionEventArgs.Ticket.CommitAsync(validatedTicket); + commitAsyncOperation.Completed += PrintTicketCommitCompleted; + commitAsyncOperation.Start(); + } + + /// <summary> + /// Invoked when the user's selections have been committed into the print ticket. + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void PrintTicketCommitCompleted(object sender, PrintSchemaAsyncOperationEventArgs e) + { + CompleteRequestAndCloseWindow(); + } + + /// <summary> + /// Complete the current printer extension request and close the current window. + /// </summary> + private void CompleteRequestAndCloseWindow() + { + // + // It is important to invoke the IPrinterExtensionRequest::Complete method from the thread the + // class instance was create on (i.e. the UI thread). + // + + this.Dispatcher.Invoke(new Action(() => + { + printerExtensionEventArgs.Request.Complete(); + })); + + requestCompleted = true; + CloseWindow(); + } + + /// <summary> + /// Demonstrates how to modify print ticket XML. This piece of code does not perform any functionality. + /// It serves to demonstrate the usage of IPrintSchemaTicket::GetReadStream()/GetWriteStream() + /// </summary> + private void ModifyPrintTicketXml() + { + // + // Load the ticket XML (as a Stream) into an XElement object. + // + + XElement ticketRootXElement = null; + using (Stream ticketReadStream = displayedPrintTicket.GetReadStream()) + { + ticketRootXElement = XElement.Load(ticketReadStream); + } + + // + // Perform any modifications on the XElement object. + // + + + // + // Write the changes back to the print ticket. + // + using (Stream ticketWriteStream = displayedPrintTicket.GetWriteStream()) + { + ticketRootXElement.Save(ticketWriteStream); + } + } + + #endregion + + /// <summary> + /// The arguments passed in for this print preferences event. + /// </summary> + private PrinterExtensionEventArgs printerExtensionEventArgs = null; + + /// <summary> + /// Reflects the currently displayed print preference options. + /// </summary> + private IPrintSchemaTicket displayedPrintTicket = null; + + /// <summary> + /// Determines if IPrinterExtensionRequest::Complete()/Cancel() has been invoked for this Window. + /// instance + /// </summary> + private bool requestCompleted = false; + } + + /// <summary> + /// This class transforms the boolean 'IPrintSchemaOption.Constrained' into a visual form. + /// </summary> + public class OptionConstrainedToDisplayColorConverter : IValueConverter + { + public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + if (value == null) + { + return "Black"; + } + + // + // If the option is not constrained, it will be diplayed in black. + // + + PrintSchemaConstrainedSetting constrained = (PrintSchemaConstrainedSetting)value; + if (constrained == PrintSchemaConstrainedSetting.None) + { + return "Black"; + } + + // + // If the option is constrained, it will be displayed in red. + // + + return "Red"; + } + + public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) + { + throw new NotImplementedException(); + } + } + + /// <summary> + /// Provides a friendlier way to use HRESULT error codes. + /// </summary> + enum HRESULT : int + { + S_OK = 0x0000, + S_FALSE = 0x0001, + S_PT_NO_CONFLICT = 0x40001, + E_INVALIDARG = unchecked((int)0x80070057), + E_OUTOFMEMORY = unchecked((int)0x8007000E), + ERROR_NOT_FOUND = unchecked((int)0x80070490) + } +} diff --git a/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/PrintSchemaHelper.cs b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/PrintSchemaHelper.cs new file mode 100644 index 00000000..e9201162 --- /dev/null +++ b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/PrintSchemaHelper.cs @@ -0,0 +1,190 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved +// +// +// Abstract: +// +// This file contains helper methods that provide a data-binding friendly way to access PrintSchema APIs. + +using System; +using System.Collections.Generic; +using System.Text; + +using System.Runtime.InteropServices; + +using Microsoft.Samples.Printing.PrinterExtension.Types; + +namespace Microsoft.Samples.Printing.PrinterExtension.Helpers +{ + /// <summary> + /// Contains helper methods that provide a data-binding friendly way to access PrintSchema APIs. + /// </summary> + public class PrintSchemaHelper + { + /// <summary> + /// Constructor. Warning constructing this object is expensive, and is best performed + /// asynchronously. + /// </summary> + /// <param name="ticket">The print ticket for which features/options will be retrieved</param> + /// <param name="featureNameCollection">List of features requested</param> + internal PrintSchemaHelper(IPrintSchemaTicket ticket, IEnumerable<String> featureNameCollection) + { + _ticket = ticket; + _featureNameCollection = featureNameCollection; + _capabilities = _ticket.GetCapabilities(); + } + + /// <summary> + /// Retrieve the list of features from the current print ticket. + /// </summary> + public List<PrintSchemaFeatureHelper> Features + { + get + { + _featureHelperCollection = new List<PrintSchemaFeatureHelper>(); + + // + // Retrieve the list of features supported by the driver + // + + foreach (string name in _featureNameCollection) + { + // + // If the feature is not present in the print ticket or the print capabilities, + // ignore it and continue. + // + + IPrintSchemaFeature ticketFeature = _ticket.GetFeatureByKeyName(name); + if (ticketFeature == null) + { + continue; + } + + IPrintSchemaFeature capabilitiesFeature = _capabilities.GetFeatureByKeyName(name); + if (capabilitiesFeature == null) + { + continue; + } + + // If the feature is not meant to be displayed on the UI, ignore it and continue. + if (!capabilitiesFeature.DisplayUI) + { + continue; + } + + _featureHelperCollection.Add(new PrintSchemaFeatureHelper(ticketFeature, _capabilities, capabilitiesFeature)); + } + + return _featureHelperCollection; + } + } + + /// <summary> + /// List of features requested. + /// </summary> + private IEnumerable<string> _featureNameCollection; + + /// <summary> + /// Helper objects that wrap an IPrintSchemaFeature object. + /// </summary> + private List<PrintSchemaFeatureHelper> _featureHelperCollection = null; + + /// <summary> + /// Print ticket passed into this class. + /// </summary> + private IPrintSchemaTicket _ticket = null; + + /// <summary> + /// Print capabilities object. + /// </summary> + private IPrintSchemaCapabilities _capabilities = null; + } + + /// <summary> + /// Contains helper methods that provide a data-binding friendly way to access IPrintSchemaFeature APIs. + /// + /// Note: This sample does not handle Print Ticket/Print Capabilities Options which rely on parameters to + /// be specified, such as psk:Custom , psk:CustomSquare, or psk:CustomMediaSize. If these options are + /// supported by compatible print drivers, then the printer extension should be modified to support them + /// appropriately. + /// </summary> + public class PrintSchemaFeatureHelper + { + /// <summary> + /// Constructor + /// </summary> + /// <param name="ticketFeature">Object retrieved via a call to IPrintSchemaTicket::GetFeature/GetFeatureByKeyName</param> + /// <param name="capabilities">Print capabilities object</param> + /// <param name="capabilitiesFeature">Object retrieved via a call to IPrintSchemaCapabilities::GetFeature/GetFeatureByKeyName</param> + internal PrintSchemaFeatureHelper(IPrintSchemaFeature ticketFeature, IPrintSchemaCapabilities capabilities, IPrintSchemaFeature capabilitiesFeature) + { + // + // Populate the properties exposed by this class. + // + + DisplayName = capabilitiesFeature.DisplayName; + Options = new List<IPrintSchemaOption>(capabilities.GetOptions(ticketFeature)); + + foreach (IPrintSchemaOption option in Options) + { + if (option.Selected) + { + _selectedOption = option; + break; + } + } + + _printTicketFeature = ticketFeature; + } + + /// <summary> + /// Returns the display name for the current IPrintSchemaFeature object. + /// </summary> + public string DisplayName + { + get; + private set; + } + + /// <summary> + /// Retrieve the list of options supported for the current feature. + /// </summary> + public List<IPrintSchemaOption> Options + { + get; + private set; + } + + /// <summary> + /// A 'get' invocation on this property returns the selected option for this print ticket feature. + /// A 'set' invocation on this property sets the selected option for this print ticket feature. + /// </summary> + public IPrintSchemaOption SelectedOption + { + get + { + return _selectedOption; + } + set + { + _selectedOption = value; + _printTicketFeature.SelectedOption = _selectedOption; + } + } + + /// <summary> + /// Feature object retrieved from the print ticket. + /// </summary> + private IPrintSchemaFeature _printTicketFeature = null; + + /// <summary> + /// Selected option for the print ticket feature. + /// </summary> + private IPrintSchemaOption _selectedOption = null; + + } +} diff --git a/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/PrinterExtensionSample.csproj b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/PrinterExtensionSample.csproj new file mode 100644 index 00000000..bbb7f044 --- /dev/null +++ b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/PrinterExtensionSample.csproj @@ -0,0 +1,219 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">x86</Platform> + <ProductVersion>8.0.30703</ProductVersion> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{CF554A99-6889-4B86-934F-B6AADBFEFC01}</ProjectGuid> + <OutputType>WinExe</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>PrinterExtensionSample</RootNamespace> + <AssemblyName>PrinterExtensionSample</AssemblyName> + <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> + <TargetFrameworkProfile> + </TargetFrameworkProfile> + <FileAlignment>512</FileAlignment> + <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <WarningLevel>4</WarningLevel> + <PublishUrl>publish\</PublishUrl> + <Install>true</Install> + <InstallFrom>Disk</InstallFrom> + <UpdateEnabled>false</UpdateEnabled> + <UpdateMode>Foreground</UpdateMode> + <UpdateInterval>7</UpdateInterval> + <UpdateIntervalUnits>Days</UpdateIntervalUnits> + <UpdatePeriodically>false</UpdatePeriodically> + <UpdateRequired>false</UpdateRequired> + <MapFileExtensions>true</MapFileExtensions> + <ApplicationRevision>0</ApplicationRevision> + <ApplicationVersion>1.0.0.%2a</ApplicationVersion> + <UseApplicationTrust>false</UseApplicationTrust> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Win8 Debug|x86' "> + <OutputPath>bin\Win8 Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <PlatformTarget>x86</PlatformTarget> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <Prefer32Bit>false</Prefer32Bit> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Win8 Release|x86' "> + <OutputPath>bin\Win8 Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <PlatformTarget>x86</PlatformTarget> + <DebugSymbols>true</DebugSymbols> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <Prefer32Bit>false</Prefer32Bit> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Win8 Debug|x64'"> + <OutputPath>bin\x64\Win8 Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <PlatformTarget>x64</PlatformTarget> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <Prefer32Bit>false</Prefer32Bit> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Win8 Release|x64'"> + <OutputPath>bin\x64\Win8 Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <PlatformTarget>x64</PlatformTarget> + <DebugSymbols>true</DebugSymbols> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <Prefer32Bit>false</Prefer32Bit> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Win8.1 Debug|x86' "> + <OutputPath>bin\Win8.1 Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <PlatformTarget>x86</PlatformTarget> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <Prefer32Bit>false</Prefer32Bit> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Win8.1 Release|x86' "> + <OutputPath>bin\Win8.1 Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <PlatformTarget>x86</PlatformTarget> + <DebugSymbols>true</DebugSymbols> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <Prefer32Bit>false</Prefer32Bit> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Win8.1 Debug|x64'"> + <OutputPath>bin\x64\Win8.1 Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <PlatformTarget>x64</PlatformTarget> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <Prefer32Bit>false</Prefer32Bit> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Win8.1 Release|x64'"> + <OutputPath>bin\x64\Win8.1 Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <PlatformTarget>x64</PlatformTarget> + <DebugSymbols>true</DebugSymbols> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + <Prefer32Bit>false</Prefer32Bit> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Data" /> + <Reference Include="System.Drawing" /> + <Reference Include="System.Windows.Forms" /> + <Reference Include="System.Xml" /> + <Reference Include="Microsoft.CSharp" /> + <Reference Include="System.Core" /> + <Reference Include="System.Xml.Linq" /> + <Reference Include="System.Data.DataSetExtensions" /> + <Reference Include="System.Xaml"> + <RequiredTargetFramework>4.0</RequiredTargetFramework> + </Reference> + <Reference Include="WindowsBase" /> + <Reference Include="PresentationCore" /> + <Reference Include="PresentationFramework" /> + </ItemGroup> + <ItemGroup> + <Compile Include="BidiHelper.cs" /> + <Compile Include="PrintSchemaHelper.cs" /> + <Compile Include="Strings.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Strings.resx</DependentUpon> + </Compile> + <Compile Include="ValidationModalDialog.xaml.cs"> + <DependentUpon>ValidationModalDialog.xaml</DependentUpon> + </Compile> + <ApplicationDefinition Include="App.xaml"> + <Generator>MSBuild:Compile</Generator> + <SubType>Designer</SubType> + </ApplicationDefinition> + <Compile Include="WindowHelper.cs" /> + <Page Include="PrintPreferenceWindow.xaml"> + <Generator>MSBuild:Compile</Generator> + <SubType>Designer</SubType> + </Page> + <Compile Include="App.xaml.cs"> + <DependentUpon>App.xaml</DependentUpon> + <SubType>Code</SubType> + </Compile> + <Compile Include="PrintPreferenceWindow.xaml.cs"> + <DependentUpon>PrintPreferenceWindow.xaml</DependentUpon> + <SubType>Code</SubType> + </Compile> + <Page Include="ValidationModalDialog.xaml"> + <Generator>MSBuild:Compile</Generator> + </Page> + </ItemGroup> + <ItemGroup> + <Compile Include="Properties\AssemblyInfo.cs"> + <SubType>Code</SubType> + </Compile> + <Compile Include="Properties\Resources.Designer.cs"> + <AutoGen>True</AutoGen> + <DesignTime>True</DesignTime> + <DependentUpon>Resources.resx</DependentUpon> + </Compile> + <Compile Include="Properties\Settings.Designer.cs"> + <AutoGen>True</AutoGen> + <DependentUpon>Settings.settings</DependentUpon> + <DesignTimeSharedInput>True</DesignTimeSharedInput> + </Compile> + <EmbeddedResource Include="Properties\Resources.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Resources.Designer.cs</LastGenOutput> + </EmbeddedResource> + <EmbeddedResource Include="Strings.resx"> + <Generator>ResXFileCodeGenerator</Generator> + <LastGenOutput>Strings.Designer.cs</LastGenOutput> + </EmbeddedResource> + <None Include="app.config" /> + <None Include="Properties\Settings.settings"> + <Generator>SettingsSingleFileGenerator</Generator> + <LastGenOutput>Settings.Designer.cs</LastGenOutput> + </None> + <AppDesigner Include="Properties\" /> + </ItemGroup> + <ItemGroup> + <Resource Include="Fabrikam_Logo.png" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\PrinterExtensionLibrary\PrinterExtensionLibrary.csproj"> + <Project>{d8da0c4d-f972-4546-9068-8eb256f222f7}</Project> + <Name>PrinterExtensionLibrary</Name> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <EmbeddedResource Include="bidi_Ink_mock.xml" /> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> +</Project>
\ No newline at end of file diff --git a/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/Properties/AssemblyInfo.cs b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..c3198284 --- /dev/null +++ b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/Properties/AssemblyInfo.cs @@ -0,0 +1,62 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved +// +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("PrinterExtensionSample")] +[assembly: AssemblyDescription("Printer Extension Sample for v4 print drivers")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft")] +[assembly: AssemblyProduct("PrinterExtensionSample")] +[assembly: AssemblyCopyright("Copyright (c) Microsoft Corporation. All rights reserved")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +//In order to begin building localizable applications, set +//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file +//inside a <PropertyGroup>. For example, if you are using US english +//in your source files, set the <UICulture> to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/Properties/Resources.Designer.cs b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/Properties/Resources.Designer.cs new file mode 100644 index 00000000..b6af3bc4 --- /dev/null +++ b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:4.0.30319.17325 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace PrinterExtensionSample.Properties { + using System; + + + /// <summary> + /// A strongly-typed resource class, for looking up localized strings, etc. + /// </summary> + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// <summary> + /// Returns the cached ResourceManager instance used by this class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PrinterExtensionSample.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/Properties/Resources.resx b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/Properties/Resources.resx new file mode 100644 index 00000000..af7dbebb --- /dev/null +++ b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/Properties/Resources.resx @@ -0,0 +1,117 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> +</root>
\ No newline at end of file diff --git a/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/Properties/Settings.Designer.cs b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/Properties/Settings.Designer.cs new file mode 100644 index 00000000..c0a373ef --- /dev/null +++ b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/Properties/Settings.Designer.cs @@ -0,0 +1,26 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:4.0.30319.17325 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace PrinterExtensionSample.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + } +} diff --git a/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/Properties/Settings.settings b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/Properties/Settings.settings new file mode 100644 index 00000000..033d7a5e --- /dev/null +++ b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/Properties/Settings.settings @@ -0,0 +1,7 @@ +<?xml version='1.0' encoding='utf-8'?> +<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)"> + <Profiles> + <Profile Name="(Default)" /> + </Profiles> + <Settings /> +</SettingsFile>
\ No newline at end of file diff --git a/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/Strings.Designer.cs b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/Strings.Designer.cs new file mode 100644 index 00000000..6ea88a35 --- /dev/null +++ b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/Strings.Designer.cs @@ -0,0 +1,82 @@ +//------------------------------------------------------------------------------ +// <auto-generated> +// This code was generated by a tool. +// Runtime Version:4.0.30319.17361 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// </auto-generated> +//------------------------------------------------------------------------------ + +namespace PrinterExtensionSample { + using System; + + + /// <summary> + /// A strongly-typed resource class, for looking up localized strings, etc. + /// </summary> + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Strings { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Strings() { + } + + /// <summary> + /// Returns the cached ResourceManager instance used by this class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PrinterExtensionSample.Strings", typeof(Strings).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// <summary> + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// </summary> + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// <summary> + /// Looks up a localized string similar to Selection conflicts were encountered. + ///Would you like them auto-resolved?. + /// </summary> + internal static string SelectionConflictsFound { + get { + return ResourceManager.GetString("SelectionConflictsFound", resourceCulture); + } + } + + /// <summary> + /// Looks up a localized string similar to Selection conflicts. + /// </summary> + internal static string SelectionConflictsTitle { + get { + return ResourceManager.GetString("SelectionConflictsTitle", resourceCulture); + } + } + } +} diff --git a/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/Strings.resx b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/Strings.resx new file mode 100644 index 00000000..8f4878a4 --- /dev/null +++ b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/Strings.resx @@ -0,0 +1,129 @@ +<?xml version="1.0" encoding="utf-8"?> +<root> + <!-- + Microsoft ResX Schema + + Version 2.0 + + The primary goals of this format is to allow a simple XML format + that is mostly human readable. The generation and parsing of the + various data types are done through the TypeConverter classes + associated with the data types. + + Example: + + ... ado.net/XML headers & schema ... + <resheader name="resmimetype">text/microsoft-resx</resheader> + <resheader name="version">2.0</resheader> + <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> + <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> + <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> + <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> + <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> + <value>[base64 mime encoded serialized .NET Framework object]</value> + </data> + <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> + <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> + <comment>This is a comment</comment> + </data> + + There are any number of "resheader" rows that contain simple + name/value pairs. + + Each data row contains a name, and value. The row also contains a + type or mimetype. Type corresponds to a .NET class that support + text/value conversion through the TypeConverter architecture. + Classes that don't support this are serialized and stored with the + mimetype set. + + The mimetype is used for serialized objects, and tells the + ResXResourceReader how to depersist the object. This is currently not + extensible. For a given mimetype the value must be set accordingly: + + Note - application/x-microsoft.net.object.binary.base64 is the format + that the ResXResourceWriter will generate, however the reader can + read any of the formats listed below. + + mimetype: application/x-microsoft.net.object.binary.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.soap.base64 + value : The object must be serialized with + : System.Runtime.Serialization.Formatters.Soap.SoapFormatter + : and then encoded with base64 encoding. + + mimetype: application/x-microsoft.net.object.bytearray.base64 + value : The object must be serialized into a byte array + : using a System.ComponentModel.TypeConverter + : and then encoded with base64 encoding. + --> + <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> + <xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> + <xsd:element name="root" msdata:IsDataSet="true"> + <xsd:complexType> + <xsd:choice maxOccurs="unbounded"> + <xsd:element name="metadata"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" /> + </xsd:sequence> + <xsd:attribute name="name" use="required" type="xsd:string" /> + <xsd:attribute name="type" type="xsd:string" /> + <xsd:attribute name="mimetype" type="xsd:string" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="assembly"> + <xsd:complexType> + <xsd:attribute name="alias" type="xsd:string" /> + <xsd:attribute name="name" type="xsd:string" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="data"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> + <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> + <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> + <xsd:attribute ref="xml:space" /> + </xsd:complexType> + </xsd:element> + <xsd:element name="resheader"> + <xsd:complexType> + <xsd:sequence> + <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> + </xsd:sequence> + <xsd:attribute name="name" type="xsd:string" use="required" /> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + </xsd:schema> + <resheader name="resmimetype"> + <value>text/microsoft-resx</value> + </resheader> + <resheader name="version"> + <value>2.0</value> + </resheader> + <resheader name="reader"> + <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <resheader name="writer"> + <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> + </resheader> + <data name="SelectionConflictsFound" xml:space="preserve"> + <value>Selection conflicts were encountered. +Would you like them auto-resolved?</value> + <comment>String to display in the message box when print ticket settings have conflicts.</comment> + </data> + <data name="SelectionConflictsTitle" xml:space="preserve"> + <value>Selection conflicts</value> + <comment>Title string on the message box that displays the selection conflicts message.</comment> + </data> +</root>
\ No newline at end of file diff --git a/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/ValidationModalDialog.xaml b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/ValidationModalDialog.xaml new file mode 100644 index 00000000..c949efd4 --- /dev/null +++ b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/ValidationModalDialog.xaml @@ -0,0 +1,19 @@ +<UserControl x:Class="Microsoft.Samples.Printing.PrinterExtension.ValidationModalDialog" + xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" + xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" + xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"> + <Grid DataContext="{Binding ElementName=root}"> + <Border Background="#60000000"> + <Border BorderBrush="Black" BorderThickness="1" Background="AliceBlue" + CornerRadius="10,0,10,0" VerticalAlignment="Center" HorizontalAlignment="Center"> + <Border.BitmapEffect> + <DropShadowBitmapEffect Color="Black" Opacity="0.5" Direction="90" ShadowDepth="0.7" /> + </Border.BitmapEffect> + <UniformGrid Grid.Row="1" Margin="10" Rows="2" Columns="1" HorizontalAlignment="Center" VerticalAlignment="Bottom"> + <TextBlock>Validating.. please wait</TextBlock> + <Button x:Name="CancelValidationButton" Content="Cancel" Click="CancelValidationButton_Click"/> + </UniformGrid> + </Border> + </Border> + </Grid> +</UserControl> diff --git a/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/ValidationModalDialog.xaml.cs b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/ValidationModalDialog.xaml.cs new file mode 100644 index 00000000..0728c84c --- /dev/null +++ b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/ValidationModalDialog.xaml.cs @@ -0,0 +1,108 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved +// +// +// Abstract: +// +// This file contains as the interaction logic for ValidationModaldialog. +// This dialog prevents the user from making changes to print ticket settings when asynchronous +// validation is being performed. + +using System; +using System.Collections.Generic; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; + +using Microsoft.Samples.Printing.PrinterExtension.Types; + +namespace Microsoft.Samples.Printing.PrinterExtension +{ + /// <summary> + /// Interaction logic for ValidationModalDialog.xaml + /// This dialog prevents the user from changing print preferences when validation is in progress. + /// </summary> + public partial class ValidationModalDialog : UserControl + { + public ValidationModalDialog() + { + InitializeComponent(); + Visibility = Visibility.Hidden; + } + + /// <summary> + /// Starts the asynchronous operation. + /// </summary> + /// <param name="asyncOperationToStart">Async operation context.</param> + public void StartAsyncOperation(IPrintSchemaAsyncOperation asyncOperationToStart) + { + this.asyncOperationContext = asyncOperationToStart; + Visibility = Visibility.Visible; + asyncOperationToStart.Completed += asyncOperation_Completed; + asyncOperationToStart.Start(); + } + + + /// <summary> + /// This method is invoked from a different thread once asynchronous validation is completed. + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void asyncOperation_Completed(object sender, PrintSchemaAsyncOperationEventArgs e) + { + ValidationHResult = e.StatusHResult; + HideWindow(); + + if (Completed != null) + { + Completed(this, e); + } + } + + /// <summary> + /// Hides the current window. + /// </summary> + private void HideWindow() + { + this.Dispatcher.Invoke(new Action(() => + { + Visibility = Visibility.Hidden; + })); + } + + + /// <summary> + /// Result of the validation operation. + /// </summary> + public int ValidationHResult + { + get; + private set; + } + + /// <summary> + /// Invoked then the "Cancel" button is clicked. + /// </summary> + /// <param name="sender"></param> + /// <param name="e"></param> + private void CancelValidationButton_Click(object sender, RoutedEventArgs e) + { + asyncOperationContext.Cancel(); + HideWindow(); + } + + /// <summary> + /// Invoked when the asynchronous operation is completed. + /// </summary> + public event EventHandler<PrintSchemaAsyncOperationEventArgs> Completed; + + /// <summary> + /// Asynchronous operation context. + /// </summary> + private IPrintSchemaAsyncOperation asyncOperationContext; + } +} diff --git a/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/WindowHelper.cs b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/WindowHelper.cs new file mode 100644 index 00000000..fe830921 --- /dev/null +++ b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/WindowHelper.cs @@ -0,0 +1,83 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved +// +// +// Abstract: +// +// This file contains helper methods that provide a friendly way to access win32 window functions. + +using System; +using System.Runtime.InteropServices; + +namespace Microsoft.Samples.Printing.PrinterExtension.Helpers +{ + class WindowHelper + { + /// <summary> + /// P/Invoke signature for Win32 function "SetForegroundWindow". + /// </summary> + /// <param name="hwnd">Handle to window</param> + [return: MarshalAs(UnmanagedType.Bool)] + [DllImport("User32", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)] + public static extern bool SetForegroundWindow(IntPtr hwnd); + + /// <summary> + /// Wrapper for Win32 function "FlashWindowEx" + /// </summary> + /// <param name="hWnd">Handle of the window to flash</param> + public static bool FlashWindow(IntPtr hWnd) + { + FLASHWINFO fInfo = new FLASHWINFO(); + + fInfo.cbSize = Convert.ToUInt32(Marshal.SizeOf(fInfo)); + fInfo.hwnd = hWnd; // Handle to window + fInfo.uCount = UInt32.MaxValue; // Number of times to flash + fInfo.dwTimeout = 0; // Use default cursor blink rate + // Flash both window caption and taskbar button, until the window is brought to the foreground. + fInfo.dwFlags = (uint)(FLASHW.ALL | FLASHW.TIMERNOFG); + + return FlashWindowEx(ref fInfo); + } + + #region private members + + /// <summary> + /// P/Invoke signature for Win32 function "FlashWindowEx". + /// </summary> + [return: MarshalAs(UnmanagedType.Bool)] + [DllImport("User32", CharSet = CharSet.Auto, SetLastError = false, ExactSpelling = true)] + private static extern bool FlashWindowEx(ref FLASHWINFO pwfi); + + [StructLayout(LayoutKind.Sequential)] + private struct FLASHWINFO + { + public UInt32 cbSize; + public IntPtr hwnd; + public UInt32 dwFlags; + public UInt32 uCount; + public UInt32 dwTimeout; + } + + /// <summary> + /// Represents the FLASH_Xxx flags + /// </summary> + [Flags] + private enum FLASHW : uint + { + /// <summary> + /// Flash both the window caption and taskbar button + /// </summary> + ALL = 3, + /// <summary> + /// Flash continuously until the window comes to the foreground. + /// </summary> + TIMERNOFG = 12 + } + + #endregion + } +} diff --git a/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/app.config b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/app.config new file mode 100644 index 00000000..bfc57c55 --- /dev/null +++ b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/app.config @@ -0,0 +1,9 @@ +<?xml version="1.0"?> +<configuration> + <appSettings> + <add key="UseSetWindowPosForTopmostWindows" value="True" /> + </appSettings> + <startup> + <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/> + </startup> +</configuration> diff --git a/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/bidi_Ink_mock.xml b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/bidi_Ink_mock.xml new file mode 100644 index 00000000..b1a685f1 --- /dev/null +++ b/print/v4PrintDriverSamples/PrinterExtensionSample/ExtensionSample/bidi_Ink_mock.xml @@ -0,0 +1,74 @@ +<?xml version="1.0" encoding="utf-8"?> +<bidi:Get xmlns:bidi="http://schemas.microsoft.com/windows/2005/03/printing/bidi"> + <Query schema="\Printer.Consumables"> + <Schema name="\Printer.Consumables.BlackInk:Color"> + <BIDI_STRING>Black</BIDI_STRING> + </Schema> + <Schema name="\Printer.Consumables.BlackInk:Installed"> + <BIDI_BOOL>true</BIDI_BOOL> + </Schema> + <Schema name="\Printer.Consumables.BlackInk:Level"> + <BIDI_INT>86</BIDI_INT> + </Schema> + <Schema name="\Printer.Consumables.BlackInk:Type"> + <BIDI_STRING>InkSupply</BIDI_STRING> + </Schema> + <Schema name="\Printer.Consumables.CyanInk:Color"> + <BIDI_STRING>Cyan</BIDI_STRING> + </Schema> + <Schema name="\Printer.Consumables.CyanInk:Installed"> + <BIDI_BOOL>true</BIDI_BOOL> + </Schema> + <Schema name="\Printer.Consumables.CyanInk:Level"> + <BIDI_INT>79</BIDI_INT> + </Schema> + <Schema name="\Printer.Consumables.CyanInk:Type"> + <BIDI_STRING>InkSupply</BIDI_STRING> + </Schema> + <Schema name="\Printer.Consumables.LightBlackInk:Color"> + <BIDI_STRING>LightBlack</BIDI_STRING> + </Schema> + <Schema name="\Printer.Consumables.LightBlackInk:Installed"> + <BIDI_BOOL>true</BIDI_BOOL> + </Schema> + <Schema name="\Printer.Consumables.LightBlackInk:Level"> + <BIDI_INT>0</BIDI_INT> + </Schema> + <Schema name="\Printer.Consumables.LightBlackInk:Type"> + <BIDI_STRING>InkSupply</BIDI_STRING> + </Schema> + <Schema name="\Printer.Consumables.MagentaInk:Color"> + <BIDI_STRING>Magenta</BIDI_STRING> + </Schema> + <Schema name="\Printer.Consumables.MagentaInk:Installed"> + <BIDI_BOOL>true</BIDI_BOOL> + </Schema> + <Schema name="\Printer.Consumables.MagentaInk:Level"> + <BIDI_INT>79</BIDI_INT> + </Schema> + <Schema name="\Printer.Consumables.MagentaInk:Type"> + <BIDI_STRING>InkSupply</BIDI_STRING> + </Schema> + <Schema name="\Printer.Consumables.PrintHead:Installed"> + <BIDI_BOOL>true</BIDI_BOOL> + </Schema> + <Schema name="\Printer.Consumables.PrintHead:Level"> + <BIDI_INT>-1</BIDI_INT> + </Schema> + <Schema name="\Printer.Consumables.PrintHead:Type"> + <BIDI_STRING>PrintHead</BIDI_STRING> + </Schema> + <Schema name="\Printer.Consumables.YellowInk:Color"> + <BIDI_STRING>Yellow</BIDI_STRING> + </Schema> + <Schema name="\Printer.Consumables.YellowInk:Installed"> + <BIDI_BOOL>true</BIDI_BOOL> + </Schema> + <Schema name="\Printer.Consumables.YellowInk:Level"> + <BIDI_INT>87</BIDI_INT> + </Schema> + <Schema name="\Printer.Consumables.YellowInk:Type"> + <BIDI_STRING>InkSupply</BIDI_STRING> + </Schema> + </Query> +</bidi:Get> diff --git a/print/v4PrintDriverSamples/PrinterExtensionSample/PrinterExtensionLibrary/PrinterExtensionAdapters.cs b/print/v4PrintDriverSamples/PrinterExtensionSample/PrinterExtensionLibrary/PrinterExtensionAdapters.cs new file mode 100644 index 00000000..60277c61 --- /dev/null +++ b/print/v4PrintDriverSamples/PrinterExtensionSample/PrinterExtensionLibrary/PrinterExtensionAdapters.cs @@ -0,0 +1,2051 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved +// +// +// Abstract: +// +// This file contains Adapters that wrap the PrinterExtension COM Interop types. +// +using System; +using System.IO; +using System.Collections; +using System.Collections.Generic; +using System.Runtime; +using System.Runtime.InteropServices; +using Microsoft.Samples.Printing.PrinterExtension.Types; + +namespace Microsoft.Samples.Printing.PrinterExtension +{ + // The following three classes are constructable adapters for the root of the + // object model. The balance of the types will typically be interfaces. This + // choice was made so we can share the interface file between projects and enforce + // the same public surface from both the "Reference" and "Implementation" projects. + + #region PrinterExtension adapter classes + + /// <summary> + /// Wraps an COM pointer to IPrinterExtensionContext + /// </summary> + public class PrinterExtensionContext : IPrinterExtensionContext + { + /// <summary> + /// Wraps an opaque COM pointer to IPrinterExtensionContext and provides usable methods + /// </summary> + /// <param name="comContext">Opaque COM pointer to IPrinterExtensionContext</param> + public PrinterExtensionContext(Object comContext) + { + _context = (PrinterExtensionLib.IPrinterExtensionContext)comContext; + } + + #region IPrinterExtensionContext methods + + /// <summary> + /// Maps to COM IPrinterExtensionContext::PrinterQueue + /// </summary> + public IPrinterQueue Queue + { + get { return new PrinterQueue(_context.PrinterQueue); } + } + + /// <summary> + /// Maps to COM IPrinterExtensionContext::PrintSchemaTicket + /// </summary> + public IPrintSchemaTicket Ticket + { + get { return new PrintSchemaTicket(_context.PrintSchemaTicket); } + } + + /// <summary> + /// Maps to COM IPrinterExtensionContext::DriverProperties + /// </summary> + public IPrinterPropertyBag DriverProperties + { + get + { + try + { + return new PrinterPropertyBag(_context.DriverProperties, PrintPropertyBagType.DriverProperties); + } + catch (Exception) + { + // If the property bag is not found, instead of + // throwing an exception, return null, which is more appropriate for a property 'get' operation. + return null; + } + } + } + + /// <summary> + /// Maps to COM IPrinterExtensionContext::UserProperties + /// </summary> + public IPrinterPropertyBag UserProperties + { + get { return new PrinterPropertyBag(_context.UserProperties, PrintPropertyBagType.UserProperties); } + } + + #endregion + + #region Implementation details + + private PrinterExtensionLib.IPrinterExtensionContext _context; + + // Prevent default construction + private PrinterExtensionContext() + { + } + + #endregion + } + + /// <summary> + /// Wraps an COM pointer to IPrinterExtensionEventArgs + /// </summary> + public class PrinterExtensionEventArgs : EventArgs, IPrinterExtensionEventArgs + { + /// <summary> + /// Wraps an opaque COM pointer to IPrinterExtensionEventArgs and provides usable methods + /// </summary> + /// <param name="comContext">Opaque COM pointer to IPrinterExtensionEventArgs</param> + public PrinterExtensionEventArgs(Object eventArgs) + { + _eventArgs = (PrinterExtensionLib.IPrinterExtensionEventArgs)eventArgs; + _context = new PrinterExtensionContext(eventArgs); + } + + #region IPrinterExtensionEventArgs methods + + /// <summary> + /// Maps to COM IPrinterExtensionEventArgs::BidiNotification + /// </summary> + public string BidiNotification + { + get { return _eventArgs.BidiNotification; } + } + + /// <summary> + /// Maps to COM IPrinterExtensionEventArgs::ReasonId + /// </summary> + public Guid ReasonId + { + get { return _eventArgs.ReasonId; } + } + + /// <summary> + /// Maps to COM IPrinterExtensionEventArgs::Request + /// </summary> + public IPrinterExtensionRequest Request + { + get { return new PrinterExtensionRequest(_eventArgs.Request); } + } + + /// <summary> + /// Maps to COM IPrinterExtensionEventArgs::SourceApplication + /// </summary> + public string SourceApplication + { + get { return _eventArgs.SourceApplication; } + } + + /// <summary> + /// Maps to COM IPrinterExtensionEventArgs::DetailedReasonId + /// </summary> + public Guid DetailedReasonId + { + get { return _eventArgs.DetailedReasonId; } + } + + /// <summary> + /// Maps to COM IPrinterExtensionEventArgs::WindowModal + /// </summary> + public bool WindowModal + { + get + { + if (_eventArgs.WindowModal != 0) + { + return true; + } + return false; + } + } + + /// <summary> + /// Maps to COM IPrinterExtensionEventArgs::WindowParent + /// </summary> + public IntPtr WindowParent + { + get { return _eventArgs.WindowParent; } + } + + #endregion + + #region IPrinterExtensionContext methods + + /// <summary> + /// Maps to COM IPrinterExtensionContext::PrinterQueue + /// </summary> + public IPrinterQueue Queue + { + get { return _context.Queue; } + } + + /// <summary> + /// Maps to COM IPrinterExtensionContext::PrintSchemaTicket + /// </summary> + public IPrintSchemaTicket Ticket + { + get { return _context.Ticket; } + } + + /// <summary> + /// Maps to COM IPrinterExtensionContext::DriverProperties + /// </summary> + public IPrinterPropertyBag DriverProperties + { + get { return _context.DriverProperties; } + } + + /// <summary> + /// Maps to COM IPrinterExtensionContext::UserProperties + /// </summary> + public IPrinterPropertyBag UserProperties + { + get { return _context.UserProperties; } + } + + #endregion + + #region Implementation details + + private PrinterExtensionLib.IPrinterExtensionEventArgs _eventArgs; + + /// <summary> + /// Containment - since multiple inheritance is not possible in C#. + /// </summary> + private PrinterExtensionContext _context; + + #endregion + } + + /// <summary> + /// This class provides wraps IPrinterExtensionContextCollection in a IEnumerable interface + /// </summary> + public sealed class PrinterQueuesEnumeratedEventArgs : EventArgs, IEnumerable<IPrinterExtensionContext> + { + + #region IEnumerable<IPrinterExtensionContext> methods + + public IEnumerator<IPrinterExtensionContext> GetEnumerator() + { + for (uint i = 0; i < _contextCollection.Count; i++) + { + yield return new PrinterExtensionContext(_contextCollection.GetAt(i)); + } + } + + IEnumerator IEnumerable.GetEnumerator() + { + return (IEnumerator)GetEnumerator(); + } + + #endregion + + #region Implementation details + + internal PrinterQueuesEnumeratedEventArgs(PrinterExtensionLib.IPrinterExtensionContextCollection contextCollection) + { + _contextCollection = contextCollection; + } + + private PrinterExtensionLib.IPrinterExtensionContextCollection _contextCollection; + + #endregion + } + +#if WINDOWS_81_APIS + internal sealed class PrinterExtensionAsyncOperation : IPrinterExtensionAsyncOperation + { + #region IPrinterExtensionAsyncOperation methods + + public void Cancel() + { + _asyncOperation.Cancel(); + } + + #endregion + + #region Implementation methods + + internal PrinterExtensionAsyncOperation(PrinterExtensionLib.IPrinterExtensionAsyncOperation asyncOperation) + { + _asyncOperation = asyncOperation; + } + + private PrinterExtensionLib.IPrinterExtensionAsyncOperation _asyncOperation; + + #endregion + } +#endif + #endregion + + #region COM Adapter Classes + + // + // The following class provide an adapter that exposes a 'Stream' and wraps a + // COM pointer to PrinterExtensionLib.IStream + // + internal class PrinterExtensionLibIStreamAdapter : Stream, IDisposable + { + public PrinterExtensionLibIStreamAdapter(PrinterExtensionLib.IStream stream, bool canWrite = false, bool canSeek = false, bool canRead = true) + { + if (stream != null) + { + _printerExtensionIStream = stream; + } + else + { + throw new ArgumentNullException("stream"); + } + _streamValidation = new StreamValidation(canWrite, canSeek, canRead); + } + + ~PrinterExtensionLibIStreamAdapter() + { + Dispose(false); + } + + #region Overridden Stream methods + + public override int Read(byte[] buffer, int offset, int count) + { + _streamValidation.ValidateRead(buffer, offset, count); + + uint bytesRead = 0; + + // Pin the byte array so that it will not be moved by the garbage collector + byte[] tempBuffer = new byte[count]; + GCHandle gcHandle = GCHandle.Alloc(tempBuffer, GCHandleType.Pinned); + try + { + _printerExtensionIStream.RemoteRead(out tempBuffer[0], Convert.ToUInt32(count), out bytesRead); + + Array.Copy(tempBuffer, 0, buffer, offset, (int)bytesRead); // Safe to cast. Cannot be bigger than 'int count' + } + finally + { + gcHandle.Free(); + } + + return (int)bytesRead; // Safe to cast; bytesRead can never be larger than 'int count' + } + + public override void Write(byte[] buffer, int offset, int count) + { + _streamValidation.ValidateWrite(buffer, offset, count); + + uint written; + + // Pin the byte array so that it will not be moved by the garbage collector + byte[] tempBuffer = new byte[count]; + GCHandle gcHandle = GCHandle.Alloc(tempBuffer, GCHandleType.Pinned); + try + { + Array.Copy(buffer, offset, tempBuffer, 0, count); + _printerExtensionIStream.RemoteWrite(ref tempBuffer[0], Convert.ToUInt32(count), out written); + } + finally + { + gcHandle.Free(); + } + + if ((int)written < count) + { + throw new IOException(); + } + } + + public override long Seek(long offset, SeekOrigin origin) + { + _streamValidation.ValidateSeek(offset, origin); + + uint istreamSeekOrigin = 0; + + switch (origin) + { + case SeekOrigin.Begin: + istreamSeekOrigin = (uint)PrinterExtensionLib.tagSTREAM_SEEK.STREAM_SEEK_SET; + break; + + case SeekOrigin.Current: + istreamSeekOrigin = (uint)PrinterExtensionLib.tagSTREAM_SEEK.STREAM_SEEK_CUR; + break; + + case SeekOrigin.End: + istreamSeekOrigin = (uint)PrinterExtensionLib.tagSTREAM_SEEK.STREAM_SEEK_END; + break; + } + + PrinterExtensionLib._LARGE_INTEGER dlibMove; + PrinterExtensionLib._ULARGE_INTEGER plibNewPosition; + + dlibMove.QuadPart = offset; + + _printerExtensionIStream.RemoteSeek(dlibMove, istreamSeekOrigin, out plibNewPosition); + return Convert.ToInt64(plibNewPosition.QuadPart); + } + + public override long Length + { + get + { + _streamValidation.ValidateSeek(); + + PrinterExtensionLib.tagSTATSTG statstg; + _printerExtensionIStream.Stat(out statstg, 1 /* STATSFLAG_NONAME*/ ); + return Convert.ToInt64(statstg.cbSize.QuadPart); + } + } + public override long Position + { + get { return Seek(0, SeekOrigin.Current); } + set { Seek(value, SeekOrigin.Begin); } + } + + public override void SetLength(long value) + { + _streamValidation.ValidateSeek(); + + PrinterExtensionLib._ULARGE_INTEGER libNewSize; + libNewSize.QuadPart = Convert.ToUInt64(value); + _printerExtensionIStream.SetSize(libNewSize); + } + + public override void Flush() + { + _printerExtensionIStream.Commit(0); + } + + public override bool CanRead + { + get { return _streamValidation.CanRead; } + } + + public override bool CanWrite + { + get { return _streamValidation.CanWrite; } + } + + public override bool CanSeek + { + get { return _streamValidation.CanSeek; } + } + + #endregion + + #region IDisposable methods + + protected override void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + + try + { + if (disposing) + { + _streamValidation.Dispose(); + } + + if (_printerExtensionIStream != null) + { + Marshal.ReleaseComObject(_printerExtensionIStream); + _printerExtensionIStream = null; + } + } + finally + { + base.Dispose(disposing); + } + _disposed = true; + } + + #endregion + + #region Implementation details + + // Prevent default construction + private PrinterExtensionLibIStreamAdapter() { } + + private bool _disposed = false; + private PrinterExtensionLib.IStream _printerExtensionIStream = null; + private StreamValidation _streamValidation = null; + + #endregion + } + + + // + // The following class provide an adapter that exposes a 'Stream' and wraps a + // COM pointer to the standard COM 'IStream' interface + // + internal class ComIStreamAdapter : Stream, IDisposable + { + public ComIStreamAdapter(System.Runtime.InteropServices.ComTypes.IStream stream, bool canWrite = false, bool canSeek = false, bool canRead = true) + { + if (stream != null) + { + _comIstream = stream; + } + else + { + throw new ArgumentNullException("stream"); + } + _streamValidation = new StreamValidation(canWrite, canSeek, canRead); + } + + ~ComIStreamAdapter() + { + Dispose(false); + } + + #region Overridden Stream methods + + public override int Read(byte[] buffer, int offset, int count) + { + _streamValidation.ValidateRead(buffer, offset, count); + + uint bytesRead = 0; + + // Pin the byte array so that it will not be moved by the garbage collector + byte[] tempBuffer = new byte[count]; + GCHandle gcHandle = GCHandle.Alloc(tempBuffer, GCHandleType.Pinned); + IntPtr bytesReadPtr = Marshal.AllocHGlobal(sizeof(int)); + try + { + _comIstream.Read(tempBuffer, count, bytesReadPtr); + bytesRead = (uint)Marshal.ReadInt32(bytesReadPtr); + + Array.Copy(tempBuffer, 0, buffer, offset, (int)bytesRead); // Safe to cast. Cannot be bigger than 'int count' + } + finally + { + Marshal.FreeHGlobal(bytesReadPtr); + gcHandle.Free(); + } + + return (int)bytesRead; // Safe to cast; bytesRead can never be larger than 'int count' + } + + public override void Write(byte[] buffer, int offset, int count) + { + _streamValidation.ValidateWrite(buffer, offset, count); + + uint written; + + // Pin the byte array so that it will not be moved by the garbage collector + byte[] tempBuffer = new byte[count]; + GCHandle gcHandle = GCHandle.Alloc(tempBuffer, GCHandleType.Pinned); + IntPtr writeCountPointer = Marshal.AllocHGlobal(sizeof(int)); + try + { + Array.Copy(buffer, offset, tempBuffer, 0, count); + + _comIstream.Write(tempBuffer, count, writeCountPointer); + written = (uint)Marshal.ReadInt32(writeCountPointer); // safe to cast. 'written' is always non-negative + } + finally + { + gcHandle.Free(); + Marshal.FreeHGlobal(writeCountPointer); + } + + if ((int)written < count) + { + throw new IOException(); + } + } + + public override long Seek(long offset, SeekOrigin origin) + { + _streamValidation.ValidateSeek(offset, origin); + + uint istreamSeekOrigin = 0; + + switch (origin) + { + case SeekOrigin.Begin: + istreamSeekOrigin = (uint)PrinterExtensionLib.tagSTREAM_SEEK.STREAM_SEEK_SET; + break; + + case SeekOrigin.Current: + istreamSeekOrigin = (uint)PrinterExtensionLib.tagSTREAM_SEEK.STREAM_SEEK_CUR; + break; + + case SeekOrigin.End: + istreamSeekOrigin = (uint)PrinterExtensionLib.tagSTREAM_SEEK.STREAM_SEEK_END; + break; + } + + IntPtr seekPositionPointer = Marshal.AllocHGlobal(sizeof(long)); + long seekPosition = 0; + try + { + _comIstream.Seek(offset, (int)istreamSeekOrigin, seekPositionPointer); + seekPosition = Marshal.ReadInt64(seekPositionPointer); + } + finally + { + Marshal.FreeHGlobal(seekPositionPointer); + } + + return seekPosition; + } + + public override long Length + { + get + { + _streamValidation.ValidateSeek(); + + System.Runtime.InteropServices.ComTypes.STATSTG statstg; + _comIstream.Stat(out statstg, 1 /* STATSFLAG_NONAME*/ ); + return statstg.cbSize; + } + } + public override long Position + { + get { return Seek(0, SeekOrigin.Current); } + set { Seek(value, SeekOrigin.Begin); } + } + + public override void SetLength(long value) + { + _streamValidation.ValidateSeek(); + _comIstream.SetSize(value); + } + + public override void Flush() + { + _comIstream.Commit(0); + } + + public override bool CanRead + { + get { return _streamValidation.CanRead; } + } + + public override bool CanWrite + { + get { return _streamValidation.CanWrite; } + } + + public override bool CanSeek + { + get { return _streamValidation.CanSeek; } + } + + #endregion + + #region IDisposable methods + + protected override void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + + try + { + if (disposing) + { + _streamValidation.Dispose(); + } + + if (_comIstream != null) + { + Marshal.ReleaseComObject(_comIstream); + _comIstream = null; + } + } + finally + { + base.Dispose(disposing); + } + _disposed = true; + } + + #endregion + + #region Implementation details + + // Prevent default construction + private ComIStreamAdapter() { } + + private bool _disposed = false; + private System.Runtime.InteropServices.ComTypes.IStream _comIstream = null; + private StreamValidation _streamValidation = null; + + #endregion + } + + internal class StreamValidation : IDisposable + { + internal StreamValidation(bool canWrite = false, bool canSeek = false, bool canRead = true) + { + _canWrite = canWrite; + _canSeek = canSeek; + _canRead = canRead; + } + + internal void ValidateRead(byte[] buffer, int offset, int count) + { + if (!_canRead) + { + throw new NotSupportedException(); + } + if (_disposed == true) + { + throw new ObjectDisposedException("COM IStream"); + } + if (buffer == null) + { + throw new ArgumentNullException("buffer"); + } + if (offset < 0) + { + throw new ArgumentOutOfRangeException("offset"); + } + if (count < 0) + { + throw new ArgumentOutOfRangeException("count"); + } + if ((buffer.Length - offset) < count) + { + throw new ArgumentException(); + } + } + + internal void ValidateWrite(byte[] buffer, int offset, int count) + { + if (!_canWrite) + { + throw new NotSupportedException(); + } + if (_disposed == true) + { + throw new ObjectDisposedException("COM IStream"); + } + if (buffer == null) + { + throw new ArgumentNullException("buffer"); + } + if (offset < 0) + { + throw new ArgumentOutOfRangeException("offset"); + } + if (count < 0) + { + throw new ArgumentOutOfRangeException("count"); + } + if ((buffer.Length - offset) < count) + { + throw new ArgumentException("Insufficient buffer size"); + } + } + + internal void ValidateSeek(long offset, SeekOrigin origin) + { + ValidateSeek(); + if ((origin < SeekOrigin.Begin) || (origin > SeekOrigin.End)) + { + throw new ArgumentException("Invalid value", "origin"); + } + } + + internal void ValidateSeek() + { + if (!_canSeek) + { + throw new NotSupportedException(); + } + if (_disposed == true) + { + throw new ObjectDisposedException("COM IStream"); + } + } + + public bool CanRead + { + get { return _canRead; } + } + + public bool CanWrite + { + get { return _canWrite; } + } + + public bool CanSeek + { + get { return _canSeek; } + } + + #region IDisposable methods + + public void Dispose() + { + _disposed = true; + } + + #endregion + + #region Implementation details + + private bool _disposed = false; + private bool _canWrite = false; + private bool _canSeek = false; + private bool _canRead = true; + + #endregion + } + + #endregion + + #region PrintSchema Adapter Classes + + // + // Following are concrete implementation of the PrinterExtension interfaces + // These classes wrap the underlying COM interfaces. + // + + internal class PrintSchemaOption : IPrintSchemaOption + { + + #region IPrintSchemaOption methods + + public bool Selected + { + get { return (0 == _option.Selected) ? false : true; } + } + + public PrintSchemaConstrainedSetting Constrained + { + get { return (PrintSchemaConstrainedSetting)_option.Constrained; } + } + + #endregion + + #region IPrintSchemaDisplayableElement methods + + public string DisplayName { get { return _option.DisplayName; } } + public string Name { get { return _option.Name; } } + public string XmlNamespace { get { return _option.NamespaceUri; } } + + #endregion + + #region Implementation details + + internal PrintSchemaOption(PrinterExtensionLib.IPrintSchemaOption option) + { + _option = option; + } + + internal PrinterExtensionLib.IPrintSchemaOption InteropOption + { + get { return _option; } + set { _option = value; } + } + + // + // Create the correct 'PrintSchemaOption' subclass, possibly exposing one of the these interfaces + // 1. IPrintSchemaPageMediaSizeOption + // 2. IPrintSchemaNUpOption + // + internal static IPrintSchemaOption CreateOptionSubclass(PrinterExtensionLib.IPrintSchemaOption option) + { + // IPrintSchemaNUpOption option + if (option is PrinterExtensionLib.IPrintSchemaNUpOption) + { + return new PrintSchemaNUpOption(option); + } + + // IPrintSchemaPageMediaSizeOption option + if (option is PrinterExtensionLib.IPrintSchemaPageMediaSizeOption) + { + return new PrintSchemaPageMediaSizeOption(option); + } + + return new PrintSchemaOption(option); + } + + internal PrinterExtensionLib.IPrintSchemaOption _option; + + // Prevent default constuction + private PrintSchemaOption() { } + + #endregion + } + + internal sealed class PrintSchemaPageMediaSizeOption : PrintSchemaOption, IPrintSchemaPageMediaSizeOption + { + #region IPrintSchemaPageMediaSizeOption methods + + public uint HeightInMicrons + { + get { return _pageMediaSizeOption.HeightInMicrons; } + } + + public uint WidthInMicrons + { + get { return _pageMediaSizeOption.WidthInMicrons; } + } + + #endregion + + #region Implementation details + + internal PrintSchemaPageMediaSizeOption(PrinterExtensionLib.IPrintSchemaOption option) + : base(option) + { + _pageMediaSizeOption = _option as PrinterExtensionLib.IPrintSchemaPageMediaSizeOption; + if (null == _pageMediaSizeOption) + { + throw new NotImplementedException("Could not retrieve IPrintSchemaPageMediaSizeOption interface."); + } + } + + private PrinterExtensionLib.IPrintSchemaPageMediaSizeOption _pageMediaSizeOption; + + #endregion + } + + internal sealed class PrintSchemaNUpOption : PrintSchemaOption, IPrintSchemaNUpOption + { + #region IPrintSchemaNUpOption methods + + public uint PagesPerSheet + { + get { return _nupOption.PagesPerSheet; } + } + + #endregion + + #region Implementation details + + internal PrintSchemaNUpOption(PrinterExtensionLib.IPrintSchemaOption option) : + base(option) + { + _nupOption = _option as PrinterExtensionLib.IPrintSchemaNUpOption; + if (null == _nupOption) + { + throw new NotImplementedException("Could not retrieve IPrintSchemaNUpOption interface."); + } + } + + private PrinterExtensionLib.IPrintSchemaNUpOption _nupOption; + + #endregion + } + + /// <summary> + /// This class provides wraps IPrintSchemaOptionCollection in a IEnumerable interface + /// </summary> + internal sealed class PrintSchemaOptionsCollection : IEnumerable<IPrintSchemaOption> + { + + #region IEnumerable<IPrintSchemaOption> methods + + public IEnumerator<IPrintSchemaOption> GetEnumerator() + { + for (uint i = 0; i < _optionCollection.Count; i++) + { + yield return new PrintSchemaOption(_optionCollection.GetAt(i)); + } + } + + IEnumerator IEnumerable.GetEnumerator() + { + return (IEnumerator)GetEnumerator(); + } + + #endregion + + #region Implementation details + + internal PrintSchemaOptionsCollection(PrinterExtensionLib.IPrintSchemaOptionCollection optionCollection) + { + _optionCollection = optionCollection; + } + + private PrinterExtensionLib.IPrintSchemaOptionCollection _optionCollection; + + #endregion + } + + internal sealed class PrintSchemaFeature : IPrintSchemaFeature + { + #region IPrintSchemaFeature methods + + public PrintSchemaSelectionType SelectionType + { + get { return (PrintSchemaSelectionType)_feature.SelectionType; } + } + + public IPrintSchemaOption GetOption(string name) + { + return GetOption(name, PrintSchemaConstants.KeywordsNamespaceUri); + } + + public IPrintSchemaOption GetOption(string name, string xmlNamespace) + { + PrinterExtensionLib.IPrintSchemaOption option = _feature.GetOption(name, xmlNamespace); + if (option != null) + { + return PrintSchemaOption.CreateOptionSubclass(option); + } + + return null; + } + + public IPrintSchemaOption SelectedOption + { + get + { + return PrintSchemaOption.CreateOptionSubclass(_feature.SelectedOption); + } + set + { + _feature.SelectedOption = (value as PrintSchemaOption).InteropOption; + } + } + + public bool DisplayUI + { + get + { + return (0 == _feature.DisplayUI) ? false : true; + } + } + + #endregion + + #region IPrintSchemaDisplayableElement methods + + public string DisplayName { get { return _feature.DisplayName; } } + public string Name { get { return _feature.Name; } } + public string XmlNamespace { get { return _feature.NamespaceUri; } } + + #endregion + + #region Implementation details + + internal PrintSchemaFeature(PrinterExtensionLib.IPrintSchemaFeature feature) + { + _feature = feature; + } + + internal PrinterExtensionLib.IPrintSchemaFeature InteropFeature + { + get { return _feature; } + } + + private PrinterExtensionLib.IPrintSchemaFeature _feature; + + #endregion + } + + internal sealed class PrintSchemaPageImageableSize : IPrintSchemaPageImageableSize + { + #region IPrintSchemaPageImageableSize methods + + public uint ExtentHeightInMicrons + { + get { return _pageImageableSize.ExtentHeightInMicrons; } + } + + public uint ExtentWidthInMicrons + { + get { return _pageImageableSize.ExtentWidthInMicrons; } + } + + public uint ImageableSizeHeightInMicrons + { + get { return _pageImageableSize.ImageableSizeHeightInMicrons; } + } + + public uint ImageableSizeWidthInMicrons + { + get { return _pageImageableSize.ImageableSizeWidthInMicrons; } + } + + public uint OriginHeightInMicrons + { + get { return _pageImageableSize.OriginHeightInMicrons; } + } + + public uint OriginWidthInMicrons + { + get { return _pageImageableSize.OriginWidthInMicrons; } + } + + #endregion + + #region IPrintSchemaElement methods + + public string Name { get { return _pageImageableSize.Name; } } + public string XmlNamespace { get { return _pageImageableSize.NamespaceUri; } } + + #endregion + + #region Implementation details + + internal PrintSchemaPageImageableSize(PrinterExtensionLib.IPrintSchemaPageImageableSize pageImageableSize) + { + _pageImageableSize = pageImageableSize; + } + + private PrinterExtensionLib.IPrintSchemaPageImageableSize _pageImageableSize; + + #endregion + } + +#if WINDOWS_81_APIS + internal sealed class PrintSchemaParameterDefinition : IPrintSchemaParameterDefinition + { + #region IPrintSchemaParameterDefinition methods + + public bool UserInputRequired + { + get + { + if (_parameter.UserInputRequired != 0) + { + return true; + } + return false; + } + } + + public string UnitType + { + get { return _parameter.UnitType; } + } + + public PrintSchemaParameterDataType DataType + { + get { return (PrintSchemaParameterDataType)_parameter.DataType; } + } + + public int RangeMin + { + get { return _parameter.RangeMin; } + } + + public int RangeMax + { + get { return _parameter.RangeMax; } + } + #endregion + + #region IPrintSchemaDisplayableItem methods + + public string DisplayName { get { return _parameter.DisplayName; } } + public string Name { get { return _parameter.Name; } } + public string XmlNamespace { get { return _parameter.NamespaceUri; } } + + #endregion + + #region Implementation details + + internal PrintSchemaParameterDefinition(PrinterExtensionLib.IPrintSchemaParameterDefinition parameter) + { + _parameter = parameter; + } + + private PrinterExtensionLib.IPrintSchemaParameterDefinition _parameter; + + #endregion + } + + internal sealed class PrintSchemaParameterInitializer : IPrintSchemaParameterInitializer + { + #region IPrintSchemaParameterInitializer methods + + public string StringValue + { + get + { + object value = _parameter.get_Value(); + return (string)value; + } + set + { + _parameter.set_Value(value); + } + } + + public int IntegerValue + { + get + { + object value = _parameter.get_Value(); + return (int)value; + } + set + { + _parameter.set_Value(value); + } + } + #endregion + + #region IPrintSchemaElement methods + + public string Name { get { return _parameter.Name; } } + public string XmlNamespace { get { return _parameter.NamespaceUri; } } + + #endregion + + #region Implementation details + + internal PrintSchemaParameterInitializer(PrinterExtensionLib.IPrintSchemaParameterInitializer parameter) + { + _parameter = parameter; + } + + PrinterExtensionLib.IPrintSchemaParameterInitializer _parameter; + + #endregion + } +#endif + + internal sealed class PrintSchemaCapabilities : IPrintSchemaCapabilities + { + #region IPrintSchemaCapabilities methods + + public IPrintSchemaFeature GetFeatureByKeyName(string keyName) + { + PrinterExtensionLib.IPrintSchemaFeature feature = _capabilities.GetFeatureByKeyName(keyName); + if (feature != null) + { + return new PrintSchemaFeature(feature); + } + + return null; + } + + public IPrintSchemaFeature GetFeature(string featureName) + { + return GetFeature(featureName, PrintSchemaConstants.KeywordsNamespaceUri); + } + + public IPrintSchemaFeature GetFeature(string featureName, string xmlNamespace) + { + PrinterExtensionLib.IPrintSchemaFeature feature = _capabilities.GetFeature(featureName, xmlNamespace); + if (feature != null) + { + return new PrintSchemaFeature(feature); + } + + return null; + } + + public IPrintSchemaPageImageableSize PageImageableSize + { + get { return new PrintSchemaPageImageableSize(_capabilities.PageImageableSize); } + } + + public uint JobCopiesAllDocumentsMaxValue + { + get + { + uint value = _capabilities.JobCopiesAllDocumentsMaxValue; + if (value == 0) + { + throw new NotSupportedException("Property \"JobCopiesAllDocumentsMaxValue\" not found in print capabilities."); + } + + return value; + } + } + + public uint JobCopiesAllDocumentsMinValue + { + get + { + uint value = _capabilities.JobCopiesAllDocumentsMinValue; + if (value == 0) + { + throw new NotSupportedException("Property \"JobCopiesAllDocumentsMinValue\" not found in print capabilities."); + } + + return value; + } + } + + public IPrintSchemaOption GetSelectedOptionInPrintTicket(IPrintSchemaFeature feature) + { + PrintSchemaFeature f = feature as PrintSchemaFeature; + PrinterExtensionLib.IPrintSchemaOption option = _capabilities.GetSelectedOptionInPrintTicket(f.InteropFeature); + + if (option != null) + { + return PrintSchemaOption.CreateOptionSubclass(option); + } + + return null; + } + + public IEnumerable<IPrintSchemaOption> GetOptions(IPrintSchemaFeature pFeature) + { + return new PrintSchemaOptionsCollection( + _capabilities.GetOptions( + (pFeature as PrintSchemaFeature).InteropFeature) + ); + } + + public Stream GetReadStream() + { + return new ComIStreamAdapter(XmlStream, + false, // canWrite + true, // canSeek + true // canRead + ); + } + + public Stream GetWriteStream() + { + return new ComIStreamAdapter(XmlStream, + true, // canWrite + true, // canSeek + false // canRead + ); + } + +#if WINDOWS_81_APIS + public IPrintSchemaParameterDefinition GetParameterDefinition(string parameterName) + { + return GetParameterDefinition(parameterName, PrintSchemaConstants.KeywordsNamespaceUri); + } + + public IPrintSchemaParameterDefinition GetParameterDefinition(string parameterName, string xmlNamespace) + { + PrinterExtensionLib.IPrintSchemaParameterDefinition parameter = _capabilities2.GetParameterDefinition(parameterName, xmlNamespace); + if (parameter != null) + { + return new PrintSchemaParameterDefinition(parameter); + } + + return null; + } +#endif + + private System.Runtime.InteropServices.ComTypes.IStream XmlStream + { + get + { + System.Runtime.InteropServices.ComTypes.IStream istream = _capabilities.XmlNode as System.Runtime.InteropServices.ComTypes.IStream; + + return istream; + } + } + + #endregion + + #region Implementation details + + internal PrintSchemaCapabilities(PrinterExtensionLib.IPrintSchemaCapabilities caps) + { + _capabilities = caps; +#if WINDOWS_81_APIS + _capabilities2 = (PrinterExtensionLib.IPrintSchemaCapabilities2)caps; +#endif + } + + private PrinterExtensionLib.IPrintSchemaCapabilities _capabilities; +#if WINDOWS_81_APIS + private PrinterExtensionLib.IPrintSchemaCapabilities2 _capabilities2; +#endif + #endregion + } + + internal class PrintSchemaAsyncOperation : IPrintSchemaAsyncOperation + { + #region IPrintSchemaAsyncOperation methods + + public void Cancel() + { + _asyncOperation.Cancel(); + } + + public void Start() + { + _asyncOperation.Start(); + } + + public event EventHandler<PrintSchemaAsyncOperationEventArgs> Completed; + + #endregion + + #region Implementation details + + internal PrintSchemaAsyncOperation(PrinterExtensionLib.PrintSchemaAsyncOperation asyncOperation) + { + _asyncOperation = asyncOperation; + _asyncOperation.Completed += _asyncOperation_Completed; + } + + void _asyncOperation_Completed(PrinterExtensionLib.IPrintSchemaTicket printTicket, int hrOperation) + { + if (Completed != null) + { + IPrintSchemaTicket ticket = new PrintSchemaTicket(printTicket); + Completed(this, new PrintSchemaAsyncOperationEventArgs(ticket, hrOperation)); + } + + // This subscriber object (current object) holds a reference to the publishing object (i.e the underlying COM object) + // because it is a class member, and the publishing object holds a reference to the subscriber via the registered delegate. + // This implies neither object will be garbage collected until the application terminates. + // It's expected the event is fired once per instance so unsubscribing the delegate has no side effects. + _asyncOperation.Completed -= _asyncOperation_Completed; + Marshal.ReleaseComObject(_asyncOperation); + _asyncOperation = null; + } + + private PrinterExtensionLib.PrintSchemaAsyncOperation _asyncOperation; + + #endregion + } + + internal class PrintSchemaTicket : IPrintSchemaTicket + { + + #region IPrintSchemaTicket methods + + public IPrintSchemaCapabilities GetCapabilities() + { + return new PrintSchemaCapabilities(_printTicket.GetCapabilities()); + } + + public IPrintSchemaFeature GetFeature(string featureName) + { + return GetFeature(featureName, PrintSchemaConstants.KeywordsNamespaceUri); + } + + public IPrintSchemaFeature GetFeature(string featureName, string xmlNamespace) + { + PrinterExtensionLib.IPrintSchemaFeature feature = _printTicket.GetFeature(featureName, xmlNamespace); + if (feature != null) + { + return new PrintSchemaFeature(feature); + } + + return null; + } + + public IPrintSchemaFeature GetFeatureByKeyName(string keyName) + { + PrinterExtensionLib.IPrintSchemaFeature feature = _printTicket.GetFeatureByKeyName(keyName); + if (feature != null) + { + return new PrintSchemaFeature(feature); + } + + return null; + } + + public uint JobCopiesAllDocuments + { + get + { + uint value = _printTicket.JobCopiesAllDocuments; + if (value == 0) + { + throw new NotSupportedException("Property \"JobCopiesAllDocuments\" not found in print ticket."); + } + + return value; + } + set + { + _printTicket.JobCopiesAllDocuments = value; + } + } + + public Stream GetReadStream() + { + return new ComIStreamAdapter(XmlStream, + false, // canWrite + true, // canSeek + true // canRead + ); + } + + public Stream GetWriteStream() + { + return new ComIStreamAdapter(XmlStream, + true, // canWrite + true, // canSeek + false // canRead + ); + } + + private System.Runtime.InteropServices.ComTypes.IStream XmlStream + { + get + { + System.Runtime.InteropServices.ComTypes.IStream istream = _printTicket.XmlNode as System.Runtime.InteropServices.ComTypes.IStream; + + return istream; + } + } + + public IPrintSchemaAsyncOperation ValidateAsync() + { + PrinterExtensionLib.PrintSchemaAsyncOperation interopAsyncOperation; + _printTicket.ValidateAsync(out interopAsyncOperation); + return new PrintSchemaAsyncOperation(interopAsyncOperation); + } + + public IPrintSchemaAsyncOperation CommitAsync(IPrintSchemaTicket printTicketCommit) + { + PrinterExtensionLib.IPrintSchemaTicket interopTicket = (printTicketCommit as PrintSchemaTicket)._printTicket; + PrinterExtensionLib.PrintSchemaAsyncOperation interopAsyncOperation; + _printTicket.CommitAsync(interopTicket, out interopAsyncOperation); + return new PrintSchemaAsyncOperation(interopAsyncOperation); + } + + public void NotifyXmlChanged() + { + _printTicket.NotifyXmlChanged(); + } +#if WINDOWS_81_APIS + public IPrintSchemaParameterInitializer GetParameterInitializer(string parameterName) + { + return GetParameterInitializer(parameterName, PrintSchemaConstants.KeywordsNamespaceUri); + } + + public IPrintSchemaParameterInitializer GetParameterInitializer(string parameterName, string xmlNamespace) + { + PrinterExtensionLib.IPrintSchemaParameterInitializer parameter = _printTicket2.GetParameterInitializer(parameterName, xmlNamespace); + if (parameter != null) + { + return new PrintSchemaParameterInitializer(parameter); + } + + return null; + } +#endif + + #endregion + + #region Implementation details + + internal PrintSchemaTicket(PrinterExtensionLib.IPrintSchemaTicket printTicket) + { + _printTicket = printTicket; +#if WINDOWS_81_APIS + _printTicket2 = (PrinterExtensionLib.IPrintSchemaTicket2)printTicket; +#endif + } + + private PrinterExtensionLib.IPrintSchemaTicket _printTicket; +#if WINDOWS_81_APIS + private PrinterExtensionLib.IPrintSchemaTicket2 _printTicket2; +#endif + + #endregion + } + + internal enum PrintPropertyBagType + { + QueueProperties, + DriverProperties, + UserProperties + } + + internal class PrinterPropertyBag : IPrinterPropertyBag + { + #region IPrinterPropertyBag methods + + public bool GetBool(string propertyName) + { + try + { + int integerEquivalent = _bag.GetBool(propertyName); + bool boolEquivalent = true; + if (integerEquivalent == 0) + { + boolEquivalent = false; + } + return boolEquivalent; + } + catch (ArgumentException e) + { + // Fix the type of exception thrown when the property does not exist. + if (ShouldConvertExceptionType(e)) + { + throw new FileNotFoundException("", e); + } + throw; + } + } + + public byte[] GetBytes(string propertyName) + { + try + { + uint count = 0; + IntPtr intptrData = Marshal.AllocCoTaskMem(IntPtr.Size); + _bag.GetBytes( + propertyName, + out count, + intptrData); + + byte[] data = new byte[count]; + Marshal.Copy(Marshal.ReadIntPtr(intptrData), data, 0, (int)count); + Marshal.FreeCoTaskMem(Marshal.ReadIntPtr(intptrData)); + Marshal.FreeCoTaskMem(intptrData); + return data; + } + catch (ArgumentException e) + { + // Fix the type of exception thrown when the property does not exist. + if (ShouldConvertExceptionType(e)) + { + throw new FileNotFoundException("", e); + } + throw; + } + } + + public int GetInt(string propertyName) + { + try + { + return _bag.GetInt32(propertyName); + } + catch (ArgumentException e) + { + // Fix the type of exception thrown when the property does not exist. + if (ShouldConvertExceptionType(e)) + { + throw new FileNotFoundException("", e); + } + throw; + } + } + + public string GetString(string propertyName) + { + try + { + return _bag.GetString(propertyName); + } + catch (ArgumentException e) + { + // Fix the type of exception thrown when the property does not exist. + if (ShouldConvertExceptionType(e)) + { + throw new FileNotFoundException("", e); + } + throw; + } + } + + public void SetBool(string propertyName, bool value) + { + int integerEquivalent = 1; + if (value == false) + { + integerEquivalent = 0; + } + + _bag.SetBool(propertyName, integerEquivalent); + } + + public void SetBytes(string propertyName, byte[] data) + { + // Pin the byte array so that it will not be moved by the garbage collector + // This would not be required if the COM Interop function took in a byte[] parameter + // as opposed to a byte parameter + GCHandle gcHandle = GCHandle.Alloc(data, GCHandleType.Pinned); + try + { + _bag.SetBytes(propertyName, Convert.ToUInt32(data.Length), ref data[0]); + } + finally + { + gcHandle.Free(); + } + } + + public void SetInt(string propertyName, int value) + { + _bag.SetInt32(propertyName, value); + } + + public void SetString(string propertyName, string value) + { + _bag.SetString(propertyName, value); + } + + public Stream GetReadStream(string propertyName) + { + try + { + return new PrinterExtensionLibIStreamAdapter(_bag.GetReadStream(propertyName), false, true, true); + } + catch (COMException e) + { + // Fix the type of exception thrown when the property does not exist. + if (ShouldConvertExceptionType(e)) + { + throw new FileNotFoundException("", e); + } + throw; + } + } + + public Stream GetWriteStream(string propertyName) + { + return new PrinterExtensionLibIStreamAdapter(_bag.GetWriteStream(propertyName), true, true, false); + } + + #endregion + + #region Indexer + + public PrinterProperty this[string name] + { + get { return new PrinterProperty(this, name); } + } + + #endregion + + #region Implementation details + + internal PrinterPropertyBag(PrinterExtensionLib.IPrinterPropertyBag bag, PrintPropertyBagType type) + { + _bag = bag; + _type = type; + } + + /// <summary> + /// Check if exception thrown when a property is not found in a property bag needs to be converted. + /// </summary> + /// <param name="e"></param> + /// <returns>True if the exception type needs to be converted.</returns> + private bool ShouldConvertExceptionType(Exception e) + { + // Only the driver property bag throws exceptions other than 'FileNotFoundException' + // when a property is not found. + if (_type != PrintPropertyBagType.DriverProperties) + { + return false; + } + else if (e is ArgumentException) + { + return true; + } + else if (e is COMException) + { + // Since there is no portable way to check the HRESULT across classic .Net and + // .Net for Windows Store apps, all COMExceptions encountered are converted. + return true; + } + return false; + } + + private PrinterExtensionLib.IPrinterPropertyBag _bag; + private PrintPropertyBagType _type; + + #endregion + } + +#if WINDOWS_81_APIS + public sealed class PrintJob : IPrintJob + { + #region IPrintJob methods + + public string Name + { + get { return _job.Name; } + } + + public ulong Id + { + get { return _job.Id; } + } + + public ulong PrintedPages + { + get { return _job.PrintedPages; } + } + + public ulong TotalPages + { + get { return _job.TotalPages; } + } + + public PrintJobStatus Status + { + get { return (PrintJobStatus)_job.Status; } + } + + public DateTime SubmissionTime + { + get { return _job.SubmissionTime; } + } + + public void RequestCancel() + { + _job.RequestCancel(); + } + + #endregion + + #region Implementation details + + internal PrintJob(PrinterExtensionLib.IPrintJob job) + { + _job = job; + } + + PrinterExtensionLib.IPrintJob _job; + + #endregion + } + + /// <summary> + /// This class provides wraps IPrintJobCollection in a IEnumerable interface + /// </summary> + public sealed class PrintJobCollection : IEnumerable<IPrintJob> + { + #region IEnumerable<IPrintJob> methods + + public IEnumerator<IPrintJob> GetEnumerator() + { + for (uint i = 0; i < _jobCollection.Count; i++) + { + yield return new PrintJob(_jobCollection.GetAt(i)); + } + } + + IEnumerator IEnumerable.GetEnumerator() + { + return (IEnumerator)GetEnumerator(); + } + + #endregion + + #region Implementation details + + internal PrintJobCollection(PrinterExtensionLib.IPrintJobCollection jobCollection) + { + _jobCollection = jobCollection; + } + + private PrinterExtensionLib.IPrintJobCollection _jobCollection; + + #endregion + } + + internal sealed class PrinterQueueView : IPrinterQueueView + { + #region IPrinterQueueView methods + + public void SetViewRange(uint viewOffset, uint viewSize) + { + _view.SetViewRange(viewOffset, viewSize); + } + + public event EventHandler<PrinterQueueViewEventArgs> OnChanged + { + add + { + if (_onChanged == null) + { + _view.OnChanged += _view_OnChanged; + } + _onChanged += value; + } + remove + { + _onChanged -= value; + if (_onChanged == null) + { + _view.OnChanged -= _view_OnChanged; + } + } + } + + #endregion + + #region Implementation details + + internal PrinterQueueView(PrinterExtensionLib.PrinterQueueView view) + { + _view = view; + } + + void _view_OnChanged(PrinterExtensionLib.IPrintJobCollection pCollection, uint ulViewOffset, uint ulViewSize, uint ulCountJobsInPrintQueue) + { + if (_onChanged != null) + { + _onChanged(this, new PrinterQueueViewEventArgs(new PrintJobCollection(pCollection), ulViewOffset, ulViewSize, ulCountJobsInPrintQueue)); + } + } + + private PrinterExtensionLib.PrinterQueueView _view; + private event EventHandler<PrinterQueueViewEventArgs> _onChanged; + + #endregion + } + + internal sealed class PrinterBidiSetRequestCallback : PrinterExtensionLib.IPrinterBidiSetRequestCallback + { + #region IPrinterBidiSetRequestCallback methods + + public void Completed(string response, int statusHResult) + { + _callback.Completed(response, statusHResult); + } + + #endregion + + #region Implementation details + + internal PrinterBidiSetRequestCallback(IPrinterBidiSetRequestCallback callback) + { + _callback = callback; + } + + private IPrinterBidiSetRequestCallback _callback; + + #endregion + } +#endif + + internal sealed class PrinterQueue : IPrinterQueue + { + #region IPrinterQueue methods + + public string Name + { + get { return _queue.Name; } + } + + public void SendBidiQuery(string bidiQuery) + { + _queue.SendBidiQuery(bidiQuery); + } + + public IntPtr Handle + { + get { return _queue.Handle; } + } + + public IPrinterPropertyBag GetProperties() + { + return new PrinterPropertyBag(_queue.GetProperties(), PrintPropertyBagType.QueueProperties); + } + public event EventHandler<PrinterQueueEventArgs> OnBidiResponseReceived + { + add + { + if (_onBidiResponseReceived == null) + { + _queue.OnBidiResponseReceived += _queue_OnBidiResponseReceived; + } + _onBidiResponseReceived += value; + } + remove + { + _onBidiResponseReceived -= value; + if (_onBidiResponseReceived == null) + { + _queue.OnBidiResponseReceived -= _queue_OnBidiResponseReceived; + } + } + } + +#if WINDOWS_81_APIS + public IPrinterExtensionAsyncOperation SendBidiSetRequestAsync(string bidiRequest, IPrinterBidiSetRequestCallback callback) + { + PrinterBidiSetRequestCallback comCallback = new PrinterBidiSetRequestCallback(callback); + PrinterExtensionLib.IPrinterBidiSetRequestCallback comCallbackInterface = comCallback; + return new PrinterExtensionAsyncOperation(_queue2.SendBidiSetRequestAsync(bidiRequest, comCallbackInterface)); + } + + public IPrinterQueueView GetPrinterQueueView(uint viewOffset, uint viewSize) + { + return new PrinterQueueView(_queue2.GetPrinterQueueView(viewOffset, viewSize)); + } +#endif + + #endregion + + #region Implementation details + + internal PrinterQueue(PrinterExtensionLib.PrinterQueue queue) + { + _queue = queue; +#if WINDOWS_81_APIS + _queue2 = (PrinterExtensionLib.IPrinterQueue2)queue; +#endif + } + + private void _queue_OnBidiResponseReceived(string bstrResponse, int hrStatus) + { + if (_onBidiResponseReceived != null) + { + _onBidiResponseReceived(this, new PrinterQueueEventArgs(bstrResponse, hrStatus)); + } + } + + private event EventHandler<PrinterQueueEventArgs> _onBidiResponseReceived; +#if WINDOWS_81_APIS + private PrinterExtensionLib.IPrinterQueue2 _queue2; +#endif + private PrinterExtensionLib.PrinterQueue _queue; + + #endregion + } + + internal sealed class PrinterExtensionRequest : IPrinterExtensionRequest + { + #region IPrinterExtensionRequest methods + + public void Complete() + { + _request.Complete(); + } + + public void Cancel(int hr, string logMessage) + { + _request.Cancel(hr, logMessage); + } + + #endregion + + #region Implementation details + + internal PrinterExtensionRequest(PrinterExtensionLib.IPrinterExtensionRequest request) + { + _request = request; + } + + private PrinterExtensionLib.IPrinterExtensionRequest _request; + + #endregion + } + + #endregion +} + diff --git a/print/v4PrintDriverSamples/PrinterExtensionSample/PrinterExtensionLibrary/PrinterExtensionLibrary.csproj b/print/v4PrintDriverSamples/PrinterExtensionSample/PrinterExtensionLibrary/PrinterExtensionLibrary.csproj new file mode 100644 index 00000000..8ecb8721 --- /dev/null +++ b/print/v4PrintDriverSamples/PrinterExtensionSample/PrinterExtensionLibrary/PrinterExtensionLibrary.csproj @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <ProjectGuid>{D8DA0C4D-F972-4546-9068-8EB256F222F7}</ProjectGuid> + <DefaultLanguage>en-US</DefaultLanguage> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>Microsoft.Samples.Printing.PrinterExtension</RootNamespace> + <AssemblyName>Microsoft.Samples.Printing.PrinterExtensionLibrary</AssemblyName> + <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <!-- Silence warnings generated from all COM references. --> + <ResolveComReferenceSilent>true</ResolveComReferenceSilent> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Win8 Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Win8 Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Win8 Release|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Win8 Release\</OutputPath> + <DefineConstants>TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Win8.1 Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Win8.1 Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE;WINDOWS_81_APIS</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Win8.1 Release|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>pdbonly</DebugType> + <Optimize>true</Optimize> + <OutputPath>bin\Win8.1 Release\</OutputPath> + <DefineConstants>TRACE;WINDOWS_81_APIS</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </PropertyGroup> + <ItemGroup> + <!-- A reference to the entire .Net Framework and Windows SDK are automatically included --> + </ItemGroup> + <ItemGroup> + <Compile Include="PrinterExtensionAdapters.cs" /> + <Compile Include="PrinterExtensionTypes.cs"> + <SubType>Code</SubType> + </Compile> + <Compile Include="PrinterExtensionManager.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + </ItemGroup> + <ItemGroup> + <COMReference Include="PrinterExtensionLib"> + <Guid>{91CE54EE-C67C-4B46-A4FF-99416F27A8BF}</Guid> + <VersionMajor>1</VersionMajor> + <VersionMinor>0</VersionMinor> + <Lcid>0</Lcid> + <WrapperTool>tlbimp</WrapperTool> + <Isolated>False</Isolated> + <EmbedInteropTypes>True</EmbedInteropTypes> + </COMReference> + </ItemGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <!-- To modify your build process, add your task inside one of the targets below and uncomment it. + Other similar extension points exist, see Microsoft.Common.targets. + <Target Name="BeforeBuild"> + </Target> + <Target Name="AfterBuild"> + </Target> + --> +</Project>
\ No newline at end of file diff --git a/print/v4PrintDriverSamples/PrinterExtensionSample/PrinterExtensionLibrary/PrinterExtensionManager.cs b/print/v4PrintDriverSamples/PrinterExtensionSample/PrinterExtensionLibrary/PrinterExtensionManager.cs new file mode 100644 index 00000000..91815d6a --- /dev/null +++ b/print/v4PrintDriverSamples/PrinterExtensionSample/PrinterExtensionLibrary/PrinterExtensionManager.cs @@ -0,0 +1,121 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved +// +// +// Abstract: +// +// This file contains an Adapter that wrap the PrinterExtensionManager COM Interop type. +// +using System; +using System.IO; +using System.Collections; +using System.Collections.Generic; +using System.Runtime; +using System.Runtime.InteropServices; +using Microsoft.Samples.Printing.PrinterExtension.Types; + +namespace Microsoft.Samples.Printing.PrinterExtension +{ + public class PrinterExtensionManager + { + public PrinterExtensionManager() + { + _manager = new PrinterExtensionLib.PrinterExtensionManager(); + } + + #region IPrinterExtensionManager methods + + /// <summary> + /// Maps to COM IPrinterExtensionManager::DisableEvents + /// </summary> + public void DisableEvents() + { + _manager.DisableEvents(); + } + + /// <summary> + /// Maps to COM IPrinterExtensionManager::EnableEvents + /// </summary> + public void EnableEvents(Guid printerDriverId) + { + _manager.EnableEvents(printerDriverId); + } + + /// <summary> + /// Maps to COM IPrinterExtensionEvent::OnDriverEvent + /// </summary> + public event EventHandler<PrinterExtensionEventArgs> OnDriverEvent + { + add + { + if (_onDriverEvent == null) + { + _manager.OnDriverEvent += OnDriverEventReceiver; + } + _onDriverEvent += value; + } + remove + { + _onDriverEvent -= value; + if (_onDriverEvent == null) + { + _manager.OnDriverEvent -= OnDriverEventReceiver; + } + } + } + + /// <summary> + /// Maps to COM IPrinterExtensionEvent::OnPrinterQueuesEnumerated + /// </summary> + public event EventHandler<PrinterQueuesEnumeratedEventArgs> OnPrinterQueuesEnumerated + { + add + { + if (_onPrinterQueuesEnumerated == null) + { + _manager.OnPrinterQueuesEnumerated += OnPrinterQueuesEnumeratedReceiver; + } + _onPrinterQueuesEnumerated += value; + } + remove + { + _onPrinterQueuesEnumerated -= value; + if (_onPrinterQueuesEnumerated == null) + { + _manager.OnPrinterQueuesEnumerated -= OnPrinterQueuesEnumeratedReceiver; + } + } + } + + #endregion + + #region Implementation details + + private void OnDriverEventReceiver(PrinterExtensionLib.IPrinterExtensionEventArgs pEventArgs) + { + if (_onDriverEvent != null) + { + _onDriverEvent(this, new PrinterExtensionEventArgs(pEventArgs)); + } + } + + private void OnPrinterQueuesEnumeratedReceiver(PrinterExtensionLib.IPrinterExtensionContextCollection contextCollection) + { + if (_onPrinterQueuesEnumerated != null) + { + _onPrinterQueuesEnumerated(this, new PrinterQueuesEnumeratedEventArgs(contextCollection)); + } + } + + private event EventHandler<PrinterExtensionEventArgs> _onDriverEvent; + private event EventHandler<PrinterQueuesEnumeratedEventArgs> _onPrinterQueuesEnumerated; + + private PrinterExtensionLib.PrinterExtensionManager _manager; + + #endregion + } +}
\ No newline at end of file diff --git a/print/v4PrintDriverSamples/PrinterExtensionSample/PrinterExtensionLibrary/PrinterExtensionTypes.cs b/print/v4PrintDriverSamples/PrinterExtensionSample/PrinterExtensionLibrary/PrinterExtensionTypes.cs new file mode 100644 index 00000000..33991cde --- /dev/null +++ b/print/v4PrintDriverSamples/PrinterExtensionSample/PrinterExtensionLibrary/PrinterExtensionTypes.cs @@ -0,0 +1,921 @@ +// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF +// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A +// PARTICULAR PURPOSE. +// +// Copyright (c) Microsoft Corporation. All rights reserved +// +// +// Abstract: +// +// This file defines all types and interfaces that may be used to build a printer +// extension application. +// + +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; + +namespace Microsoft.Samples.Printing.PrinterExtension.Types +{ + // + // Enums and Constants + // + /// <summary> + /// Maps to COM PrintSchemaConstrainedSetting + /// </summary> + public enum PrintSchemaConstrainedSetting + { + None = 0, + PrintTicket = 1, + Admin = 2, + Device = 3, + } + + /// <summary> + /// Maps to COM PrintSchemaSelectionType + /// </summary> + public enum PrintSchemaSelectionType + { + PickOne = 0, + PickMany = 1 + } + +#if WINDOWS_81_APIS + /// <summary> + /// Maps to COM PrintSchemaParameterDataType + /// </summary> + public enum PrintSchemaParameterDataType + { + Integer = 0, + NumericString = 1, + String = 2 + } + + /// <summary> + /// Maps to COM PrintJobStatus + /// </summary> + [Flags] + public enum PrintJobStatus + { + Paused = 0x1, + Error = 0x2, + Deleting = 0x4, + Spooling = 0x8, + Printing = 0x10, + Offline = 0x20, + PaperOut = 0x40, + Printed = 0x80, + Deleted = 0x100, + BlockedDeviceQueue = 0x200, + UserIntervention = 0x400, + Restarted = 0x800, + Complete = 0x1000, + Retained = 0x2000, + } +#endif + + public static class PrinterExtensionReason + { + // An Enum was the first choice but the list of Guid is designed to be extendable. + // A read-only property was the second choice however this would have made new copies of the Guid. + // Using a class with static Guids balances both considerations. + + /// <summary> + /// In this mode preferences for a print job or default print preferences is expected to be displayed. + /// Maps to C++ PRINTER_EXTENSION_REASON_PRINT_PREFERENCES + /// </summary> + public static Guid PrintPreferences = new Guid("{EC8F261F-267C-469F-B5D6-3933023C29CC}"); + + + /// <summary> + /// In this mode a status monitor for the print queue is expected to be displayed. + /// Maps to C++ PRINTER_EXTENSION_REASON_DRIVER_EVENT + /// </summary> + public static Guid DriverEvent = new Guid("{23BB1328-63DE-4293-915B-A6A23D929ACB}"); + } + + public static class PrintSchemaConstants + { + /// <summary> + /// The namespace URI for the Print Schema keywords + /// </summary> + public const string KeywordsNamespaceUri = "http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords"; + /// <summary> + /// The namespace URI for the Print Schema keywords V1.1 + /// </summary> + public const string KeywordsV11NamespaceUri = "http://schemas.microsoft.com/windows/2013/05/printing/printschemakeywordsv11"; + /// <summary> + /// The namespace URI for the Print Schema Framework + /// </summary> + public const string FrameworkNamespaceUri = "http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework"; + } + + // + // Interfaces + // + + // The following interfaces are shared between the "Reference" and "Implementation" + // project. These interfaces are the public surface for the adapters that will remain + // internal to the "Implementation" project. It is done this way because the public + // surface and strong name must be the same for "Reference" and "Implementation". + + /// <summary> + /// Maps to COM IPrinterExtensionContext + /// </summary> + public interface IPrinterExtensionContext + { + /// <summary> + /// Maps to COM IPrinterExtensionContext::PrinterQueue + /// </summary> + IPrinterQueue Queue { get; } + + /// <summary> + /// Maps to COM IPrinterExtensionContext::PrintSchemaTicket + /// </summary> + IPrintSchemaTicket Ticket { get; } + + /// <summary> + /// Maps to COM IPrinterExtensionContext::DriverProperties + /// </summary> + IPrinterPropertyBag DriverProperties { get; } + + /// <summary> + /// Maps to COM IPrinterExtensionContext::UserProperties + /// </summary> + IPrinterPropertyBag UserProperties { get; } + } + + /// <summary> + /// Maps to COM IPrinterExtensionEventArgs + /// </summary> + public interface IPrinterExtensionEventArgs : IPrinterExtensionContext + { + /// <summary> + /// Maps to COM IPrinterExtensionEventArgs::BidiNotification + /// </summary> + string BidiNotification { get; } + + /// <summary> + /// Maps to COM IPrinterExtensionEventArgs::ReasonId + /// </summary> + Guid ReasonId { get; } + + + /// <summary> + /// Maps to COM IPrinterExtensionEventArgs::Request + /// </summary> + IPrinterExtensionRequest Request { get; } + + /// <summary> + /// Maps to COM IPrinterExtensionEventArgs::SourceApplication + /// </summary> + string SourceApplication { get; } + + /// <summary> + /// Maps to COM IPrinterExtensionEventArgs::DetailedReasonId + /// </summary> + Guid DetailedReasonId { get; } + + /// <summary> + /// Maps to COM IPrinterExtensionEventArgs::WindowModal + /// </summary> + bool WindowModal { get; } + + /// <summary> + /// Maps to COM IPrinterExtensionEventArgs::WindowParent + /// </summary> + IntPtr WindowParent { get; } + } + +#if WINDOWS_81_APIS + /// <summary> + /// Maps to COM IPrinterExtensionAsyncOperation + /// </summary> + public interface IPrinterExtensionAsyncOperation + { + /// <summary> + /// Maps to COM IPrinterExtensionAsyncOperation::Cancel + /// </summary> + void Cancel(); + } +#endif + + /// <summary> + /// Maps to COM IPrintSchemaElement + /// </summary> + public interface IPrintSchemaElement + { + /// <summary> + /// Maps to COM IPrintSchemaElement::Name + /// </summary> + string Name { get; } + + /// <summary> + /// Maps to COM IPrintSchemaElement::NamespaceUri + /// </summary> + string XmlNamespace { get; } + } + + /// <summary> + /// Maps to COM IPrintSchemaDisplayableElement + /// </summary> + public interface IPrintSchemaDisplayableElement : IPrintSchemaElement + { + /// <summary> + /// Maps to COM IPrintSchemaDisplayableElement::DisplayName + /// </summary> + string DisplayName { get; } + } + + /// <summary> + /// Maps to COM IPrintSchemaOption + /// </summary> + public interface IPrintSchemaOption : IPrintSchemaDisplayableElement + { + /// <summary> + /// Maps to COM IPrintSchemaOption::Selected + /// </summary> + bool Selected { get; } + + /// <summary> + /// Maps to COM IPrintSchemaOption::Constrained + /// </summary> + PrintSchemaConstrainedSetting Constrained { get; } + } + + /// <summary> + /// Maps to COM IPrintSchemaPageMediaSizeOption + /// </summary> + public interface IPrintSchemaPageMediaSizeOption : IPrintSchemaOption + { + /// <summary> + /// Maps to COM IPrintSchemaPageMediaSizeOption::HeightInMicrons + /// </summary> + uint HeightInMicrons { get; } + + /// <summary> + /// Maps to COM IPrintSchemaPageMediaSizeOption::WidthInMicrons + /// </summary> + uint WidthInMicrons { get; } + } + + /// <summary> + /// Maps to COM IPrintSchemaNUpOption + /// </summary> + public interface IPrintSchemaNUpOption : IPrintSchemaOption + { + /// <summary> + /// Maps to COM IPrintSchemaNUpOption::PagesPerSheet + /// </summary> + uint PagesPerSheet { get; } + } + + /// <summary> + /// Maps to COM IPrintSchemaFeature + /// </summary> + public interface IPrintSchemaFeature : IPrintSchemaDisplayableElement + { + /// <summary> + /// Maps to COM IPrintSchemaFeature::SelectedOption + /// </summary> + IPrintSchemaOption SelectedOption { get; set; } + + /// <summary> + /// Maps to COM IPrintSchemaFeature::SelectionType + /// </summary> + PrintSchemaSelectionType SelectionType { get; } + + /// <summary> + /// Maps to COM IPrintSchemaFeature::GetOption + /// </summary> + IPrintSchemaOption GetOption(string optionName); + + /// <summary> + /// Maps to COM IPrintSchemaFeature::GetOption + /// </summary> + IPrintSchemaOption GetOption(string optionName, string xmlNamespace); + + /// <summary> + /// Maps to COM IPrintSchemaFeature::DisplayUI + /// </summary> + bool DisplayUI { get; } + } + + /// <summary> + /// Maps to COM IPrintSchemaPageImageableSize + /// </summary> + public interface IPrintSchemaPageImageableSize : IPrintSchemaElement + { + /// <summary> + /// Maps to COM IPrintSchemaPageImageableSize::ExtentHeightInMicrons + /// </summary> + uint ExtentHeightInMicrons { get; } + + /// <summary> + /// Maps to COM IPrintSchemaPageImageableSize::ExtentWidthInMicrons + /// </summary> + uint ExtentWidthInMicrons { get; } + + /// <summary> + /// Maps to COM IPrintSchemaPageImageableSize::ImageableSizeHeightInMicrons + /// </summary> + uint ImageableSizeHeightInMicrons { get; } + + /// <summary> + /// Maps to COM IPrintSchemaPageImageableSize::ImageableSizeWidthInMicrons + /// </summary> + uint ImageableSizeWidthInMicrons { get; } + + /// <summary> + /// Maps to COM IPrintSchemaPageImageableSize::OriginHeightInMicrons + /// </summary> + uint OriginHeightInMicrons { get; } + + /// <summary> + /// Maps to COM IPrintSchemaPageImageableSize::OriginWidthInMicrons + /// </summary> + uint OriginWidthInMicrons { get; } + } + +#if WINDOWS_81_APIS + /// <summary> + /// Maps to COM IPrintSchemaParameterDefinition + /// </summary> + public interface IPrintSchemaParameterDefinition : IPrintSchemaDisplayableElement + { + /// <summary> + /// Maps to COM IPrintSchemaParameterDefinition::UserInputRequired + /// </summary> + bool UserInputRequired { get; } + + /// <summary> + /// Maps to COM IPrintSchemaParameterDefinition::UnitType + /// </summary> + string UnitType { get; } + + /// <summary> + /// Maps to COM IPrintSchemaParameterDefinition::DataType + /// </summary> + PrintSchemaParameterDataType DataType { get; } + + /// <summary> + /// Maps to COM IPrintSchemaParameterDefinition::RangeMin + /// </summary> + int RangeMin { get; } + + /// <summary> + /// Maps to COM IPrintSchemaParameterDefinition::RangeMax + /// </summary> + int RangeMax { get; } + } + + /// <summary> + /// Maps to COM IPrintSchemaParameterInitializer + /// </summary> + public interface IPrintSchemaParameterInitializer : IPrintSchemaElement + { + /// <summary> + /// Maps to COM IPrintSchemaParameterInitializer::Value + /// </summary> + string StringValue { get; set; } + /// <summary> + /// Maps to COM IPrintSchemaParameterInitializer::Value + /// </summary> + int IntegerValue { get; set; } + } +#endif + + /// <summary> + /// Maps to COM IPrintSchemaCapabilities + /// </summary> + public interface IPrintSchemaCapabilities + { + /// <summary> + /// Maps to COM IPrintSchemaCapabilities::GetFeatureByKeyName + /// </summary> + IPrintSchemaFeature GetFeatureByKeyName(string keyName); + + /// <summary> + /// Maps to COM IPrintSchemaCapabilities::GetFeature + /// </summary> + IPrintSchemaFeature GetFeature(string featureName); + + /// <summary> + /// Maps to COM IPrintSchemaCapabilities::GetFeature + /// </summary> + IPrintSchemaFeature GetFeature(string featureName, string xmlNamespace); + + /// <summary> + /// Maps to COM IPrintSchemaCapabilities::PageImageableSize + /// </summary> + IPrintSchemaPageImageableSize PageImageableSize { get; } + + /// <summary> + /// Maps to COM IPrintSchemaCapabilities::JobCopiesAllDocumentsMinValue + /// </summary> + uint JobCopiesAllDocumentsMaxValue { get; } + + /// <summary> + /// Maps to COM IPrintSchemaCapabilities::JobCopiesAllDocumentsMaxValue + /// </summary> + uint JobCopiesAllDocumentsMinValue { get; } + + /// <summary> + /// Maps to COM IPrintSchemaCapabilities::GetSelectedOptionInPrintTicket + /// </summary> + IPrintSchemaOption GetSelectedOptionInPrintTicket(IPrintSchemaFeature feature); + + /// <summary> + /// Maps to COM IPrintSchemaCapabilities::GetOptions + /// </summary> + IEnumerable<IPrintSchemaOption> GetOptions(IPrintSchemaFeature feature); + + /// <summary> + /// Replaces COM IPrintSchemaCapabilities::XmlNode + /// </summary> + Stream GetReadStream(); + + /// <summary> + /// Replaces COM IPrintSchemaCapabilities::XmlNode + /// </summary> + Stream GetWriteStream(); + +#if WINDOWS_81_APIS + /// <summary> + /// Maps to COM IPrintSchemaCapabilities2::GetParameterDefinition + /// </summary> + IPrintSchemaParameterDefinition GetParameterDefinition(string parameterName); + + /// <summary> + /// Maps to COM IPrintSchemaCapabilities2::GetParameterDefinition + /// </summary> + IPrintSchemaParameterDefinition GetParameterDefinition(string parameterName, string xmlNamespace); +#endif + } + + /// <summary> + /// The EventArgs for the PrintSchemaAsyncOperation + /// Maps to COM IPrintSchemaAsyncOperationEvent + /// </summary> + public class PrintSchemaAsyncOperationEventArgs : EventArgs + { + // + // Event arguments + // + /// <summary> + /// Maps to COM IPrintSchemaAsyncOperationEvent::Completed, parameter 'hrOperation' + /// </summary> + public int StatusHResult { get { return _statusHResult; } } + + /// <summary> + /// Maps to COM IPrintSchemaAsyncOperationEvent::Completed, parameter 'pTicket' + /// </summary> + public IPrintSchemaTicket Ticket { get { return _printTicket; } } + + // + // Implementation details + // + internal PrintSchemaAsyncOperationEventArgs(IPrintSchemaTicket printTicket, int statusHResult) + { + _statusHResult = statusHResult; + _printTicket = printTicket; + } + + private int _statusHResult; + private IPrintSchemaTicket _printTicket; + } + + /// <summary> + /// Maps to COM IPrintSchemaAsyncOperation + /// </summary> + public interface IPrintSchemaAsyncOperation + { + /// <summary> + /// Maps to COM IPrintSchemaAsyncOperationEvent::Completed + /// </summary> + event EventHandler<PrintSchemaAsyncOperationEventArgs> Completed; + + /// <summary> + /// Maps to COM IPrintSchemaAsyncOperation::Start + /// </summary> + void Start(); + + /// <summary> + /// Maps to COM IPrintSchemaAsyncOperation::Cancel + /// </summary> + void Cancel(); + } + + /// <summary> + /// Maps to COM IPrintSchemaTicket + /// </summary> + public interface IPrintSchemaTicket + { + /// <summary> + /// Maps to COM IPrintSchemaTicket::GetFeatureByKeyName + /// </summary> + IPrintSchemaFeature GetFeatureByKeyName(string featureName); + + /// <summary> + /// Maps to COM IPrintSchemaTicket::GetFeature + /// </summary> + IPrintSchemaFeature GetFeature(string featureName); + + /// <summary> + /// Maps to COM IPrintSchemaTicket::GetFeature + /// </summary> + IPrintSchemaFeature GetFeature(string featureName, string xmlNamespace); + + /// <summary> + /// Maps to COM IPrintSchemaTicket::ValidateAsync + /// </summary> + IPrintSchemaAsyncOperation ValidateAsync(); + + /// <summary> + /// Maps to COM IPrintSchemaTicket::CommitAsync + /// </summary> + IPrintSchemaAsyncOperation CommitAsync(IPrintSchemaTicket printTicketCommit); + + /// <summary> + /// Maps to COM IPrintSchemaTicket::NotifyXmlChanged + /// </summary> + void NotifyXmlChanged(); + + /// <summary> + /// Maps to COM IPrintSchemaTicket::GetCapabilities + /// </summary> + IPrintSchemaCapabilities GetCapabilities(); + + /// <summary> + /// Maps to COM IPrintSchemaTicket::JobCopiesAllDocuments + /// </summary> + uint JobCopiesAllDocuments { get; set; } + + /// <summary> + /// Replaces COM IPrintSchemaTicket::XmlNode + /// </summary> + Stream GetReadStream(); + + /// <summary> + /// Replaces COM IPrintSchemaTicket::XmlNode + /// </summary> + Stream GetWriteStream(); + +#if WINDOWS_81_APIS + /// <summary> + /// Maps to COM IPrintSchemaTicket2::GetParameterInitializer + /// </summary> + IPrintSchemaParameterInitializer GetParameterInitializer(string parameterName); + + /// <summary> + /// Maps to COM IPrintSchemaTicket2::GetParameterInitializer + /// </summary> + IPrintSchemaParameterInitializer GetParameterInitializer(string parameterName, string xmlNamespace); +#endif + } + + /// <summary> + /// Maps to COM IPrinterPropertyBag + /// </summary> + public interface IPrinterPropertyBag + { + /// <summary> + /// Maps to COM IPrinterPropertyBag::GetBool + /// </summary> + bool GetBool(string propertyName); + + /// <summary> + /// Maps to COM IPrinterPropertyBag::SetBool + /// </summary> + void SetBool(string propertyName, bool value); + + /// <summary> + /// Maps to COM IPrinterPropertyBag::GetInt32 + /// </summary> + int GetInt(string propertyName); + + /// <summary> + /// Maps to COM IPrinterPropertyBag::SetInt32 + /// </summary> + void SetInt(string propertyName, int value); + + /// <summary> + /// Maps to COM IPrinterPropertyBag::GetString + /// </summary> + string GetString(string propertyName); + + /// <summary> + /// Maps to COM IPrinterPropertyBag::SetString + /// </summary> + void SetString(string propertyName, string value); + + /// <summary> + /// Maps to COM IPrinterPropertyBag::GetBytes + /// </summary> + byte[] GetBytes(string propertyName); + + /// <summary> + /// Maps to COM IPrinterPropertyBag::SetBytes + /// </summary> + void SetBytes(string propertyName, byte[] value); + + /// <summary> + /// Maps to COM IPrinterPropertyBag::GetReadStream + /// </summary> + Stream GetReadStream(string propertyName); + + /// <summary> + /// Maps to COM IPrinterPropertyBag::GetWriteStream + /// </summary> + Stream GetWriteStream(string propertyName); + + /// <summary> + /// Indexer for the properties + /// </summary> + /// <param name="name">Property name</param> + /// <returns>An instance of 'PrinterProperty' used to get/set values</returns> + PrinterProperty this[string name] { get; } + } + + /// <summary> + /// Represents one property returned by the indexer in IPrinterPropertyBag + /// </summary> + public class PrinterProperty + { + internal PrinterProperty(IPrinterPropertyBag bag, string name) + { + _bag = bag; + _name = name; + } + + /// <summary> + /// Prevents default construction + /// </summary> + private PrinterProperty() + { + } + + /// <summary> + /// Get/Set a value of type 'bool' + /// </summary> + public bool Bool + { + get { return _bag.GetBool(_name); } + set { _bag.SetBool(_name, value); } + } + + /// <summary> + /// Get/Set a value of type 'Int32' + /// </summary> + public int Int + { + get { return _bag.GetInt(_name); } + set { _bag.SetInt(_name, value); } + } + + /// <summary> + /// Get/Set a value of type 'byte[]' + /// </summary> + public byte[] Bytes + { + get { return _bag.GetBytes(_name); } + set { _bag.SetBytes(_name, value); } + } + + /// <summary> + /// Get/Set a value of type 'string' + /// </summary> + public string String + { + get { return _bag.GetString(_name); } + set { _bag.SetString(_name, value); } + } + + /// <summary> + /// Get a read/write Stream corresponding to this property name + /// </summary> + public Stream WriteStream + { + get { return _bag.GetWriteStream(_name); } + } + + /// <summary> + /// Get a read-only Stream corresponding to this property name + /// </summary> + public Stream ReadStream + { + get { return _bag.GetReadStream(_name); } + } + + // + // Implementation details + // + private IPrinterPropertyBag _bag; + private string _name; + } + +#if WINDOWS_81_APIS + /// <summary> + /// Maps to COM IPrintJob + /// </summary> + public interface IPrintJob + { + /// <summary> + /// Maps to COM IPrintJob::Name + /// </summary> + string Name { get; } + + /// <summary> + /// Maps to COM IPrintJob::Id + /// </summary> + ulong Id { get; } + + /// <summary> + /// Maps to COM IPrintJob::PrintedPages + /// </summary> + ulong PrintedPages { get; } + + /// <summary> + /// Maps to COM IPrintJob::TotalPages + /// </summary> + ulong TotalPages { get; } + + /// <summary> + /// Maps to COM IPrintJob::Status + /// </summary> + PrintJobStatus Status { get; } + + /// <summary> + /// Maps to COM IPrintJob::SubmissionTime + /// </summary> + DateTime SubmissionTime { get; } + + /// <summary> + /// Maps to COM IPrintJob::RequestCancel + /// </summary> + void RequestCancel(); + } + + /// <summary> + /// Maps to COM IPrinterQueueViewEvent + /// </summary> + public class PrinterQueueViewEventArgs : EventArgs + { + /// <summary> + /// Maps to COM IPrinterQueueViewEvent::OnChanged, parameter 'pCollection' + /// </summary> + public IEnumerable<IPrintJob> Collection { get { return _collection; } } + + /// <summary> + /// Maps to COM IPrinterQueueViewEvent::OnChanged, parameter 'ulViewOffset' + /// </summary> + public uint ViewOffset { get { return _viewOffset; } } + + /// <summary> + /// Maps to COM IPrinterQueueViewEvent::OnChanged, parameter 'ulViewSize' + /// </summary> + public uint ViewSize { get { return _viewSize; } } + + /// <summary> + /// Maps to COM IPrinterQueueViewEvent::OnChanged, parameter 'ulCountJobsInPrintQueue' + /// </summary> + public uint CountJobsInPrintQueue { get { return _countJobsInPrintQueue; } } + + #region Implementation details + + internal PrinterQueueViewEventArgs(IEnumerable<IPrintJob> collection, uint viewOffset, uint viewSize, uint countJobsInPrintQueue) + { + _collection = collection; + _viewOffset = viewOffset; + _viewSize = viewSize; + _countJobsInPrintQueue = countJobsInPrintQueue; + } + + private IEnumerable<IPrintJob> _collection; + private uint _viewOffset; + private uint _viewSize; + private uint _countJobsInPrintQueue; + + #endregion + } + + /// <summary> + /// Maps to COM IPrinterQueueView + /// </summary> + public interface IPrinterQueueView + { + /// <summary> + /// Maps to COM IPrinterQueueView::SetViewRange + /// </summary> + void SetViewRange(uint viewOffset, uint viewSize); + + /// <summary> + /// Maps to COM IPrinterQueueViewEvent::OnChanged + /// </summary> + event EventHandler<PrinterQueueViewEventArgs> OnChanged; + } + + /// <summary> + /// Maps to COM IPrinterBidiSetRequestCallback + /// </summary> + public interface IPrinterBidiSetRequestCallback + { + /// <summary> + /// Maps to COM IPrinterBidiSetRequestCallback::Completed + /// </summary> + void Completed(string response, int statusHResult); + } +#endif + + /// <summary> + /// Maps to COM IPrinterQueueEvent + /// </summary> + public class PrinterQueueEventArgs : EventArgs + { + /// <summary> + /// Maps to COM IPrinterQueueEvent::OnBidiResponseReceived, parameter 'bstrResponse' + /// </summary> + public string Response { get { return _response; } } + + /// <summary> + /// Maps to COM IPrinterQueueEvent::OnBidiResponseReceived, parameter 'hrStatus' + /// </summary> + public int StatusHResult { get { return _statusHResult; } } + + // + // Implementation details + // + public PrinterQueueEventArgs(string response, int statusHResult) + { + _response = response; + _statusHResult = statusHResult; + } + + private int _statusHResult; + private string _response; + } + + /// <summary> + /// Maps to COM IPrinterQueue + /// </summary> + public interface IPrinterQueue + { + /// <summary> + /// Maps to COM IPrinterQueue::Handle + /// </summary> + IntPtr Handle { get; } + + /// <summary> + /// Maps to COM IPrinterQueue::Name + /// </summary> + string Name { get; } + + /// <summary> + /// Maps to COM IPrinterQueue::SendBidiQuery + /// </summary> + void SendBidiQuery(string bidiQuery); + + /// <summary> + /// Maps to COM IPrinterQueue::GetProperties + /// </summary> + IPrinterPropertyBag GetProperties(); + +#if WINDOWS_81_APIS + /// <summary> + /// Maps to COM IPrinterQueue2::SendBidiSetRequestAsync + /// </summary> + /// <param name="callback">Maps to COM callback type IPrinterBidiSetRequestCallback</param> + /// <returns>IPrinterExtensionAsyncOperation - async operation context</returns> + IPrinterExtensionAsyncOperation SendBidiSetRequestAsync(string bidiRequest, IPrinterBidiSetRequestCallback callback); + + /// <summary> + /// Maps to COM IPrinterQueue2::GetPrinterQueueView + /// </summary> + IPrinterQueueView GetPrinterQueueView(uint viewOffset, uint viewSize); +#endif + + /// <summary> + /// Maps to COM IPrinterQueueEvent::OnBidiResponseReceived + /// </summary> + event EventHandler<PrinterQueueEventArgs> OnBidiResponseReceived; + } + + /// <summary> + /// Maps to COM IPrinterExtensionRequest + /// </summary> + public interface IPrinterExtensionRequest + { + /// <summary> + /// Maps to COM IPrinterExtensionRequest::Complete + /// </summary> + void Complete(); + + /// <summary> + /// Maps to COM IPrinterExtensionRequest::Cancel + /// </summary> + void Cancel(int statusHResult, string logMessage); + } +} + diff --git a/print/v4PrintDriverSamples/PrinterExtensionSample/PrinterExtensionLibrary/Properties/AssemblyInfo.cs b/print/v4PrintDriverSamples/PrinterExtensionSample/PrinterExtensionLibrary/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..8b42d1af --- /dev/null +++ b/print/v4PrintDriverSamples/PrinterExtensionSample/PrinterExtensionLibrary/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Microsoft.Samples.Printing.PrinterExtensionLibrary")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Microsoft Corporation")] +[assembly: AssemblyProduct("Microsoft.Samples.Printing.PrinterExtensionLibrary")] +[assembly: AssemblyCopyright("Copyright (c) 2011 Microsoft Corporation. All rights reserved.")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/print/v4PrintDriverSamples/PrinterExtensionSample/PrinterExtensionSample.sln b/print/v4PrintDriverSamples/PrinterExtensionSample/PrinterExtensionSample.sln new file mode 100644 index 00000000..5573b670 --- /dev/null +++ b/print/v4PrintDriverSamples/PrinterExtensionSample/PrinterExtensionSample.sln @@ -0,0 +1,86 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0 +MinimumVisualStudioVersion = 12.0 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ExtensionSample", "ExtensionSample", "{EAF81F7A-957C-4C1F-A2ED-5A9FE3DAEA77}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "PrinterExtensionLibrary", "PrinterExtensionLibrary", "{D86B51AE-7E8E-4A5B-947B-02BD9CA9A176}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PrinterExtensionSample", "ExtensionSample\PrinterExtensionSample.csproj", "{CF554A99-6889-4B86-934F-B6AADBFEFC01}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PrinterExtensionLibrary", "PrinterExtensionLibrary\PrinterExtensionLibrary.csproj", "{D8DA0C4D-F972-4546-9068-8EB256F222F7}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Win8 Debug|x86 = Win8 Debug|x86 + Win8 Debug|x64 = Win8 Debug|x64 + Win8 Release|x86 = Win8 Release|x86 + Win8 Release|x64 = Win8 Release|x64 + Win8.1 Debug|x86 = Win8.1 Debug|x86 + Win8.1 Debug|x64 = Win8.1 Debug|x64 + Win8.1 Release|x86 = Win8.1 Release|x86 + Win8.1 Release|x64 = Win8.1 Release|x64 + Win8 Debug|Any CPU = Win8 Debug|Any CPU + Win8 Release|Any CPU = Win8 Release|Any CPU + Win8.1 Debug|Any CPU = Win8.1 Debug|Any CPU + Win8.1 Release|Any CPU = Win8.1 Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CF554A99-6889-4B86-934F-B6AADBFEFC01}.Win8 Debug|x86.ActiveCfg = Win8 Debug|x86 + {CF554A99-6889-4B86-934F-B6AADBFEFC01}.Win8 Debug|x86.Build.0 = Win8 Debug|x86 + {CF554A99-6889-4B86-934F-B6AADBFEFC01}.Win8 Debug|x64.ActiveCfg = Win8 Debug|x64 + {CF554A99-6889-4B86-934F-B6AADBFEFC01}.Win8 Debug|x64.Build.0 = Win8 Debug|x64 + {CF554A99-6889-4B86-934F-B6AADBFEFC01}.Win8 Release|x86.ActiveCfg = Win8 Release|x86 + {CF554A99-6889-4B86-934F-B6AADBFEFC01}.Win8 Release|x86.Build.0 = Win8 Release|x86 + {CF554A99-6889-4B86-934F-B6AADBFEFC01}.Win8 Release|x64.ActiveCfg = Win8 Release|x64 + {CF554A99-6889-4B86-934F-B6AADBFEFC01}.Win8 Release|x64.Build.0 = Win8 Release|x64 + {CF554A99-6889-4B86-934F-B6AADBFEFC01}.Win8.1 Debug|x86.ActiveCfg = Win8.1 Debug|x86 + {CF554A99-6889-4B86-934F-B6AADBFEFC01}.Win8.1 Debug|x86.Build.0 = Win8.1 Debug|x86 + {CF554A99-6889-4B86-934F-B6AADBFEFC01}.Win8.1 Debug|x64.ActiveCfg = Win8.1 Debug|x64 + {CF554A99-6889-4B86-934F-B6AADBFEFC01}.Win8.1 Debug|x64.Build.0 = Win8.1 Debug|x64 + {CF554A99-6889-4B86-934F-B6AADBFEFC01}.Win8.1 Release|x86.ActiveCfg = Win8.1 Release|x86 + {CF554A99-6889-4B86-934F-B6AADBFEFC01}.Win8.1 Release|x86.Build.0 = Win8.1 Release|x86 + {CF554A99-6889-4B86-934F-B6AADBFEFC01}.Win8.1 Release|x64.ActiveCfg = Win8.1 Release|x64 + {CF554A99-6889-4B86-934F-B6AADBFEFC01}.Win8.1 Release|x64.Build.0 = Win8.1 Release|x64 + {CF554A99-6889-4B86-934F-B6AADBFEFC01}.Win8 Debug|Any CPU.ActiveCfg = Win8 Debug|x86 + {CF554A99-6889-4B86-934F-B6AADBFEFC01}.Win8 Debug|Any CPU.Build.0 = Win8 Debug|x86 + {CF554A99-6889-4B86-934F-B6AADBFEFC01}.Win8 Release|Any CPU.ActiveCfg = Win8 Release|x86 + {CF554A99-6889-4B86-934F-B6AADBFEFC01}.Win8 Release|Any CPU.Build.0 = Win8 Release|x86 + {CF554A99-6889-4B86-934F-B6AADBFEFC01}.Win8.1 Debug|Any CPU.ActiveCfg = Win8.1 Debug|x86 + {CF554A99-6889-4B86-934F-B6AADBFEFC01}.Win8.1 Debug|Any CPU.Build.0 = Win8.1 Debug|x86 + {CF554A99-6889-4B86-934F-B6AADBFEFC01}.Win8.1 Release|Any CPU.ActiveCfg = Win8.1 Release|x86 + {CF554A99-6889-4B86-934F-B6AADBFEFC01}.Win8.1 Release|Any CPU.Build.0 = Win8.1 Release|x86 + {D8DA0C4D-F972-4546-9068-8EB256F222F7}.Win8 Debug|x86.ActiveCfg = Win8 Debug|Any CPU + {D8DA0C4D-F972-4546-9068-8EB256F222F7}.Win8 Debug|x86.Build.0 = Win8 Debug|Any CPU + {D8DA0C4D-F972-4546-9068-8EB256F222F7}.Win8 Debug|x64.ActiveCfg = Win8 Debug|Any CPU + {D8DA0C4D-F972-4546-9068-8EB256F222F7}.Win8 Debug|x64.Build.0 = Win8 Debug|Any CPU + {D8DA0C4D-F972-4546-9068-8EB256F222F7}.Win8 Release|x86.ActiveCfg = Win8 Release|Any CPU + {D8DA0C4D-F972-4546-9068-8EB256F222F7}.Win8 Release|x86.Build.0 = Win8 Release|Any CPU + {D8DA0C4D-F972-4546-9068-8EB256F222F7}.Win8 Release|x64.ActiveCfg = Win8 Release|Any CPU + {D8DA0C4D-F972-4546-9068-8EB256F222F7}.Win8 Release|x64.Build.0 = Win8 Release|Any CPU + {D8DA0C4D-F972-4546-9068-8EB256F222F7}.Win8.1 Debug|x86.ActiveCfg = Win8.1 Debug|Any CPU + {D8DA0C4D-F972-4546-9068-8EB256F222F7}.Win8.1 Debug|x86.Build.0 = Win8.1 Debug|Any CPU + {D8DA0C4D-F972-4546-9068-8EB256F222F7}.Win8.1 Debug|x64.ActiveCfg = Win8.1 Debug|Any CPU + {D8DA0C4D-F972-4546-9068-8EB256F222F7}.Win8.1 Debug|x64.Build.0 = Win8.1 Debug|Any CPU + {D8DA0C4D-F972-4546-9068-8EB256F222F7}.Win8.1 Release|x86.ActiveCfg = Win8.1 Release|Any CPU + {D8DA0C4D-F972-4546-9068-8EB256F222F7}.Win8.1 Release|x86.Build.0 = Win8.1 Release|Any CPU + {D8DA0C4D-F972-4546-9068-8EB256F222F7}.Win8.1 Release|x64.ActiveCfg = Win8.1 Release|Any CPU + {D8DA0C4D-F972-4546-9068-8EB256F222F7}.Win8.1 Release|x64.Build.0 = Win8.1 Release|Any CPU + {D8DA0C4D-F972-4546-9068-8EB256F222F7}.Win8 Debug|Any CPU.ActiveCfg = Win8 Debug|Any CPU + {D8DA0C4D-F972-4546-9068-8EB256F222F7}.Win8 Debug|Any CPU.Build.0 = Win8 Debug|Any CPU + {D8DA0C4D-F972-4546-9068-8EB256F222F7}.Win8 Release|Any CPU.ActiveCfg = Win8 Release|Any CPU + {D8DA0C4D-F972-4546-9068-8EB256F222F7}.Win8 Release|Any CPU.Build.0 = Win8 Release|Any CPU + {D8DA0C4D-F972-4546-9068-8EB256F222F7}.Win8.1 Debug|Any CPU.ActiveCfg = Win8.1 Debug|Any CPU + {D8DA0C4D-F972-4546-9068-8EB256F222F7}.Win8.1 Debug|Any CPU.Build.0 = Win8.1 Debug|Any CPU + {D8DA0C4D-F972-4546-9068-8EB256F222F7}.Win8.1 Release|Any CPU.ActiveCfg = Win8.1 Release|Any CPU + {D8DA0C4D-F972-4546-9068-8EB256F222F7}.Win8.1 Release|Any CPU.Build.0 = Win8.1 Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {CF554A99-6889-4B86-934F-B6AADBFEFC01} = {EAF81F7A-957C-4C1F-A2ED-5A9FE3DAEA77} + {D8DA0C4D-F972-4546-9068-8EB256F222F7} = {D86B51AE-7E8E-4A5B-947B-02BD9CA9A176} + EndGlobalSection +EndGlobal diff --git a/print/v4PrintDriverSamples/PrinterExtensionSample/ReadMe.md b/print/v4PrintDriverSamples/PrinterExtensionSample/ReadMe.md new file mode 100644 index 00000000..e7ab1d25 --- /dev/null +++ b/print/v4PrintDriverSamples/PrinterExtensionSample/ReadMe.md @@ -0,0 +1,14 @@ +Printer Extension Sample +======================== + +This sample demonstrates how to use .NET to build a customized, desktop UI for a v4 print driver. This .NET app uses PrintTicket, PrintCapabilities and Bidi in order to communicate with the print system and is suitable for inclusion in a v4 print driver. + +**Note** This sample is for the v4 print driver model. + +Related topics +-------------- + +[Building a Driver](http://msdn.microsoft.com/en-us/library/windows/hardware/ff554644) + +[v4 Print Driver Interfaces and Enumerations](http://msdn.microsoft.com/en-us/library/hh464103(v=vs.85).aspx) + |
