Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / TrustUi / MS / Internal / documents / DocumentApplicationDocumentViewer.cs / 1 / DocumentApplicationDocumentViewer.cs
//---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // Description: The main DocumentViewer subclass that drives the MongooseUI // // History: // 06/10/2005 - [....] reworked DocumentApplicationUI.cs // //--------------------------------------------------------------------------- // Used to support the warnings disabled below #pragma warning disable 1634, 1691 using MS.Internal.Documents.Application; using MS.Internal.IO.Packaging; // For PreloadedPackages using MS.Internal.PresentationUI; using System; using System.Collections.Generic; using System.ComponentModel; // For IValueConverter using System.Globalization; // For localization of string conversion using System.IO; using System.IO.Packaging; // For Packages using System.Printing; // For PrintQueue using System.Security; using System.Security.Permissions; // For Friend Access using System.Windows; using System.Windows.Controls; // For Page Ranges using System.Windows.Controls.Primitives; // For ToggleButton using System.Windows.Data; // For data binding using System.Windows.Documents; // For PresentationUIStyleResources using System.Windows.Documents.Serialization; // For WritingCompletedEventArgs using System.Windows.Input; // For focus / input based events using System.Windows.Interop; // For WindowInteropHelper using System.Windows.Navigation; // For NavigationWindow using System.Windows.Markup; // For MarkupExtension using System.Windows.Threading; // For DispatcherPriority using System.Windows.TrustUI; // For string resources using System.Windows.Xps; // XpsDocumentWriter using System.Windows.Media; // Visual Stuff namespace MS.Internal.Documents { [FriendAccessAllowed] internal sealed class DocumentApplicationDocumentViewer : DocumentViewer { //----------------------------------------------------- // // Constructors // //----------------------------------------------------- #region Constructors ////// Static constructor used to ensure commands are setup. /// static DocumentApplicationDocumentViewer() { CreateCommandBindings(); } ////// Constructor for DocumentApplicationDocumentViewer /// public DocumentApplicationDocumentViewer() : base() { System.Diagnostics.Debug.Assert( _singletonInstance == null, "DocumentApplicationDocumentViewer constructor called twice."); if (_singletonInstance == null) { _singletonInstance = this; // Setup the CommandEnforcer before any of the UI is prepared. CreateEnforcer(); } } #endregion Constructors //------------------------------------------------------ // // Public Properties // //----------------------------------------------------- #region Public Properties ////// This command will give focus to the first control in our main toolbar. /// public static RoutedUICommand FocusToolBar { get { return _focusToolBarCommand; } } ////// This command will issue the Sign Command to the DocumentSignatureManager /// public static RoutedUICommand Sign { get { return _signCommand; } } ////// This command will issue the RequestSigners Command to the DocumentSignatureManager /// public static RoutedUICommand RequestSigners { get { return _requestSignersCommand; } } ////// This command will issue the ShowSignatureSummary Command to the DocumentSignatureManager /// public static RoutedUICommand ShowSignatureSummary { get { return _showSignatureSummaryCommand; } } ////// This command will invoke the RM Permissions dialog. /// public static RoutedUICommand ShowRMPermissions { get { return _showRMPermissionsCommand; } } ////// This command will invoke the RM Credentials manager. /// public static RoutedUICommand ShowRMCredentialManager { get { return _showRMCredentialManagerCommand; } } ////// This command will invoke the RM publishing ui. /// public static RoutedUICommand ShowRMPublishingUI { get { return _showRMPublishingUICommand; } } ////// The current DocumentApplicationState stored on the DocumentViewer. Does not necessarily /// mean the currently visible state. /// public DocumentApplicationState StoredDocumentApplicationState { get { return _state; } set { _state = value; } } ////// The current RightManagementPolicy that is being enforced on the UI. /// Used to safely deliver the RightsManagementPolicy to the CommandEnforcer. /// public RightsManagementPolicy RightsManagementPolicy { get { return _rightsManagementPolicy.Value; } } ////// Exposes XPSViewer's RootBrowserWindow as an IWin32Window for use in parenting Winforms /// dialogs. /// public System.Windows.Forms.IWin32Window RootBrowserWindow { [SecurityCritical] get { if (_rootBrowserWindow == null) { IntPtr handle = IntPtr.Zero; WindowInteropHelper helper = new WindowInteropHelper( System.Windows.Application.Current.MainWindow); (new UIPermission(UIPermissionWindow.AllWindows)).Assert(); //Blessed try { handle = helper.Handle; } finally { UIPermission.RevertAssert(); } _rootBrowserWindow = new WrapperIWin32Window(handle); } return _rootBrowserWindow; } } ////// Critical /// 1) IWin32Window exposes an IntPtr handle to the window, which could be used /// for malicious purposes. /// ////// Exposes the singleton instance of DocumentApplicationDocumentViewer. /// public static DocumentApplicationDocumentViewer Instance { get { return _singletonInstance; } } #endregion Public Properties //------------------------------------------------------ // // Public Methods // //------------------------------------------------------ #region Public Methods ////// Used to initialize the UI controls. /// If multiple initializations are needed during navigation, etc, this method should be used. /// /// A reference to the DocumentSignatureManager ////// Critical - Accepts a DocumentRightsManagementManager as a parameter, which is used /// to control access to commands through the CommandEnforcer. Additionally, /// The RMPolicyChange event, which updates the permissions on the enforcer, /// is hooked up in this method. /// [SecurityCritical] public void InitializeUI(DocumentSignatureManager docSigManager, DocumentRightsManagementManager rmManager) { if (docSigManager == null) { throw new ArgumentNullException("docSigManager"); } if (rmManager == null) { throw new ArgumentNullException("rmManager"); } // Set DocumentSignatureManager reference. _docSigManager = docSigManager; // Setup DigSigInfoBar event handler _docSigManager.SignatureStatusChange += new DocumentSignatureManager.SignatureStatusChangeHandler(_digSigInfoBar.OnStatusChange); //We disallow all RM-protected actions until the RM Manager tells us otherwise. _rightsManagementPolicy.Value = RightsManagementPolicy.AllowNothing; CommandEnforcer.Enforce(); _rmManager = rmManager; _rmManager.RMStatusChange += new DocumentRightsManagementManager.RMStatusChangeHandler(_rmInfoBar.OnStatusChange); _rmManager.RMStatusChange += new DocumentRightsManagementManager.RMStatusChangeHandler(OnRMStatusChanged); _rmManager.RMPolicyChange += new DocumentRightsManagementManager.RMPolicyChangeHandler(OnRMPolicyChanged); Invariant.Assert( RequiredControlsExist(), "DocumentApplicationDocumentViewer must have a valid style."); // Set default focus on DocumentViewer Focus(); } ////// Called when the Template's tree has been generated. /// ////// This method is commonly used to check the status of the visual /// tree prior to rendering, so that elements of the tree can be /// customized before they are shown. /// If a style is changed that affects the visual tree, the /// ApplyTemplate method will expand the new visual tree and return /// true. Otherwise, it will return false. /// When overriding this method, be sure to call the ApplyTemplate /// method of the base class. /// ////// True if the Visual Tree has been created /// public override void OnApplyTemplate() { base.OnApplyTemplate(); // Setup the UI controls event handlers, if needed if (RequiredControlsExist() && (!_isUISetup)) { SetupUIControls(); SetupUITabIndices(); _isUISetup = true; } } ////// Handler for the Print command. /// ////// Critical /// 1) Makes a security decision to determine whether or not the user /// is allowed to perform the print operation /// 2) Satisfies a link-demand for SafePrinting permissions /// TreatAsSafe /// 1) The decision is based on the RM policy, which is critical for /// set. /// 2) SafePrinting is in the Internet Zone by default -- we've /// restricted our permissions even further in order to delay /// loading of System.Windows.Drawing.dll until printing is invoked. /// [SecurityCritical, SecurityTreatAsSafe] protected override void OnPrintCommand() { if ((RightsManagementPolicy & RightsManagementPolicy.AllowPrint) == RightsManagementPolicy.AllowPrint) { OnPrintCommandPageRangeOverride(); } else { throw new InvalidOperationException( SR.Get(SRID.RightsManagementExceptionNoRightsForOperation)); } } ////// Handler for the CancelPrint command. /// protected override void OnCancelPrintCommand() { #if !DONOTREFPRINTINGASMMETA if (_documentWriter != null) { _documentWriter.CancelAsync(); } #endif // DONOTREFPRINTINGASMMETA } ////// Called when WritingCompleted event raised by a DocumentWriter (during printing). /// /// Sender of the event. /// Event arguments. private void HandlePrintCompleted(object sender, WritingCompletedEventArgs e) { #if !DONOTREFPRINTINGASMMETA if (_documentWriter != null) { _documentWriter.WritingCompleted -= new WritingCompletedEventHandler(HandlePrintCompleted); _documentWriter = null; // Since _documentWriter value is used to determine CanExecute state, we must invalidate that state. CommandManager.InvalidateRequerySuggested(); } #endif // DONOTREFPRINTINGASMMETA } ////// Called when WritingCancelled event raised by a DocumentWriter (during printing). /// /// Sender of the event. /// Event arguments. private void HandlePrintCancelled(object sender, WritingCancelledEventArgs e) { #if !DONOTREFPRINTINGASMMETA if (_documentWriter != null) { _documentWriter.WritingCancelled -= new WritingCancelledEventHandler(HandlePrintCancelled); _documentWriter = null; // Since _documentWriter value is used to determine CanExecute state, we must invalidate that state. CommandManager.InvalidateRequerySuggested(); } #endif // DONOTREFPRINTINGASMMETA } ////// This is a copy of DocumentViewerBase OnPrintCommand modified to /// handle page ranges /// ////// Critical /// 1) Calls PrintQueue.CreateXpsDocumentWriter which is security critical /// 2) Accesses DocumentProperties.Filename which is security critical /// [SecurityCritical] private void OnPrintCommandPageRangeOverride() { #if !DONOTREFPRINTINGASMMETA XpsDocumentWriter docWriter; PrintDocumentImageableArea ia = null; PageRangeSelection pageRangeSelection = PageRangeSelection.AllPages; PageRange pageRange = new PageRange(0); // Only one printing job is allowed. if (_documentWriter != null) { return; } if (Document != null) { // Show print dialog. docWriter = PrintQueue.CreateXpsDocumentWriter( Path.GetFileNameWithoutExtension(DocumentProperties.Current.Filename), ref ia, ref pageRangeSelection, ref pageRange); if (docWriter != null && ia != null) { // Register for WritingCompleted event. _documentWriter = docWriter; _documentWriter.WritingCompleted += new WritingCompletedEventHandler(HandlePrintCompleted); _documentWriter.WritingCancelled += new WritingCancelledEventHandler(HandlePrintCancelled); // Since _documentWriter value is used to determine CanExecute state, we must invalidate that state. CommandManager.InvalidateRequerySuggested(); DocumentPaginator paginator = Document.DocumentPaginator; int pageCount = paginator.PageCount; // Write to the PrintQueue if (pageRangeSelection == PageRangeSelection.UserPages) { if (pageRange.PageFrom < 1) { pageRange.PageFrom = 1; } else if (pageRange.PageFrom > pageCount) { pageRange.PageFrom = 1; pageRange.PageTo = pageCount; } if (pageRange.PageTo < pageRange.PageFrom) { pageRange.PageTo = pageRange.PageFrom; } else if (pageRange.PageTo > pageCount) { pageRange.PageTo = pageCount; } } else { pageRange.PageFrom = 1; pageRange.PageTo = pageCount; } WritePageSelection(docWriter, paginator, pageRange, ia); } } #endif // DONOTREFPRINTINGASMMETA } ////// This method finds the URI to pages from the document /// specified in the page range. Deserializes a copy of the pages from /// a package stored in the PreloadedPackages and generates a new /// doucment with these pages. This is serialized to the provided /// document writer. /// ////// Critical /// 1) Accesses the critical class PreloadedPackages /// TreatAsSafe /// 1) The returned package is used internal to the method /// to deserialize a copy of the pages. /// [SecurityCritical, SecurityTreatAsSafe] private void WritePageSelection( XpsDocumentWriter docWriter, DocumentPaginator docPaginator, System.Windows.Controls.PageRange pageRange, PrintDocumentImageableArea ia ) { // // Create a destination FixedDocument // FixedDocument dstDoc = new FixedDocument(); FixedDocumentSequence fds = docPaginator.Source as FixedDocumentSequence; if (fds != null) { // // If the source is a FixedDocumentSequence (Should be in Mongoose!), do not use a DocumentPaginator // because that unnecessarily loads pages. Instead, enumerate through the references only // FixedDocument fd = null; int skip = pageRange.PageFrom - 1; int pageInDoc = 0; int docIndex = 0; while (skip> 0) { if (fd == null) { fd = fds.References[docIndex++].GetDocument(false); pageInDoc = 0; if (fd == null) { break; } } int k = skip; if (k >= fd.Pages.Count) { k = fd.Pages.Count; fd = null; } skip -= k; pageInDoc += k; } int pages = pageRange.PageTo - pageRange.PageFrom + 1; while ( pages > 0 ) { if (fd == null) { fd = fds.References[docIndex++].GetDocument(false); pageInDoc = 0; if (fd == null) { break; } } if (pageInDoc >= fd.Pages.Count) { fd = null; } else { PageContent pageContent = new PageContent(); pageContent.BeginInit(); ((IUriContext)pageContent).BaseUri = ((IUriContext)fd.Pages[pageInDoc]).BaseUri; pageContent.Source = fd.Pages[pageInDoc++].Source; pageContent.EndInit(); (dstDoc as IAddChild).AddChild(pageContent); pages--; } } } else { for (int i = pageRange.PageFrom; i <= pageRange.PageTo; i++) { DocumentPage page = docPaginator.GetPage(i - 1); IUriContext fixedPage = page.Visual as IUriContext; PageContent pageContent = new PageContent(); pageContent.BeginInit(); pageContent.Source = fixedPage.BaseUri; pageContent.EndInit(); (dstDoc as IAddChild).AddChild(pageContent); } } DocumentPaginator scalingDocument = new ScalingDocument(dstDoc, ia); docWriter.WriteAsync(scalingDocument); } ////// Called whenever a new document is assigned. /// protected override void OnDocumentChanged() { base.OnDocumentChanged(); // Whenever the document changes (possibly from navigation) hook up a handler // to reset the DocumentViewer to the stored state (usually this will mean the // default state) DynamicDocumentPaginator paginator = Document.DocumentPaginator as DynamicDocumentPaginator; if (paginator != null) { paginator.PaginationCompleted += new EventHandler(OnPaginationCompleted); //If the doc is already paginated, update now. if (paginator.IsPageCountValid) { OnPaginationCompleted(Document, EventArgs.Empty); } } } ////// Called when ContextMenuOpening is raised on this element. /// We use this opportunity to make sure the ScrollViewer's ContextMenu is invoked. /// /// Event arguments protected override void OnContextMenuOpening(ContextMenuEventArgs e) { // Raise the ContextMenu command on the ScrollViewer if the ContextMenu // was invoked via the Menu key. // A negative offset for e.CursorLeft means the user invoked // the menu with a hotkey (shift-F10). if (_scrollViewer != null && DoubleUtil.LessThan(e.CursorLeft, 0)) { this.ContextMenu = ScrollViewer.ContextMenu; } base.OnContextMenuOpening(e); } ////// Called when ContextMenuClosing is raised on this element. /// /// Event arguments protected override void OnContextMenuClosing(ContextMenuEventArgs e) { //Reset our ContextMenu back to null. this.ContextMenu = null; base.OnContextMenuOpening(e); } ////// This is the method that responds to the KeyDown event. It will reclaim the /// focus when the user presses escape if one of our buttons is focused. /// /// protected override void OnKeyDown(KeyEventArgs e) { if (e.Key == Key.Escape) { Focus(); } base.OnKeyDown(e); } ////// Returns the current UI state /// ///The current UI state public DocumentApplicationState GetCurrentState() { // Store the current state, so that on refresh the data is still available. _state = new DocumentApplicationState(Zoom, HorizontalOffset, VerticalOffset, MaxPagesAcross); return _state; } ////// This will reset the current UI to match that of the StoredDocumentApplicationState /// public void SetUIToStoredState() { // Must be positive if (_state.MaxPagesAcross > 0) { MaxPagesAcross = _state.MaxPagesAcross; } // Must be positive if (_state.Zoom > 0) { Zoom = _state.Zoom; } // Invoke a delegate at Background priority so that // the Vertical and Horizontal offsets are restored // after DocumentViewer has finished laying out the document. // (This is not necessary for MaxPagesAcross and Zoom since // DocumentViewer will not reset those during layout.) Dispatcher.BeginInvoke(DispatcherPriority.Background, (DispatcherOperationCallback)delegate(object arg) { // Must be non-negative if (_state.VerticalOffset >= 0) { VerticalOffset = _state.VerticalOffset; } // Must be non-negative if (_state.HorizontalOffset >= 0) { HorizontalOffset = _state.HorizontalOffset; } return null; }, null); } #endregion Public Methods //----------------------------------------------------- // // Private Events // //------------------------------------------------------ ////// Called when a new custom JournalEntry should be made /// /// /// public delegate void JournalEntryHandler(object sender, DocumentApplicationJournalEntryEventArgs args); ////// Fired whenever the current UI should have a custom journal entry added to the /// NavWindow's back stack /// public event JournalEntryHandler AddJournalEntry; //----------------------------------------------------- // // Private Properties // // All of these CLR properties (UI-controls) are guaranteed to exist (non-null) otherwise // the UI will throw upon startup // //----------------------------------------------------- #region Private Properties ////// The ToolBar that contains all of the main controls. /// private Grid ToolBar { get { // find control if the reference is not set. if (_toolBar == null) { _toolBar = GetTemplateChild(_toolBarName) as Grid; } return _toolBar; } } ////// ZoomComboBox used for zoom value selection, and text zoom input /// private ZoomComboBox ZoomComboBox { get { // find control if the reference is not set. if (_zoomComboBox == null) { // Find ContentControl to host the ZoomComboBox. ContentControl host = GetTemplateChild("ZoomComboBoxHost") as ContentControl; if (host != null) { // Construct a new ZoomComboBox, and insert it into the host. _zoomComboBox = new ZoomComboBox(); // Setup two binds on the Width and Height to ensure these are controlled // by the ContentControl parent. Binding bind = new Binding("Width"); bind.Mode = BindingMode.OneWay; bind.Source = host; _zoomComboBox.SetBinding(ContentControl.WidthProperty, bind); bind = new Binding("Height"); bind.Mode = BindingMode.OneWay; bind.Source = host; _zoomComboBox.SetBinding(ContentControl.HeightProperty, bind); // Insert the ZoomComboBox into it's host (and thus the ToolBar). host.Content = _zoomComboBox; } } return _zoomComboBox; } } ////// Used to move up a page /// private Button PageUpButton { get { // find control if the reference is not set. if (_pageUpButton == null) { _pageUpButton = GetTemplateChild(_pageUpButtonName) as Button; } return _pageUpButton; } } ////// Used to display, and input page selection /// private PageTextBox PageTextBox { get { // find control if the reference is not set. if (_pageTextBox == null) { // Find ContentControl to host the PageTextBox. ContentControl host = GetTemplateChild("PageTextBoxHost") as ContentControl; if (host != null) { // Construct a new PageTextBox, and insert it into the host. _pageTextBox = new PageTextBox(); // Setup two binds on the Width and Height to ensure these are controlled // by the ContentControl parent. Binding bind = new Binding("Width"); bind.Mode = BindingMode.OneWay; bind.Source = host; _pageTextBox.SetBinding(ContentControl.WidthProperty, bind); bind = new Binding("Height"); bind.Mode = BindingMode.OneWay; bind.Source = host; _pageTextBox.SetBinding(ContentControl.HeightProperty, bind); // Insert the PageTextBox into it's host (and thus the ToolBar). host.Content = _pageTextBox; } } return _pageTextBox; } } ////// Used to move down a page /// private Button PageDownButton { get { // find control if the reference is not set. if (_pageDownButton == null) { _pageDownButton = GetTemplateChild(_pageDownButtonName) as Button; } return _pageDownButton; } } ////// Used to view document at 100% /// private Button ActualSizeButton { get { // find control if the reference is not set. if (_actualSizeButton == null) { _actualSizeButton = GetTemplateChild(_actualSizeButtonName) as Button; } return _actualSizeButton; } } ////// Used to view document at page width /// private Button PageWidthButton { get { // find control if the reference is not set. if (_pageWidthButton == null) { _pageWidthButton = GetTemplateChild(_pageWidthButtonName) as Button; } return _pageWidthButton; } } ////// Used to view document at 1 whole page at a time /// private Button WholePageButton { get { // find control if the reference is not set. if (_wholePageButton == null) { _wholePageButton = GetTemplateChild(_wholePageButtonName) as Button; } return _wholePageButton; } } ////// Used to view document at 2 pages at a time /// private Button TwoPageButton { get { // find control if the reference is not set. if (_twoPageButton == null) { _twoPageButton = GetTemplateChild(_twoPageButtonName) as Button; } return _twoPageButton; } } ////// Used to view document in a 'tiled' or 'thumbnail' view /// private Button ThumbnailButton { get { // find control if the reference is not set. if (_thumbnailButton == null) { _thumbnailButton = GetTemplateChild(_thumbnailButtonName) as Button; } return _thumbnailButton; } } ////// Used to spawn RightsManagement dialogs /// private Button RMButton { get { // find control if the reference is not set. if (_rmButton == null) { _rmButton = GetTemplateChild(_rmButtonName) as Button; } return _rmButton; } } ////// Used to spawn the Save As dialog /// private Button SaveAsButton { get { // find control if the reference is not set. if (_saveAsButton == null) { _saveAsButton = GetTemplateChild(_saveAsButtonName) as Button; } return _saveAsButton; } } ////// Menu to hold the DigSig options /// private MenuItem DigitalSignaturesMenuItem { get { // find control if the reference is not set. if (_digitalSignaturesMenuItem == null) { _digitalSignaturesMenuItem = GetTemplateChild(_digitalSignaturesMenuItemName) as MenuItem; } return _digitalSignaturesMenuItem; } } ////// Used to display DigSig and Permission information /// private FrameworkElement InfoBar { get { // find control if the reference is not set. if (_infoBar == null) { _infoBar = GetTemplateChild(_infoBarName) as FrameworkElement; } return _infoBar; } } ////// Used to close the InfoBar /// private Button InfoBarCloseButton { get { // find control if the reference is not set. if (_infoBarCloseButton == null) { // Setup InfoBar Close Button _infoBarCloseButton = GetTemplateChild(_infoBarCloseButtonName) as Button; if (_infoBarCloseButton != null) { _infoBarCloseButton.Click += OnInfoBarCloseClicked; } } return _infoBarCloseButton; } } ////// Used to display DigSig information and to launch the /// summary dialog /// private Button InfoBarDigSigButton { get { // find control if the reference is not set. if (_infoBarDigSigButton == null) { // Setup Digital Signature Status Changes _infoBarDigSigButton = GetTemplateChild(_infoBarSignaturesButtonName) as Button; if (_infoBarDigSigButton != null) { _infoBarDigSigButton.Command = DocumentApplicationDocumentViewer.ShowSignatureSummary; _infoBarDigSigButton.ApplyTemplate(); _digSigInfoBar = new StatusInfoItem(StatusInfoItemType.DigSig, _infoBarDigSigButton, DigitalSignaturesMenuItem); _digSigInfoBar.InfoBarVisibilityChanged += new EventHandler(OnInfoBarVisibilityChanged); } } return _infoBarDigSigButton; } } ////// Used to display RM information and to launch the /// a dialog with more information /// private Button InfoBarRMButton { get { // find control if the reference is not set. if (_infoBarRMButton == null) { // Setup Rights Management Status Changes _infoBarRMButton = GetTemplateChild(_infoBarRMButtonName) as Button; if (_infoBarRMButton != null) { _infoBarRMButton.Command = DocumentApplicationDocumentViewer.ShowRMPermissions; _infoBarRMButton.ApplyTemplate(); _rmInfoBar = new StatusInfoItem(StatusInfoItemType.RM, _infoBarRMButton, RMButton); _rmInfoBar.InfoBarVisibilityChanged += new EventHandler(OnInfoBarVisibilityChanged); } } return _infoBarRMButton; } } ////// Gets a reference to the FindToolBar and sets up default properties. /// private FindToolBar FindToolBar { get { // Locate the FindToolBar to set styling properties (to match main ToolBar). if (_findToolBar == null) { // Find ContentControl to host the FindToolBar. ContentControl host = GetTemplateChild("PART_FindToolBarHost") as ContentControl; if ((host != null) && ((_findToolBar = host.Content as FindToolBar) != null)) { ResourceKey toolBarStyleKey = new ComponentResourceKey( typeof(PresentationUIStyleResources), _toolBarStyleKeyName); _findToolBar.Style = _findToolBar.FindResource(toolBarStyleKey) as Style; _findToolBar.Background = ToolBar.Background; } } return _findToolBar; } } ////// Gets a reference to the ScrollViewer used to scroll the document content. /// private ScrollViewer ScrollViewer { get { if (_scrollViewer == null) { _scrollViewer = GetTemplateChild(_contentHostName) as ScrollViewer; } return _scrollViewer; } } ////// The current command enforcer. /// private CommandEnforcer CommandEnforcer { get { return _commandEnforcer.Value; } } #endregion Private Properties //----------------------------------------------------- // // Private Methods // //------------------------------------------------------ #region Private Methods ////// Used to setup the properties and behaviors of controls /// private void SetupUIControls() { // Attach handler to RMButton RMButton.Command = DocumentApplicationDocumentViewer.ShowRMPermissions; // Setup the DigitalSignaturesMenu // Add the Sign MenuItem MenuItem menuItem = new MenuItem(); menuItem.Name = _digSigSignMenuItemName; menuItem.Command = DocumentApplicationDocumentViewer.Sign; DigitalSignaturesMenuItem.Items.Add(menuItem); menuItem = new MenuItem(); menuItem.Name = _digSigRequestSignersMenuItemName; menuItem.Command = DocumentApplicationDocumentViewer.RequestSigners; DigitalSignaturesMenuItem.Items.Add(menuItem); menuItem = new MenuItem(); menuItem.Name = _digSigShowSignatureSummaryMenuItemName; menuItem.Command = DocumentApplicationDocumentViewer.ShowSignatureSummary; DigitalSignaturesMenuItem.Items.Add(menuItem); // Properly handle Esc from menus DigitalSignaturesMenuItem.PreviewKeyDown += MenuPreviewKeyDown; FindToolBar.OptionsMenuItem.PreviewKeyDown += MenuPreviewKeyDown; // Setup ZoomComboBox // Bind Text to ZoomPercentage Binding bind = new Binding("Zoom"); bind.Mode = BindingMode.OneWay; bind.Source = this; ZoomComboBox.SetBinding(ZoomComboBox.ZoomProperty, bind); // Attach ZoomComboBox event handlers ZoomComboBox.LostKeyboardFocus += new KeyboardFocusChangedEventHandler(OnZoomComboBoxLostFocus); ZoomComboBox.SelectionChanged += new SelectionChangedEventHandler(OnZoomComboBoxSelectionChanged); ZoomComboBox.ZoomValueEdited += new EventHandler(OnZoomComboBoxValueEdited); ZoomComboBox.ZoomValueEditCancelled += new EventHandler(OnZoomComboBoxEditCancelled); // Set default ZoomComboBox properties ZoomComboBox.Name = _zoomComboBoxName; // Fill the ZoomComboBox items PopulateZoomComboBoxItems(); bind = new Binding("MasterPageNumber"); bind.Mode = BindingMode.OneWay; bind.Source = this; PageTextBox.SetBinding(PageTextBox.PageNumberProperty, bind); // Attach PageTextBox event handlers PageTextBox.LostKeyboardFocus += new KeyboardFocusChangedEventHandler(OnPageTextBoxLostFocus); PageTextBox.PageNumberEdited += new EventHandler(OnPageTextBoxValueEdited); PageTextBox.PageNumberEditCancelled += new EventHandler(OnPageTextBoxEditCancelled); PageTextBox.Name = _pageTextBoxName; } ////// Sets the TabIndex explicitly for all controls in the /// UI where we would want the focus to stop. /// private void SetupUITabIndices() { int tabIndex = 1; // Initial tab stop this.TabIndex = tabIndex++; // Top Toolbar SaveAsButton.TabIndex = tabIndex++; RMButton.TabIndex = tabIndex++; DigitalSignaturesMenuItem.TabIndex = tabIndex++; // Find Toolbar FindToolBar.FindTextBox.TabIndex = tabIndex++; FindToolBar.FindPreviousButton.TabIndex = tabIndex++; FindToolBar.FindNextButton.TabIndex = tabIndex++; FindToolBar.OptionsMenuItem.TabIndex = tabIndex++; // InfoBar InfoBarRMButton.TabIndex = tabIndex++; InfoBarDigSigButton.TabIndex = tabIndex++; InfoBarCloseButton.TabIndex = tabIndex++; // Bottom Toolbar region PageTextBox.TabIndex = tabIndex++; PageUpButton.TabIndex = tabIndex++; PageDownButton.TabIndex = tabIndex++; ActualSizeButton.TabIndex = tabIndex++; PageWidthButton.TabIndex = tabIndex++; WholePageButton.TabIndex = tabIndex++; TwoPageButton.TabIndex = tabIndex++; ThumbnailButton.TabIndex = tabIndex++; ZoomComboBox.TabIndex = tabIndex++; } ////// Verify that all UI controls exist. Since the ZoomComboBox uses properties of ZoomInButton /// to find the correct location to inject the control into the ToolBar, the ZoomInButton must /// be validated prior to the ZoomComboBox. /// ///private bool RequiredControlsExist() { return ((ToolBar != null) && (SaveAsButton != null) && (RMButton != null) && (DigitalSignaturesMenuItem != null) && (FindToolBar != null) && (InfoBar != null) && (PageTextBox != null) && (PageUpButton != null) && (PageDownButton != null) && (ActualSizeButton != null) && (PageWidthButton != null) && (WholePageButton != null) && (TwoPageButton != null) && (ThumbnailButton != null) && (ZoomComboBox != null) && (ScrollViewer != null) ); } /// /// Sets the visibility of the element passed in. /// /// The element whose visibility will be changed private void ChangeControlVisibility(UIElement uie) { if (uie != null) { ChangeControlVisibility(uie, uie.Visibility == Visibility.Collapsed); } } ////// Sets the visibility of the element passed in. /// /// The element whose visibility will be changed /// True if uie should be set visible, false for collapsed private void ChangeControlVisibility(UIElement uie, bool visibility) { if (uie != null) { if (visibility) { uie.Visibility = Visibility.Visible; } else { uie.Visibility = Visibility.Collapsed; } } } ////// Called when the user presses a key in the digital signatures menu or find toolbar /// If the user presses Esc this replaces the normal handling to focus on the document. /// This will only be done if the event was fired directly to the menu header and the /// menu is not currently open. /// /// The sender of the event /// Argument to the event private void MenuPreviewKeyDown(object sender, KeyEventArgs e) { MenuItem menuItem = sender as MenuItem; if (menuItem != null && menuItem.Role == MenuItemRole.TopLevelHeader && !menuItem.IsSubmenuOpen && e.Key == Key.Escape) { Focus(); e.Handled = true; } } ////// Called whenever the visibility of either the DigSig, or RM InfoBar buttons changes. /// If both are collapsed, this will hide the entire InfoBar. /// /// /// private void OnInfoBarVisibilityChanged(object sender, EventArgs e) { if ((_digSigInfoBar.Visibility == Visibility.Collapsed) && (_rmInfoBar.Visibility == Visibility.Collapsed)) { ChangeControlVisibility(InfoBar, false); } else { ChangeControlVisibility(InfoBar, true); } } ////// When the 'Close-Arrow' button is pressed, this will cause the InfoBar to Collapse /// /// /// private void OnInfoBarCloseClicked(object sender, EventArgs e) { _digSigInfoBar.Visibility = Visibility.Collapsed; _rmInfoBar.Visibility = Visibility.Collapsed; } ////// Called when any ApplicationCommand has been fired. Will perform the /// appropriate action depending on the control that was clicked. /// /// The document which hosts the command /// Event arguments private static void OnApplicationCommandExecute(object sender, ExecutedRoutedEventArgs e) { // Ensure parameters are valid, and DocumentManager is set. DocumentManager docManager = DocumentManager.CreateDefault(); Invariant.Assert( docManager != null, "Required DocumentManager instance is not available."); // Check if arguments are valid, fail silently otherwise. if ((e != null) && (e.Command != null)) { // Check which command was executed, and act appropriately if (e.Command.Equals(ApplicationCommands.Save)) { Trace.SafeWrite(Trace.File, "Save ApplicationCommand fired."); if (docManager.CanSave) { // Save document. docManager.Save(null); } else { docManager.SaveAs(null); } } else if (e.Command.Equals(ApplicationCommands.SaveAs)) { Trace.SafeWrite(Trace.File, "SaveAs ApplicationCommand fired."); // SaveAs is always available, so execute when requested. docManager.SaveAs(null); } else if (e.Command.Equals(ApplicationCommands.Properties)) { Trace.SafeWrite(Trace.Presentation, "Properties ApplicationCommand fired."); // Launch dialog here. DocumentProperties.Current.ShowDialog(); } else if (e.Command.Equals(DocumentApplicationDocumentViewer.FocusToolBar)) { Trace.SafeWrite(Trace.Presentation, "FocusToolBar command fired."); // Ensure that the sender is a DocumentApplicationDocumentViewer DocumentApplicationDocumentViewer docViewer = sender as DocumentApplicationDocumentViewer; Invariant.Assert(docViewer != null, "Sender must be a valid DocumentApplicationDocumentViewer"); // Handle command so that it doesn't bubble up to DocumentViewer e.Handled = true; // Focus the save as button since it is the first control. docViewer.SaveAsButton.Focus(); } } } ////// Central handler for QueryEnabled events fired by Commands directed at DocumentViewer. /// /// The target of this Command, expected to be DocumentViewer /// The event arguments for this event. private static void OnApplicationCommandQuery(object target, CanExecuteRoutedEventArgs e) { // Check if arguments are valid, fail silently otherwise. if ((e != null) && (e.Command != null)) { // Check which command was executed, and act appropriately if (e.Command.Equals(ApplicationCommands.Save)) { e.CanExecute = false; // Check DocumentManager to see if we can save package DocumentManager documentManager = DocumentManager.CreateDefault(); if (documentManager != null) { e.CanExecute = documentManager.CanSave && documentManager.IsModified; } Trace.SafeWrite( Trace.File, "Save ApplicationCommand queried result is {0}.", e.CanExecute); } else if (e.Command.Equals(ApplicationCommands.SaveAs)) { e.CanExecute = true; Trace.SafeWrite( Trace.File, "SaveAs ApplicationCommand queried result is {0}.", e.CanExecute); } else if (e.Command.Equals(ApplicationCommands.Properties)) { e.CanExecute = true; Trace.SafeWrite( Trace.Presentation, "Properties ApplicationCommand queried result is {0}.", e.CanExecute); } else if (e.Command.Equals(DocumentApplicationDocumentViewer.FocusToolBar)) { e.CanExecute = true; Trace.SafeWrite( Trace.Presentation, "FocusToolBar ApplicationCommand queried result is {0}.", e.CanExecute); } } } ////// Called when any NavigationCommand has been fired. Will perform the /// appropriate action depending on the control that was clicked. /// /// The document which hosts the command /// Event arguments private static void OnNavigationCommandExecute(object sender, ExecutedRoutedEventArgs e) { DocumentApplicationDocumentViewer dv = sender as DocumentApplicationDocumentViewer; if ((e != null) && (dv != null) && (e.Command != null)) { // If FirstPage or LastPage were executed, add a journal entry if (e.Command.Equals(NavigationCommands.FirstPage)) { dv.FireJournalEntryEvent(); dv.OnFirstPageCommand(); } else if (e.Command.Equals(NavigationCommands.LastPage)) { dv.FireJournalEntryEvent(); dv.OnLastPageCommand(); } } } ////// Central handler for QueryEnabled events fired by NavigationCommands directed /// at DocumentViewer. /// /// The document which hosts the command /// Event arguments private static void OnNavigationCommandQuery(object sender, CanExecuteRoutedEventArgs e) { DocumentApplicationDocumentViewer dv = sender as DocumentApplicationDocumentViewer; if ((e != null) && (dv != null) && (e.Command != null)) { // Check if the commands are allowed if (e.Command.Equals(NavigationCommands.FirstPage)) { e.CanExecute = dv.CanGoToPreviousPage; } else if (e.Command.Equals(NavigationCommands.LastPage)) { e.CanExecute = dv.CanGoToNextPage; } } } ////// Called when any DigSig command has been fired. Will perform the /// appropriate action depending on the control that was clicked. /// /// The document which hosts the command /// Event arguments private static void OnDigSigExecute(object sender, ExecutedRoutedEventArgs e) { DocumentApplicationDocumentViewer dv = sender as DocumentApplicationDocumentViewer; // Ensure parameters are valid, and DocumentSignatureManager is set. // This method is setup to fail silently if called inappropriately. if ((e != null) && (dv != null) && (dv._docSigManager != null)) { // Check which command was executed, and act appropriately if (e.Command.Equals(DocumentApplicationDocumentViewer.Sign)) { dv._docSigManager.ShowSigningDialog(); } else if (e.Command.Equals(DocumentApplicationDocumentViewer.RequestSigners)) { dv._docSigManager.ShowSignatureRequestSummaryDialog(); } else if (e.Command.Equals(DocumentApplicationDocumentViewer.ShowSignatureSummary)) { dv._docSigManager.ShowSignatureSummaryDialog(); } } } ////// Called when any DigSig command is queried for an IsEnabled value. /// /// The document which hosts the command /// Event arguments private static void OnDigSigQuery(object sender, CanExecuteRoutedEventArgs e) { DocumentApplicationDocumentViewer dv = sender as DocumentApplicationDocumentViewer; // Ensure parameters are valid, and DocumentSignatureManager is set. // This method is setup to fail silently if called inappropriately. if ((e != null) && (dv != null) && (dv._docSigManager != null)) { // Check which command was executed, and act appropriately: // 1) The Sign command can always be executed. // 2) The Request Signers command can only be executed when the document // is not signed // 3) The Show Signatures Summary command can only be executed when the // document is either signed or has signature requests // 4) No other commands should be executed if (e.Command.Equals(DocumentApplicationDocumentViewer.Sign)) { e.CanExecute = true; } else if (e.Command.Equals(DocumentApplicationDocumentViewer.RequestSigners)) { e.CanExecute = !dv._docSigManager.IsSigned; } else if (e.Command.Equals(DocumentApplicationDocumentViewer.ShowSignatureSummary)) { e.CanExecute = dv._docSigManager.IsSigned || dv._docSigManager.HasRequests; } else { e.CanExecute = false; } } } ////// Will fire an AddJournalEntry event with the current state, when needed. /// private void FireJournalEntryEvent() { AddJournalEntry(this, new DocumentApplicationJournalEntryEventArgs(GetCurrentState())); } ////// Called if a document has finished paginating, to ensure the UI state is accurate. /// /// /// private void OnPaginationCompleted(object sender, EventArgs args) { // this will change the current state to match the StoredState. SetUIToStoredState(); } #region Rights Management ////// Called when any RM command has been fired. Will perform the /// appropriate action depending on the control that was clicked. /// /// The document which hosts the command /// Event arguments private static void OnRMExecute(object sender, ExecutedRoutedEventArgs e) { DocumentApplicationDocumentViewer dv = sender as DocumentApplicationDocumentViewer; // Ensure parameters are valid, and DocumentRightsManagementManager is set. // This method is setup to fail silently if called inappropriately. if ((e != null) && (dv != null) && (dv._rmManager != null)) { // Verify that the RM Client is installed. if (dv._rmManager.IsRMInstalled) { // Check which command was executed, and act appropriately if (e.Command.Equals(DocumentApplicationDocumentViewer.ShowRMPermissions)) { dv._rmManager.ShowPermissions(); } else if (e.Command.Equals(DocumentApplicationDocumentViewer.ShowRMCredentialManager)) { dv._rmManager.ShowCredentialManagementUI(); } else if (e.Command.Equals(DocumentApplicationDocumentViewer.ShowRMPublishingUI)) { dv._rmManager.ShowPublishing(); } } else { dv._rmManager.PromptToInstallRM(); } } } ////// Called when any RM command is queried for an IsEnabled value. /// /// The document which hosts the command /// Event arguments private static void OnRMQuery(object sender, CanExecuteRoutedEventArgs e) { DocumentApplicationDocumentViewer dv = sender as DocumentApplicationDocumentViewer; // Ensure parameters are valid. // This method is setup to fail silently if called inappropriately. if ((e != null) && (dv != null)) { // Check which command was executed, and act appropriately bool isProtected = (dv._rightsManagementStatus == RightsManagementStatus.Protected); if (e.Command.Equals(DocumentApplicationDocumentViewer.ShowRMCredentialManager)) { e.CanExecute = true; } else if (e.Command.Equals(DocumentApplicationDocumentViewer.ShowRMPermissions)) { // Enable the ShowRMPermissions dialog anytime the document is already protected. // This is okay even if you're the owner because the RightsManagementManager // makes the actual decision over which dialog is shown. e.CanExecute = isProtected; } else if (e.Command.Equals(DocumentApplicationDocumentViewer.ShowRMPublishingUI)) { // Enable the ShowRMPublishing dialog whenever the dialog is not protected. e.CanExecute = !isProtected; } else { e.CanExecute = false; } } } ////// Handles the RMPolicyChanged event fired by the RMManager. /// /// /// ////// Critical - Updates _rightsManagementPolicy, which is marked SecurityCriticalDataForSet, /// with data obtained in the event arguments. /// TreatAsSafe - Since the the args have to be created and passed from critical code. In /// addition the actual RMPolicy value is protected within the args from write. /// [SecurityCritical, SecurityTreatAsSafe] private void OnRMPolicyChanged(object sender, DocumentRightsManagementManager.RightsManagementPolicyEventArgs args) { if (args != null) { //Invoke the CommandEnforcer to enable/disable commands as appropriate. _rightsManagementPolicy.Value = args.RMPolicy; CommandEnforcer.Enforce(); } else { throw new ArgumentNullException("args"); } } ////// Used to be notified of possible RM status changes. /// /// /// private void OnRMStatusChanged(object sender, DocumentRightsManagementManager.RightsManagementStatusEventArgs args) { if (args != null) { _rightsManagementStatus = args.RMStatus; if (_rightsManagementStatus == RightsManagementStatus.Protected) { RMButton.Command = DocumentApplicationDocumentViewer.ShowRMPermissions; } else { RMButton.Command = DocumentApplicationDocumentViewer.ShowRMPublishingUI; } } } #endregion Rights Management #region ZoomComboBox ////// Called when ZoomComboBox loses focus. Will reset the Text value. /// /// The ZoomComboBox to change. /// Event args private void OnZoomComboBoxLostFocus(object sender, KeyboardFocusChangedEventArgs e) { if (sender == ZoomComboBox) { // Set the default zoom value, as we've lost focus SetZoomComboBoxValue(); // Ensure that when the focus is lost no text is selected. ZoomComboBox.TextBox.Select(0, 0); } } ////// Used to apply selection when selected from list. /// /// The ZoomComboBox to change. /// Event args private void OnZoomComboBoxSelectionChanged(object sender, SelectionChangedEventArgs e) { if (sender == ZoomComboBox) { // We don't want to respond to selections generated by the user going through // the dropdown list with the keyboard. if (ZoomComboBox.ProcessSelections) { ComboBoxItem cbItem = ZoomComboBox.SelectedItem as ComboBoxItem; // Check if a selection is made (when an item is selected from the list the // SelectedItem will be non-null) if (cbItem != null && cbItem.Content is ZoomComboBoxItem) { ZoomComboBoxItem item = (ZoomComboBoxItem)cbItem.Content; // Check type of SelectedItem switch (item.Type) { // Zoom selected case ZoomComboBoxItemType.Zoom: Zoom = item.Parameter; break; // PageWidth selected case ZoomComboBoxItemType.PageWidth: FitToWidth(); break; // WholePage or TwoPages selected case ZoomComboBoxItemType.AdjacentPages: FitToMaxPagesAcross((int)item.Parameter); break; // Thumbnails selected case ZoomComboBoxItemType.Thumbnails: ViewThumbnails(); break; } } // Reset selection ZoomComboBox.SelectedIndex = -1; SetZoomComboBoxValue(); } e.Handled = true; } } ////// Called when a zoom value has been entered in the textbox. /// /// The ZoomComboBox to change. /// Event args private void OnZoomComboBoxValueEdited(object sender, EventArgs e) { double result; // Parse the new value. if (StringToZoomValue(ZoomComboBox.Text, out result)) { // The value is valid, set on DocumentViewer Zoom = result; } // Set the text shown in the ZoomComboBox to match the current Zoom value. // This is necessary when an invalid value is entered or the user has // typed a valid value that doesn't change the Zoom. SetZoomComboBoxValue(); } ////// Called when a zoom value edit has been cancelled. /// /// The ZoomComboBox to change. /// Event args private void OnZoomComboBoxEditCancelled(object sender, EventArgs e) { // Editing has been cancelled, reset the text SetZoomComboBoxValue(); } ////// Used to reset the ZoomComboBox text to the current DocumentViewer zoom value. /// private void SetZoomComboBoxValue() { // Set the current Zoom value on the ZoomComboBox ZoomComboBox.SetZoom(Zoom); } ////// Fill the ZoomComboBox with items. /// private void PopulateZoomComboBoxItems() { AddZoomComboBoxItem( new ZoomComboBoxItem( ZoomComboBoxItemType.Zoom, SR.Get(SRID.ZoomComboBoxItem400), 400.0), "Zoom400"); AddZoomComboBoxItem( new ZoomComboBoxItem( ZoomComboBoxItemType.Zoom, SR.Get(SRID.ZoomComboBoxItem250), 250.0), "Zoom250"); AddZoomComboBoxItem( new ZoomComboBoxItem( ZoomComboBoxItemType.Zoom, SR.Get(SRID.ZoomComboBoxItem150), 150.0), "Zoom150"); AddZoomComboBoxItem( new ZoomComboBoxItem( ZoomComboBoxItemType.Zoom, SR.Get(SRID.ZoomComboBoxItem100), 100.0), "Zoom100"); AddZoomComboBoxItem( new ZoomComboBoxItem( ZoomComboBoxItemType.Zoom, SR.Get(SRID.ZoomComboBoxItem75), 75.0), "Zoom75"); AddZoomComboBoxItem( new ZoomComboBoxItem( ZoomComboBoxItemType.Zoom, SR.Get(SRID.ZoomComboBoxItem50), 50.0), "Zoom50"); AddZoomComboBoxItem( new ZoomComboBoxItem( ZoomComboBoxItemType.Zoom, SR.Get(SRID.ZoomComboBoxItem25), 25.0), "Zoom25"); } ////// Wraps a ZoomComboBoxItem in a ComboBoxItem, sets the name (AutomationId) on the /// ComboBoxItem, and places it into the ZoomComboBox. /// /// New Item to add. /// Desired AutomationId private void AddZoomComboBoxItem(ZoomComboBoxItem zoomItem, String name) { // Create new ComboBox Item ComboBoxItem newItem = new ComboBoxItem(); // Assign Content and Name newItem.Content = zoomItem; newItem.Name = String.IsNullOrEmpty(name) ? String.Empty : name; // Right align the content to match the TextBox portion of the ComboBox. newItem.HorizontalAlignment = HorizontalAlignment.Right; // Add item to ZoomComboBox ZoomComboBox.Items.Add(newItem); } private static bool StringToZoomValue(string zoomString, out double zoomValue) { bool isValidArg = false; zoomValue = 0.0; CultureInfo culture = CultureInfo.CurrentCulture; // If this fails return false; try { // Remove whitespace on either end of the string. if ((culture != null) && !String.IsNullOrEmpty(zoomString)) { zoomString = zoomString.Trim(); // If this is not a neutral culture attempt to remove the percent symbol. if ((!culture.IsNeutralCulture) && (zoomString.Length > 0)) { // This will strip the percent sign (if it exists) depending on the culture information. switch (culture.NumberFormat.PercentPositivePattern) { case 0: // n % case 1: // n% // Remove the last character if it is a percent sign if (zoomString.Length - 1 == zoomString.LastIndexOf( culture.NumberFormat.PercentSymbol, StringComparison.CurrentCultureIgnoreCase)) { zoomString = zoomString.Substring(0, zoomString.Length - 1); } break; case 2: // %n case 3: // % n // Remove the first character if it is a percent sign. if (0 == zoomString.IndexOf( culture.NumberFormat.PercentSymbol, StringComparison.CurrentCultureIgnoreCase)) { zoomString = zoomString.Substring(1); } break; } } // If this conversion throws then the string wasn't a valid zoom value. zoomValue = System.Convert.ToDouble(zoomString, culture); isValidArg = true; } } // Allow empty catch statements. #pragma warning disable 56502 // Catch only the expected parse exceptions catch (ArgumentOutOfRangeException) { } catch (ArgumentNullException) { } catch (FormatException) { } catch (OverflowException) { } // Disallow empty catch statements. #pragma warning restore 56502 return isValidArg; } #endregion ZoomComboBox #region PageTextBox ////// Called when PageTextBox loses focus. Will reset the Text value. /// /// The PageTextBox to change. /// Event args private void OnPageTextBoxLostFocus(object sender, KeyboardFocusChangedEventArgs e) { if (sender == PageTextBox) { // Set the default page value, as we've lost focus SetPageTextBoxValue(); // Ensure that when the focus is lost no text is selected. PageTextBox.Select(0, 0); } } ////// Called when a page value has been entered in the textbox. /// /// The PageTextBox to change. /// Event args private void OnPageTextBoxValueEdited(object sender, EventArgs e) { int pageNumber = ParsePageNumber(PageTextBox.Text); // Check that page number is within range if ((pageNumber > 0) && (pageNumber <= PageCount)) { FireJournalEntryEvent(); NavigationCommands.GoToPage.Execute(pageNumber, this); } // Set the textbox to reflect the current page and select the number. // Reselecting the number allows the user to rapidly go between pages by // typing one number after another. If the user entered an invalid // number this will simply restore the previous value. Otherwise, // it will set the value to the first page on screen, which may not // be exactly the same as the value entered if there are multiple // pages on screen. SetPageTextBoxValue(); } ////// Called when a page value edit has been cancelled. /// /// The PageTextBox to change. /// Event args private void OnPageTextBoxEditCancelled(object sender, EventArgs e) { // Editing has been cancelled, reset the text SetPageTextBoxValue(); } ////// Used to reset the PageTextBox text to the current DocumentViewer zoom value. /// private void SetPageTextBoxValue() { // Set the current Page value on the PageTextBox PageTextBox.SetPageNumber(MasterPageNumber); } ////// Parses a string for a page number. /// /// A string representing an int pagenumber ///An int represented by the string, or -1 on a parse error public int ParsePageNumber(string pageNumberString) { CultureInfo culture = CultureInfo.CurrentCulture; // If this fails return _invalidPageNumber; try { // Remove whitespace on either end of the string. if ((culture != null) && !String.IsNullOrEmpty(pageNumberString)) { pageNumberString = pageNumberString.Trim(); // If this conversion throws then the string wasn't a valid page number value. return int.Parse(pageNumberString, culture); } } // Allow empty catch statements. #pragma warning disable 56502 // Catch only the expected parse exceptions catch (ArgumentNullException) { } catch (FormatException) { } catch (OverflowException) { } // Disallow empty catch statements. #pragma warning restore 56502 return _invalidPageNumber; } #endregion PageTextBox #region Commands ////// Set up our command bindings /// ////// Critical - creates a command binding. /// TAS - registering our own internal commands is considered safe. /// [SecurityCritical, SecurityTreatAsSafe] private static void CreateCommandBindings() { // Setup the DigSig command bindings. ExecutedRoutedEventHandler executeHandler = new ExecutedRoutedEventHandler(OnDigSigExecute); CanExecuteRoutedEventHandler queryEnabledHandler = new CanExecuteRoutedEventHandler(OnDigSigQuery); // // Command: Sign // Tells DocumentApplicationDocumentViewer to fire the Sign DigSig operation _signCommand = CreateAndBindCommand("Sign", SR.Get(SRID.DocumentApplicationDocumentViewerSignCommand), null, executeHandler, queryEnabledHandler); // // Command: RequestSigners // Tells DocumentApplicationDocumentViewer to fire the RequestSigners DigSig operation _requestSignersCommand = CreateAndBindCommand("RequestSigners", SR.Get(SRID.DocumentApplicationDocumentViewerRequestSignersCommand), null, executeHandler, queryEnabledHandler); // // Command: ShowSignatureSummary // Tells DocumentApplicationDocumentViewer to fire the ShowSignatureSummary DigSig operation _showSignatureSummaryCommand = CreateAndBindCommand("ShowSignatureSummary", SR.Get(SRID.DocumentApplicationDocumentViewerShowSignatureSummaryCommand), null, executeHandler, queryEnabledHandler); // Setup the RM command bindings. executeHandler = new ExecutedRoutedEventHandler(OnRMExecute); queryEnabledHandler = new CanExecuteRoutedEventHandler(OnRMQuery); // // Command: ShowRMPermissionsSummary // Tells DocumentApplicationDocumentViewer to fire the ShowRMPermissions operation _showRMPermissionsCommand = CreateAndBindCommand("ShowRMPermissions", SR.Get(SRID.DocumentApplicationDocumentViewerShowRMPermissionsCommand), null, executeHandler, queryEnabledHandler); // // Command: ShowRMCredentialManager // Tells DocumentApplicationDocumentViewer to fire the ShowRMCredentialManager operation _showRMCredentialManagerCommand = CreateAndBindCommand("ShowRMCredentialManager", SR.Get(SRID.DocumentApplicationDocumentViewerShowRMCredentialManagerCommand), null, executeHandler, queryEnabledHandler); // // Command: ShowRMPublishingUI // Tells DocumentApplicationDocumentViewer to fire the ShowRMPublishingUI operation _showRMPublishingUICommand = CreateAndBindCommand("ShowRMPublishingUI", SR.Get(SRID.DocumentApplicationDocumentViewerShowRMPublishingUICommand), null, executeHandler, queryEnabledHandler); // Setup the Save bindings. executeHandler = new ExecutedRoutedEventHandler(OnApplicationCommandExecute); queryEnabledHandler = new CanExecuteRoutedEventHandler(OnApplicationCommandQuery); // // Command: ApplicationCommands.Save // Tells DocumentApplicationDocumentViewer to fire the ApplicationCommands.Save operation BindCommand(ApplicationCommands.Save, executeHandler, queryEnabledHandler); // // Command: ApplicationCommands.SaveAs // Tells DocumentApplicationDocumentViewer to fire the ApplicationCommands.SaveAs operation BindCommand(ApplicationCommands.SaveAs, executeHandler, queryEnabledHandler); // // Command: ApplicationCommands.Properties // Tells DocumentApplicationDocumentViewer to fire the ApplicationCommands.Properties operation BindCommand(ApplicationCommands.Properties, executeHandler, queryEnabledHandler); // // Command: FocusToolBar // Tells DocumentApplicationDocumentViewer to fire the FocusToolBar operation // Bind to the Ctrl-F6 gesture. InputGestureCollection input = new InputGestureCollection(); input.Add(new KeyGesture(Key.F6, ModifierKeys.Control)); _focusToolBarCommand = CreateAndBindCommand("FocusToolBar", SR.Get(SRID.DocumentApplicationDocumentViewerFocusToolBarCommand), input, executeHandler, queryEnabledHandler); // // Command: ViewThumbnails // Tells DocumentViewer to fire the ViewThumbnails operation // Bind to the Ctrl+5 gesture. DocumentViewer.ViewThumbnailsCommand.InputGestures.Add(new KeyGesture(Key.D5, ModifierKeys.Control)); // Setup the NavigationCommand bindings. executeHandler = new ExecutedRoutedEventHandler(OnNavigationCommandExecute); queryEnabledHandler = new CanExecuteRoutedEventHandler(OnNavigationCommandQuery); BindCommand(NavigationCommands.FirstPage, executeHandler, queryEnabledHandler); BindCommand(NavigationCommands.LastPage, executeHandler, queryEnabledHandler); } ////// Will instantiate a command, and do the necessary registrations with the DocumentViewer /// /// Command name /// UIHeader text for the command /// Input gestures to bind /// Delegate for Execute /// Delegate for QueryEnabled ///The new registered command. private static RoutedUICommand CreateAndBindCommand(string name, string header, InputGestureCollection gestures, ExecutedRoutedEventHandler executeHandler, CanExecuteRoutedEventHandler queryEnabledHandler) { // Declare the command RoutedUICommand command = new RoutedUICommand(header, name, typeof(DocumentApplicationDocumentViewer), gestures); BindCommand(command, executeHandler, queryEnabledHandler); return command; } ////// Will register a command handler with the DocumentViewer /// /// Command to bind /// Delegate for Execute /// Delegate for QueryEnabled private static void BindCommand(RoutedUICommand command, ExecutedRoutedEventHandler executeHandler, CanExecuteRoutedEventHandler queryEnabledHandler) { if (command != null) { // Register DocumentApplicationDocumentViewer has a handler for the command. CommandManager.RegisterClassCommandBinding(typeof(DocumentApplicationDocumentViewer), new CommandBinding(command, executeHandler, queryEnabledHandler)); // Bind each input gesture on the DocumentApplicationDocumentViewer if (command.InputGestures != null) { foreach (InputGesture inputGesture in command.InputGestures) { CommandManager.RegisterClassInputBinding(typeof(DocumentApplicationDocumentViewer), new InputBinding(command, inputGesture)); } } } } ////// Creates the CommandEnforcer and adds the necessary PolicyBindings to it. /// ////// Critical /// 1) Sets critical for set field _commandEnforcer. /// 2) Calls critical function AddBinding to add bindings to the /// command enforcer. /// TreatAsSafe /// 1) The empty _commandEnforcer is created here. /// 2) Safe operation because the command enforcer is set up with all /// the enforcements that are known to be appropriate. /// [SecurityCritical, SecurityTreatAsSafe] private void CreateEnforcer() { CommandEnforcer enforcer = new CommandEnforcer(this); //Printing enforcements enforcer.AddBinding(new PolicyBinding(ApplicationCommands.Print, RightsManagementPolicy.AllowPrint)); enforcer.AddBinding(new PolicyBinding(ApplicationCommands.PrintPreview, RightsManagementPolicy.AllowPrint)); //Copy enforcements enforcer.AddBinding(new PolicyBinding(ApplicationCommands.Copy, RightsManagementPolicy.AllowCopy)); enforcer.AddBinding(new PolicyBinding(ApplicationCommands.Cut, RightsManagementPolicy.AllowCopy)); enforcer.AddBinding(new PolicyBinding(ApplicationCommands.Save, RightsManagementPolicy.AllowCopy)); enforcer.AddBinding(new PolicyBinding(ApplicationCommands.SaveAs, RightsManagementPolicy.AllowCopy)); //Signing enforcements enforcer.AddBinding(new PolicyBinding(DocumentApplicationDocumentViewer.Sign, RightsManagementPolicy.AllowSign)); enforcer.AddBinding(new PolicyBinding(DocumentApplicationDocumentViewer.RequestSigners, RightsManagementPolicy.AllowSign)); _commandEnforcer.Value = enforcer; } #endregion Commands #endregion Private Methods //----------------------------------------------------- // // Private Fields // // These must be checked for null prior to use. If available, use the CLR properties // above before these. // //------------------------------------------------------ #region Private Fields // Used to override Document ViewerBase OnPrintCommand #if !DONOTREFPRINTINGASMMETA private XpsDocumentWriter _documentWriter; // DocumentWriter used for printing. #endif // DONOTREFPRINTINGASMMETA // The single instance of our DocumentApplicationDocumentViewer private static DocumentApplicationDocumentViewer _singletonInstance; private DocumentSignatureManager _docSigManager; private DocumentRightsManagementManager _rmManager; private bool _isUISetup; private StatusInfoItem _digSigInfoBar; private StatusInfoItem _rmInfoBar; private DocumentApplicationState _state; private const int _invalidPageNumber = -1; private SecurityCriticalDataForSet_rightsManagementPolicy; private RightsManagementStatus _rightsManagementStatus; // The enforcer for RM private SecurityCriticalDataForSet _commandEnforcer; // Declare commands that are located on DocumentApplicationDocumentViewer private static RoutedUICommand _focusToolBarCommand; private static RoutedUICommand _signCommand; private static RoutedUICommand _requestSignersCommand; private static RoutedUICommand _showSignatureSummaryCommand; private static RoutedUICommand _showRMPermissionsCommand; private static RoutedUICommand _showRMCredentialManagerCommand; private static RoutedUICommand _showRMPublishingUICommand; // All of the items below have clr properties above. private Grid _toolBar; private ZoomComboBox _zoomComboBox; private Button _pageUpButton; private PageTextBox _pageTextBox; private Button _pageDownButton; private Button _actualSizeButton; private Button _pageWidthButton; private Button _wholePageButton; private Button _twoPageButton; private Button _thumbnailButton; private Button _saveAsButton; private Button _rmButton; private MenuItem _digitalSignaturesMenuItem; private FrameworkElement _infoBar; private Button _infoBarDigSigButton; private Button _infoBarRMButton; private Button _infoBarCloseButton; private FindToolBar _findToolBar; private ScrollViewer _scrollViewer; // Constants for style name references. private const string _toolBarName = "PUIDocumentApplicationToolBar"; private const string _toolBarStyleKeyName = "PUIDocumentApplicationToolBarStyleKey"; private const string _zoomComboBoxName = "PUIDocumentApplicationZoomComboBox"; private const string _pageUpButtonName = "PUIDocumentApplicationPageUpButton"; private const string _pageTextBoxName = "PUIDocumentApplicationPageTextBox"; private const string _pageDownButtonName = "PUIDocumentApplicationPageDownButton"; private const string _actualSizeButtonName = "PUIDocumentApplicationActualSizeButton"; private const string _pageWidthButtonName = "PUIDocumentApplicationPageWidthButton"; private const string _wholePageButtonName = "PUIDocumentApplicationWholePageButton"; private const string _twoPageButtonName = "PUIDocumentApplicationTwoPagesButton"; private const string _thumbnailButtonName = "PUIDocumentApplicationThumbnailButton"; private const string _saveAsButtonName = "PUIDocumentApplicationSaveAsButton"; private const string _rmButtonName = "PUIDocumentApplicationRMButton"; private const string _digitalSignaturesMenuItemName = "PUIDocumentApplicationDigitalSignaturesMenuItem"; private const string _infoBarName = "PUIDocumentApplicationInfoBar"; private const string _forwardButtonName = "PUIDocumentApplicationForwardButton"; private const string _backButtonName = "PUIDocumentApplicationBackButton"; private const string _digSigSignMenuItemName = "PUIDocumentApplicationDigSigSignMenuItem"; private const string _digSigRequestSignersMenuItemName = "PUIDocumentApplicationDigSigRequestSignersMenuItem"; private const string _digSigShowSignatureSummaryMenuItemName = "PUIDocumentApplicationDigSigShowSignatureSummaryMenuItem"; private const string _infoBarSignaturesButtonName = "PUIDocumentApplicationInfoBarSignaturesButton"; private const string _infoBarRMButtonName = "PUIDocumentApplicationInfoBarRMButton"; private const string _infoBarCloseButtonName = "PUIDocumentApplicationInfoBarCloseButton"; private const string _contentHostName = "PART_ContentHost"; /// /// An IWin32Window reference to the RootBrowserWindow hosting XPSViewer. /// [SecurityCritical] private System.Windows.Forms.IWin32Window _rootBrowserWindow; #endregion Private Fields //------------------------------------------------------ // // Private Nested Classes // //----------------------------------------------------- #region WrapperIWin32Window ////// Critical /// 1) IWin32Window exposes an IntPtr handle to the window, which could be used /// for malicious purposes. /// ////// This class exists for the sole purpose of wrapping an IntPtr Window handle into /// an IWin32Window object that our WinForms dialogs can use. /// private class WrapperIWin32Window : System.Windows.Forms.IWin32Window { ////// Constructor for WrapperIWin32Window /// /// [SecurityCritical] public WrapperIWin32Window(IntPtr handle) { _handle = handle; } ////// Critical - instantiating an instance is considered critical /// because it wraps a critical window handle. /// ////// Returns the handle for this IWin32Window object /// /// IntPtr System.Windows.Forms.IWin32Window.Handle { [SecurityCritical] get { return _handle; } } ////// Critical - get: A Window handle is considered critical data. /// ////// The window handle for this IWin32Window object /// [SecurityCritical] private IntPtr _handle; } #endregion WrapperIWin32Window #region ZoomComboBoxItem ////// Critical - A Window handle is considered critical data. /// ////// Used to determine what type of item was selected from a ZoomComboBox /// private enum ZoomComboBoxItemType { Unknown = -1, Zoom, PageWidth, AdjacentPages, Thumbnails, } ////// Used as an item in a ZoomComboBox /// private struct ZoomComboBoxItem { ////// Constructor /// /// Type of item /// String representation /// Zoom value, or number of pages public ZoomComboBoxItem(ZoomComboBoxItemType itemType, string description, double parameter) { _type = itemType; _description = description; _parameter = parameter; } ////// Type of ZoomComboBox item this refers to /// public ZoomComboBoxItemType Type { get { return _type; } } ////// A double value which is used for as a zoom value or the number of adjacent /// pages to display, depending on the Type defined. /// public double Parameter { get { return _parameter; } } ////// Returns the description, to be displayed in the ComboBox /// ///public override string ToString() { return _description; } // Private fields. private ZoomComboBoxItemType _type; private string _description; private double _parameter; } #endregion ZoomComboBoxItem #region ScalingDocument /// /// Paginates any document source and scales to fit paper /// private sealed class ScalingDocument : DocumentPaginator { ////// Constructor for ScalingDocument /// /// Document to be printed /// Imagable area of page public ScalingDocument(IDocumentPaginatorSource document, PrintDocumentImageableArea ia) { _documentPaginator = document.DocumentPaginator; _ia = ia; } ////// Returns a scaled DocumentPage /// public override DocumentPage GetPage(int pageNumber) { DocumentPage page = null; FixedPage fixedPage = null; FixedDocument fd = _documentPaginator.Source as FixedDocument; if (fd != null && pageNumber < fd.Pages.Count) { fixedPage = fd.Pages[pageNumber].GetPageRoot(false) as FixedPage; } if (fixedPage == null) { page = _documentPaginator.GetPage(pageNumber); fixedPage = page.Visual as FixedPage; } if (fixedPage!=null) { Rect bleedBox = fixedPage.BleedBox; Rect contentBox = fixedPage.ContentBox; // // Create a Canvas and transfer all children of the fixedPage to the Canvas. // This is required, because XpsDocumentWriter.Write does not handle FixedPage returned // as the Visual from DocumentPaginator.GetPage() // Canvas canvas = new Canvas(); canvas.BeginInit(); canvas.Language = fixedPage.Language; canvas.Name = fixedPage.Name; UIElement[] children = new UIElement[fixedPage.Children.Count]; int i = 0; foreach (UIElement child in fixedPage.Children) { children[i++] = child; } fixedPage.Children.Clear(); foreach (UIElement child in children) { canvas.Children.Add(child); } // // First check if the FixedPage fits onto the imagable area // Rect pageBounds = new Rect(0.0, 0.0, fixedPage.Width, fixedPage.Height); TransformGroup tg = new TransformGroup(); tg.Children.Add(Transform.Identity); // // See if this is a case of mismatched orientation // bool documentPagePortrait = (fixedPage.Width < fixedPage.Height); bool physicalPagePortrait = (_ia.MediaSizeWidth < _ia.MediaSizeHeight); if (documentPagePortrait != physicalPagePortrait) { // // Must Rotate // if (documentPagePortrait) { // // Printing a Portrait document on a landscape paper. Rotate clockwise // (Rotation direction is NOT arbitrary and matches printschema!) // And shift origin to fit // tg.Children.Add(new MatrixTransform(0.0, 1.0, -1.0, 0.0, fixedPage.Height, 0.0)); } else { // // Printing a Landscape document on a portrait paper. Rotate counter-clockwise // (Rotation direction is NOT arbitrary and matches printschema!) // And shift origin to fit // tg.Children.Add(new MatrixTransform(0.0, -1.0, 1.0, 0.0, 0.0, fixedPage.Width)); } pageBounds = tg.TransformBounds(pageBounds); } if (pageBounds.Width > _ia.MediaSizeWidth || pageBounds.Height > _ia.MediaSizeHeight ) { // // We need to scale, because page is too big // double factorX = _ia.MediaSizeWidth / pageBounds.Width; double factorY = _ia.MediaSizeHeight / pageBounds.Height; // // Scale uniformly by smaller of two factors. // if (factorY < factorX) { factorX = factorY; } ScaleTransform scale = new ScaleTransform(factorX, factorX); tg.Children.Add(scale); pageBounds = scale.TransformBounds(pageBounds); } // // Now center the result // double left = (_ia.MediaSizeWidth - pageBounds.Width) / 2.0; double top = (_ia.MediaSizeHeight - pageBounds.Height) / 2.0; if (left > 0.0 || top > 0.0) { tg.Children.Add(new TranslateTransform(left - pageBounds.Left, top - pageBounds.Top)); } // // Attach resulting transform // canvas.RenderTransform = tg; canvas.EndInit(); // // Finally, force measure and arrange // Size size = new Size(_ia.MediaSizeWidth, _ia.MediaSizeHeight); canvas.Measure(size); canvas.Arrange(new Rect(size)); canvas.UpdateLayout(); if ( !bleedBox.IsEmpty ) { bleedBox= tg.TransformBounds(bleedBox); } if (!contentBox.IsEmpty) { contentBox = tg.TransformBounds(contentBox); } page = new DocumentPage(canvas, size, bleedBox, contentBox); } return page; } public override bool IsPageCountValid { get { return _documentPaginator.IsPageCountValid; } } public override int PageCount { get { return _documentPaginator.PageCount; } } public override System.Windows.Size PageSize { get { return _documentPaginator.PageSize; } set { _documentPaginator.PageSize = value; } } public override IDocumentPaginatorSource Source { get { return _documentPaginator.Source; } } // Private fields. private DocumentPaginator _documentPaginator; private PrintDocumentImageableArea _ia; } #endregion ScalingDocument } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- storepermissionattribute.cs
- XmlNodeChangedEventArgs.cs
- TableLayoutPanel.cs
- DefaultTraceListener.cs
- BamlRecordHelper.cs
- ActivityExecutionContext.cs
- _ContextAwareResult.cs
- CodeConditionStatement.cs
- AppSettingsSection.cs
- IUnknownConstantAttribute.cs
- XmlDataSourceView.cs
- ConsumerConnectionPointCollection.cs
- Sentence.cs
- BufferAllocator.cs
- InvokeGenerator.cs
- XmlNavigatorFilter.cs
- GridViewRowCollection.cs
- XmlWriter.cs
- KnownBoxes.cs
- StringCollection.cs
- DesignerHelpers.cs
- HtmlAnchor.cs
- DropSourceBehavior.cs
- WebMethodAttribute.cs
- UnaryNode.cs
- _UriSyntax.cs
- TokenizerHelper.cs
- TabItem.cs
- IgnoreDeviceFilterElementCollection.cs
- HtmlSelect.cs
- DataObject.cs
- PopupControlService.cs
- KeyNameIdentifierClause.cs
- TokenizerHelper.cs
- TypeValidationEventArgs.cs
- TypographyProperties.cs
- EventLogTraceListener.cs
- ExpressionTable.cs
- WebPartsPersonalization.cs
- DataColumnCollection.cs
- HostedElements.cs
- SystemInformation.cs
- ConfigXmlAttribute.cs
- JpegBitmapDecoder.cs
- typedescriptorpermissionattribute.cs
- DataGridCommandEventArgs.cs
- PTConverter.cs
- ControlTemplate.cs
- InheritanceService.cs
- WebPartDeleteVerb.cs
- SurrogateEncoder.cs
- SystemPens.cs
- DoubleLinkListEnumerator.cs
- ExceptionUtil.cs
- GACIdentityPermission.cs
- ReachSerializationUtils.cs
- MSG.cs
- X500Name.cs
- D3DImage.cs
- UInt16Converter.cs
- WSHttpBinding.cs
- EntitySetRetriever.cs
- DefaultBindingPropertyAttribute.cs
- HttpMethodAttribute.cs
- MessageQueuePermission.cs
- FtpWebResponse.cs
- XmlTextReaderImpl.cs
- ExportException.cs
- RegexCompilationInfo.cs
- RemotingConfigParser.cs
- VirtualPathUtility.cs
- WebSysDisplayNameAttribute.cs
- ColorInterpolationModeValidation.cs
- IdentityHolder.cs
- SQLStringStorage.cs
- BlockCollection.cs
- ContainerUIElement3D.cs
- FormClosedEvent.cs
- SigningCredentials.cs
- DataGridViewComponentPropertyGridSite.cs
- WeakReferenceList.cs
- NativeRecognizer.cs
- QilVisitor.cs
- GridView.cs
- WebBrowserProgressChangedEventHandler.cs
- Decimal.cs
- ControlBindingsCollection.cs
- SyntaxCheck.cs
- Base64Decoder.cs
- HttpModuleActionCollection.cs
- CacheDependency.cs
- CalendarModeChangedEventArgs.cs
- Variant.cs
- HTTPNotFoundHandler.cs
- PageParser.cs
- Vector3DCollection.cs
- FlagsAttribute.cs
- DynamicDataExtensions.cs
- AdornedElementPlaceholder.cs
- InfoCardRSAOAEPKeyExchangeDeformatter.cs