//XpsCreate.cpp file using namespace System; using namespace System::IO; using namespace System::Collections::Generic; using namespace System::IO::Packaging; using namespace System::Xml; using namespace System::Windows::Forms; using namespace System::Windows::Xps; using namespace System::Windows::Xps::Packaging; using namespace System::Printing; public ref class XpsCreate { private: literal System::String^ packageWithPrintTicketName = "XpsDocument-withPrintTicket.xps"; literal System::String^ packageName = "XpsDocument.xps"; literal System::String^ image1 = "picture.jpg"; literal System::String^ image2 = "image.tif"; literal System::String^ font1 = "courier.ttf"; literal System::String^ font2 = "arial.ttf"; literal System::String^ fontContentType = "application/vnd.ms-package.obfuscated-opentype"; public: [STAThread()] static void Main (array^ args) { XpsCreate^ xpsCreate = gcnew XpsCreate(); xpsCreate->Run(); }; public: // -------------------------------- Run ----------------------------------- /// /// Creates two XpsDocument packages, the first without a PrintTicket /// and a second with a PrintTicket. void Run () { // First, create an XpsDocument without a PrintTicket. - - - - - - - - // If the document package exists from a previous run, delete it. if (File::Exists(packageName)) { File::Delete(packageName); } // Create an XpsDocument package (without PrintTicket). { Package^ package = Package::Open(packageName); try { XpsDocument^ xpsDocument = gcnew XpsDocument(package); // Add the package content (false=without PrintTicket). AddPackageContent(xpsDocument, false); // Close the package. xpsDocument->Close(); } finally { delete package; } // Next, create a second XpsDocument with a PrintTicket. - - - - - - - // If the document package exists from a previous run, delete it. if (File::Exists(packageWithPrintTicketName)) { File::Delete(packageWithPrintTicketName); } // Create an XpsDocument with PrintTicket. { Package^ package2 = Package::Open(packageWithPrintTicketName); try { XpsDocument^ xpsDocumentWithPrintTicket = gcnew XpsDocument(package2); // Add the package content (true=with PrintTicket). AddPackageContent(xpsDocumentWithPrintTicket, true); // Close the package. xpsDocumentWithPrintTicket->Close(); } finally { delete package2; } } System::String^ msg = "Created two XPS document packages:\n - " + packageName + "\n - " + packageWithPrintTicketName; MessageBox::Show(msg, "Normal Completion", MessageBoxButtons::OK, MessageBoxIcon::Information); } }; private: // ------------------------- AddPackageContent ---------------------------- /// /// Adds a predefined set of content to a given XPS document. /// /// The package to add the document content to. /// /// true to include a PrintTicket with the /// document; otherwise, false. void AddPackageContent (XpsDocument^ xpsDocument, bool attachPrintTicket) { try { PrintTicket^ printTicket = GetPrintTicketFromPrinter(); // PrintTicket is null, there is no need to attach one. if (printTicket == nullptr) { attachPrintTicket = false; } // Add a FixedDocumentSequence at the Package root IXpsFixedDocumentSequenceWriter^ documentSequenceWriter = xpsDocument->AddFixedDocumentSequence(); // Add the 1st FixedDocument to the FixedDocumentSequence. - - - - - IXpsFixedDocumentWriter^ fixedDocumentWriter = documentSequenceWriter->AddFixedDocument(); AddDocumentContent(fixedDocumentWriter); // Commit the 1st Document fixedDocumentWriter->Commit(); // Add a 2nd FixedDocument to the FixedDocumentSequence. - - - - - - fixedDocumentWriter = documentSequenceWriter->AddFixedDocument(); // Add content to the 2nd document. AddDocumentContent(fixedDocumentWriter); // If attaching PrintTickets, attach one at the FixedDocument level. if (attachPrintTicket) { fixedDocumentWriter->PrintTicket = printTicket; } // Commit the 2nd document. fixedDocumentWriter->Commit(); // If attaching PrintTickets, attach one at // the package FixedDocumentSequence level. if (attachPrintTicket) { documentSequenceWriter->PrintTicket = printTicket; } // Commit the FixedDocumentSequence documentSequenceWriter->Commit(); } catch (XpsPackagingException^ xpsException) { throw xpsException; } };// end:AddPackageContent() // ------------------------- AddDocumentContent --------------------------- /// /// Adds a predefined set of content to a given document writer. /// /// The document writer to add the content to. void AddDocumentContent (IXpsFixedDocumentWriter^ fixedDocumentWriter) { // Collection of image and font resources used on the current page. // Key: "XpsImage", "XpsFont" // Value: List of XpsImage or XpsFont resources Dictionary^>^ resources; try { // Add Page 1 to current document. IXpsFixedPageWriter^ fixedPageWriter = fixedDocumentWriter->AddFixedPage(); // Add the resources for Page 1 and get the resource collection. resources = AddPageResources(fixedPageWriter); // Write page content for Page 1. WritePageContent(fixedPageWriter->XmlWriter, "Page 1 of " + fixedDocumentWriter->Uri->ToString(), resources); // Commit Page 1. fixedPageWriter->Commit(); // Add Page 2 to current document. fixedPageWriter = fixedDocumentWriter->AddFixedPage(); // Add the resources for Page 2 and get the resource collection. resources = AddPageResources(fixedPageWriter); // Write page content to Page 2. WritePageContent(fixedPageWriter->XmlWriter, "Page 2 of " + fixedDocumentWriter->Uri->ToString(), resources); // Commit Page 2. fixedPageWriter->Commit(); } catch (XpsPackagingException^ xpsException) { throw xpsException; } };// end:AddDocumentContent() // -------------------------- AddPageResources ---------------------------- Dictionary^>^ AddPageResources (IXpsFixedPageWriter^ fixedPageWriter) { // Collection of all resources for this page. // Key: "XpsImage", "XpsFont" // Value: List of XpsImage or XpsFont Dictionary^>^ resources = gcnew Dictionary^>(); // Collections of images and fonts used in the current page. List^ xpsImages = gcnew List(); List^ xpsFonts = gcnew List(); try { XpsImage^ xpsImage; XpsFont^ xpsFont; // Add, Write, and Commit image1 to the current page. xpsImage = fixedPageWriter->AddImage(XpsImageType::JpegImageType); WriteToStream(xpsImage->GetStream(), image1); xpsImage->Commit(); xpsImages->Add(xpsImage); // Add image1 as a required resource. // Add, Write, and Commit font 1 to the current page. xpsFont = fixedPageWriter->AddFont(); WriteObfuscatedStream(xpsFont->Uri->ToString(), xpsFont->GetStream(), font1); xpsFont->Commit(); xpsFonts->Add(xpsFont); // Add font1 as a required resource. // Add, Write, and Commit image2 to the current page. xpsImage = fixedPageWriter->AddImage(XpsImageType::TiffImageType); WriteToStream(xpsImage->GetStream(), image2); xpsImage->Commit(); xpsImages->Add(xpsImage); // Add image2 as a required resource. // Add, Write, and Commit font2 to the current page. xpsFont = fixedPageWriter->AddFont(false); WriteToStream(xpsFont->GetStream(), font2); xpsFont->Commit(); xpsFonts->Add(xpsFont); // Add font2 as a required resource. // Return the image and font resources in a combined collection. resources->Add("XpsImage", xpsImages); resources->Add("XpsFont", xpsFonts); return resources; } catch (XpsPackagingException^ xpsException) { throw xpsException; } };// end:AddPageResources() // ---------------------- GetPrintTicketFromPrinter ----------------------- /// /// Returns a PrintTicket based on the current default printer. /// /// A PrintTicket for the current local default printer. PrintTicket^ GetPrintTicketFromPrinter () { PrintQueue^ printQueue = nullptr; LocalPrintServer^ localPrintServer = gcnew LocalPrintServer(); // Retrieving collection of local printer on user machine PrintQueueCollection^ localPrinterCollection = localPrintServer->GetPrintQueues(); System::Collections::IEnumerator^ localPrinterEnumerator = localPrinterCollection->GetEnumerator(); if (localPrinterEnumerator->MoveNext()) { // Get PrintQueue from first available printer printQueue = ((PrintQueue^)localPrinterEnumerator->Current); } else { return nullptr; } // Get default PrintTicket from printer PrintTicket^ printTicket = printQueue->DefaultPrintTicket; PrintCapabilities^ printCapabilites = printQueue->GetPrintCapabilities(); // Modify PrintTicket if (printCapabilites->CollationCapability->Contains(Collation::Collated)) { printTicket->Collation = Collation::Collated; } if (printCapabilites->DuplexingCapability->Contains(Duplexing::TwoSidedLongEdge)) { printTicket->Duplexing = Duplexing::TwoSidedLongEdge; } if (printCapabilites->StaplingCapability->Contains(Stapling::StapleDualLeft)) { printTicket->Stapling = Stapling::StapleDualLeft; } return printTicket; };// end:GetPrintTicketFromPrinter() // --------------------------- WritePageContent --------------------------- void WritePageContent (System::Xml::XmlWriter^ xmlWriter, System::String^ documentUri, Dictionary^>^ resources) { List^ xpsImages = resources["XpsImage"]; List^ xpsFonts = resources["XpsFont"]; // Element are indented for reading purposes only xmlWriter->WriteStartElement("FixedPage"); xmlWriter->WriteAttributeString("Width", "816"); xmlWriter->WriteAttributeString("Height", "1056"); xmlWriter->WriteAttributeString("xmlns", "http://schemas.microsoft.com/xps/2005/06"); xmlWriter->WriteAttributeString("xml:lang", "en-US"); xmlWriter->WriteStartElement("Glyphs"); xmlWriter->WriteAttributeString("Fill", "#ff000000"); xmlWriter->WriteAttributeString("FontUri", xpsFonts[0]->Uri->ToString()); xmlWriter->WriteAttributeString("FontRenderingEmSize", "18"); xmlWriter->WriteAttributeString("OriginX", "120"); xmlWriter->WriteAttributeString("OriginY", "110"); xmlWriter->WriteAttributeString("UnicodeString", documentUri); xmlWriter->WriteEndElement(); xmlWriter->WriteStartElement("Glyphs"); xmlWriter->WriteAttributeString("Fill", "#ff000000"); xmlWriter->WriteAttributeString("FontUri", xpsFonts[1]->Uri->ToString()); xmlWriter->WriteAttributeString("FontRenderingEmSize", "16"); xmlWriter->WriteAttributeString("OriginX", "120"); xmlWriter->WriteAttributeString("OriginY", "130"); xmlWriter->WriteAttributeString("UnicodeString", "Test String in Arial"); xmlWriter->WriteEndElement(); xmlWriter->WriteStartElement("Path"); xmlWriter->WriteAttributeString("Data", "M 120,187 L 301,187 301,321 120,321 z"); xmlWriter->WriteStartElement("Path.Fill"); xmlWriter->WriteStartElement("ImageBrush"); xmlWriter->WriteAttributeString("ImageSource", xpsImages[0]->Uri->ToString()); xmlWriter->WriteAttributeString("Viewbox", "0,0,181,134"); xmlWriter->WriteAttributeString("TileMode", "None"); xmlWriter->WriteAttributeString("ViewboxUnits", "Absolute"); xmlWriter->WriteAttributeString("ViewportUnits", "Absolute"); xmlWriter->WriteAttributeString("Viewport", "120,187,181,134"); xmlWriter->WriteEndElement(); xmlWriter->WriteEndElement(); xmlWriter->WriteEndElement(); xmlWriter->WriteStartElement("Path"); xmlWriter->WriteAttributeString("Data", "M 120,357 L 324,357 324,510 120,510 z"); xmlWriter->WriteStartElement("Path.Fill"); xmlWriter->WriteStartElement("ImageBrush"); xmlWriter->WriteAttributeString("ImageSource", xpsImages[1]->Uri->ToString()); xmlWriter->WriteAttributeString("Viewbox", "0,0,204,153"); xmlWriter->WriteAttributeString("TileMode", "None"); xmlWriter->WriteAttributeString("ViewboxUnits", "Absolute"); xmlWriter->WriteAttributeString("ViewportUnits", "Absolute"); xmlWriter->WriteAttributeString("Viewport", "120,357,204,153"); xmlWriter->WriteEndElement(); xmlWriter->WriteEndElement(); xmlWriter->WriteEndElement(); xmlWriter->WriteEndElement(); };// end:WritePageContent() // ----------------------------- WriteToStream ---------------------------- void WriteToStream (System::IO::Stream^ stream, System::String^ resource) { int bufSize = 0x1000; array^ buf = gcnew array(bufSize); int bytesRead = 0; { System::IO::FileStream^ fileStream = gcnew System::IO::FileStream(resource, FileMode::Open, FileAccess::Read); try { while ((bytesRead = fileStream->Read(buf, 0, bufSize)) > 0) { stream->Write(buf, 0, bytesRead); } } finally { delete fileStream; } } }; // ------------------------- WriteObfuscatedStream ------------------------ void WriteObfuscatedStream (System::String^ resourceName, System::IO::Stream^ stream, System::String^ resource) { int bufSize = 0x1000; int guidByteSize = 16; int obfuscatedByte = 32; // Get the GUID byte from the resource name. Typical Font name: // /Resources/Fonts/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.ODTTF int startPos = resourceName->LastIndexOf('/') + 1; int length = resourceName->LastIndexOf('.') - startPos; resourceName = resourceName->Substring(startPos, length); System::Guid guid = System::Guid(resourceName); System::String^ guidString = guid.ToString("N"); // Parsing the guid string and coverted into byte value array^ guidBytes = gcnew array(guidByteSize); for ( int i = 0; i < guidBytes->Length; i++) { guidBytes[i] = Convert::ToByte(guidString->Substring(i * 2, 2), 16); } { System::IO::FileStream^ filestream = gcnew System::IO::FileStream(resource, FileMode::Open); try { // XOR the first 32 bytes of the source // resource stream with GUID byte. array^ buf = gcnew array(obfuscatedByte); filestream->Read(buf, 0, obfuscatedByte); for ( int i = 0; i < obfuscatedByte; i++) { int guidBytesPos = guidBytes->Length - (i % guidBytes->Length) - 1; buf[i] ^= guidBytes[guidBytesPos]; } stream->Write(buf, 0, obfuscatedByte); // copy remaining stream from source without obfuscation buf = gcnew array(bufSize); int bytesRead = 0; while ((bytesRead = filestream->Read(buf, 0, bufSize)) > 0) { stream->Write(buf, 0, bytesRead); } } finally { delete filestream; } } }; }; //Entry Point: int main (array^ args) { XpsCreate::Main(args); return 0; }