// =========================================================================== //  ©2013-2026 WebSupergoo. All rights reserved. // //  This source code is for use exclusively with the ABCpdf product with //  which it is distributed, under the terms of the license for that //  product. Details can be found at // //    http://www.websupergoo.com/ // //  This copyright notice must not be deleted and must be reproduced alongside //  any sections of code extracted from this module. // =========================================================================== using System; using System.Drawing; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Windows.Forms; using System.Data; using System.Runtime; using System.Diagnostics; using System.IO; using System.Text; using System.Xml; using WebSupergoo.ABCpdf14; using WebSupergoo.ABCpdf14.Objects; using WebSupergoo.ABCpdf14.Operations; using WebSupergoo.ABCpdf14.Atoms; using OptionalContent; namespace OCGLayers {   /// <summary>   /// Summary description for Form1.   /// </summary>   public class Form1 : System.Windows.Forms.Form {     private Button annotateButton;     private Button removeButton;     private TextBox textBox2;     private PictureBox previewPictureBox;     private CheckedListBox layersCheckedListBox;     private ComboBox pageCombo;     private Button openButton;     private Button saveButton;     private Button createButton1;     private Button createButton2;     private Button createButton3;     private TextBox textBox1;     private TextBox textBox3;     private Button openExternallyButton;     private Button purgeButton;     /// <summary>     /// Required designer variable.     /// </summary>     private System.ComponentModel.Container components = null;     public Form1()     {       //       // Required for Windows Form Designer support       //       InitializeComponent();       //       // TODO: Add any constructor code after InitializeComponent call       //     }     /// <summary>     /// Clean up any resources being used.     /// </summary>     protected override void Dispose( bool disposing )     {       if( disposing )       {         if (components != null)         {           components.Dispose();         }       }       base.Dispose( disposing );     }     #region Windows Form Designer generated code     /// <summary>     /// Required method for Designer support - do not modify     /// the contents of this method with the code editor.     /// </summary>     private void InitializeComponent()     {       this.annotateButton = new System.Windows.Forms.Button();       this.removeButton = new System.Windows.Forms.Button();       this.textBox2 = new System.Windows.Forms.TextBox();       this.previewPictureBox = new System.Windows.Forms.PictureBox();       this.layersCheckedListBox = new System.Windows.Forms.CheckedListBox();       this.pageCombo = new System.Windows.Forms.ComboBox();       this.openButton = new System.Windows.Forms.Button();       this.saveButton = new System.Windows.Forms.Button();       this.createButton1 = new System.Windows.Forms.Button();       this.createButton2 = new System.Windows.Forms.Button();       this.createButton3 = new System.Windows.Forms.Button();       this.textBox1 = new System.Windows.Forms.TextBox();       this.textBox3 = new System.Windows.Forms.TextBox();       this.openExternallyButton = new System.Windows.Forms.Button();       this.purgeButton = new System.Windows.Forms.Button();       ((System.ComponentModel.ISupportInitialize)(this.previewPictureBox)).BeginInit();       this.SuspendLayout();       //       // annotateButton       //       this.annotateButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));       this.annotateButton.Location = new System.Drawing.Point(666, 505);       this.annotateButton.Name = "annotateButton";       this.annotateButton.Size = new System.Drawing.Size(186, 26);       this.annotateButton.TabIndex = 2;       this.annotateButton.Text = "Annotate Layers";       this.annotateButton.Click += new System.EventHandler(this.annotateButton_Click);       //       // removeButton       //       this.removeButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));       this.removeButton.Location = new System.Drawing.Point(666, 538);       this.removeButton.Name = "removeButton";       this.removeButton.Size = new System.Drawing.Size(186, 76);       this.removeButton.TabIndex = 3;       this.removeButton.Text = "Delete Content of Invisible Layers and Remove From Page";       this.removeButton.Click += new System.EventHandler(this.removeButton_Click);       //       // textBox2       //       this.textBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)             | System.Windows.Forms.AnchorStyles.Right)));       this.textBox2.Location = new System.Drawing.Point(19, 770);       this.textBox2.Name = "textBox2";       this.textBox2.Size = new System.Drawing.Size(623, 22);       this.textBox2.TabIndex = 5;       //       // previewPictureBox       //       this.previewPictureBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)             | System.Windows.Forms.AnchorStyles.Left)             | System.Windows.Forms.AnchorStyles.Right)));       this.previewPictureBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;       this.previewPictureBox.Location = new System.Drawing.Point(19, 21);       this.previewPictureBox.Name = "previewPictureBox";       this.previewPictureBox.Size = new System.Drawing.Size(623, 730);       this.previewPictureBox.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;       this.previewPictureBox.TabIndex = 6;       this.previewPictureBox.TabStop = false;       //       // layersCheckedListBox       //       this.layersCheckedListBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));       this.layersCheckedListBox.FormattingEnabled = true;       this.layersCheckedListBox.Location = new System.Drawing.Point(666, 57);       this.layersCheckedListBox.Name = "layersCheckedListBox";       this.layersCheckedListBox.Size = new System.Drawing.Size(186, 106);       this.layersCheckedListBox.TabIndex = 7;       this.layersCheckedListBox.ItemCheck += new System.Windows.Forms.ItemCheckEventHandler(this.layersCheckedListBox_ItemCheck);       //       // pageCombo       //       this.pageCombo.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));       this.pageCombo.FormattingEnabled = true;       this.pageCombo.Location = new System.Drawing.Point(666, 21);       this.pageCombo.Name = "pageCombo";       this.pageCombo.Size = new System.Drawing.Size(186, 24);       this.pageCombo.TabIndex = 8;       this.pageCombo.SelectedIndexChanged += new System.EventHandler(this.pageCombo_SelectedIndexChanged);       //       // openButton       //       this.openButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));       this.openButton.Location = new System.Drawing.Point(19, 804);       this.openButton.Name = "openButton";       this.openButton.Size = new System.Drawing.Size(124, 26);       this.openButton.TabIndex = 9;       this.openButton.Text = "Load PDF...";       this.openButton.Click += new System.EventHandler(this.openButton_Click);       //       // saveButton       //       this.saveButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));       this.saveButton.Location = new System.Drawing.Point(270, 804);       this.saveButton.Name = "saveButton";       this.saveButton.Size = new System.Drawing.Size(124, 26);       this.saveButton.TabIndex = 10;       this.saveButton.Text = "Save PDF...";       this.saveButton.Click += new System.EventHandler(this.saveButton_Click);       //       // createButton1       //       this.createButton1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));       this.createButton1.Location = new System.Drawing.Point(666, 291);       this.createButton1.Name = "createButton1";       this.createButton1.Size = new System.Drawing.Size(186, 27);       this.createButton1.TabIndex = 11;       this.createButton1.Text = "Create Simple Layers";       this.createButton1.Click += new System.EventHandler(this.createButton1_Click);       //       // createButton2       //       this.createButton2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));       this.createButton2.Location = new System.Drawing.Point(666, 323);       this.createButton2.Name = "createButton2";       this.createButton2.Size = new System.Drawing.Size(186, 27);       this.createButton2.TabIndex = 12;       this.createButton2.Text = "Create Nested Layers";       this.createButton2.Click += new System.EventHandler(this.createButton2_Click);       //       // createButton3       //       this.createButton3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));       this.createButton3.Location = new System.Drawing.Point(666, 354);       this.createButton3.Name = "createButton3";       this.createButton3.Size = new System.Drawing.Size(186, 27);       this.createButton3.TabIndex = 13;       this.createButton3.Text = "Create Membership Layers";       this.createButton3.Click += new System.EventHandler(this.createButton3_Click);       //       // textBox1       //       this.textBox1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));       this.textBox1.BorderStyle = System.Windows.Forms.BorderStyle.None;       this.textBox1.Enabled = false;       this.textBox1.Location = new System.Drawing.Point(666, 204);       this.textBox1.Multiline = true;       this.textBox1.Name = "textBox1";       this.textBox1.Size = new System.Drawing.Size(186, 82);       this.textBox1.TabIndex = 14;       this.textBox1.Text = "The buttons below allow you to create different types of layer structure. Details" +     " of the specific structures created can be found in the source code.";       //       // textBox3       //       this.textBox3.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));       this.textBox3.BorderStyle = System.Windows.Forms.BorderStyle.None;       this.textBox3.Enabled = false;       this.textBox3.Location = new System.Drawing.Point(666, 406);       this.textBox3.Multiline = true;       this.textBox3.Name = "textBox3";       this.textBox3.Size = new System.Drawing.Size(186, 92);       this.textBox3.TabIndex = 15;       this.textBox3.Text = "Use the buttons below to annotate items on the page with their layer details and " +     "also to delete and redact items on specific layers.";       //       // openExternallyButton       //       this.openExternallyButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));       this.openExternallyButton.Location = new System.Drawing.Point(666, 678);       this.openExternallyButton.Name = "openExternallyButton";       this.openExternallyButton.Size = new System.Drawing.Size(186, 27);       this.openExternallyButton.TabIndex = 16;       this.openExternallyButton.Text = "Open in Acrobat";       this.openExternallyButton.UseVisualStyleBackColor = true;       this.openExternallyButton.Click += new System.EventHandler(this.openExternallyButton_Click);       //       // purgeButton       //       this.purgeButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));       this.purgeButton.Location = new System.Drawing.Point(666, 621);       this.purgeButton.Name = "purgeButton";       this.purgeButton.Size = new System.Drawing.Size(186, 51);       this.purgeButton.TabIndex = 17;       this.purgeButton.Text = "Remove Unused Layers From Document";       this.purgeButton.Click += new System.EventHandler(this.purgeButton_Click);       //       // Form1       //       this.AutoScaleBaseSize = new System.Drawing.Size(6, 15);       this.ClientSize = new System.Drawing.Size(873, 856);       this.Controls.Add(this.purgeButton);       this.Controls.Add(this.openExternallyButton);       this.Controls.Add(this.textBox3);       this.Controls.Add(this.textBox1);       this.Controls.Add(this.createButton3);       this.Controls.Add(this.createButton2);       this.Controls.Add(this.createButton1);       this.Controls.Add(this.saveButton);       this.Controls.Add(this.openButton);       this.Controls.Add(this.pageCombo);       this.Controls.Add(this.layersCheckedListBox);       this.Controls.Add(this.previewPictureBox);       this.Controls.Add(this.textBox2);       this.Controls.Add(this.removeButton);       this.Controls.Add(this.annotateButton);       this.Name = "Form1";       this.Text = "Optional Content Demo";       this.Load += new System.EventHandler(this.Form1_Load);       ((System.ComponentModel.ISupportInitialize)(this.previewPictureBox)).EndInit();       this.ResumeLayout(false);       this.PerformLayout();     }     #endregion     /// <summary>     /// The main entry point for the application.     /// </summary>     [STAThread]     static void Main()     {       Application.Run(new Form1());     }     private Doc _doc;     List<Group> _groups;     private void Form1_Load(object sender, EventArgs e) {       string thePath = Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName;       string[] files = Directory.GetFiles(thePath, "*.pdf");       foreach (string file in files) {         if (!file.Contains("_out")) {           try {             LoadPDF(file);             break;           }           catch {           }         }       }     }     private void annotateButton_Click(object sender, EventArgs e) {       if (_doc == null)         return;       Properties props = Properties.FromDoc(_doc, false);       if (props == null)         return;       foreach (Page page in _doc.ObjectSoup.Catalog.Pages.GetPageArrayAll()) {         _doc.Page = page.ID;         Reader oc = Reader.FromPage(props, page);         if (true) {           TextOperation op = new TextOperation(_doc);           op.PageContents.AddPages(_doc.PageNumber);           string text = op.GetText();           if (text.Length > 0) {             IList<TextFragment> fragments = op.Select(0, text.Length);             _doc.FontSize = 12;             _doc.Width = 0.1;             foreach (TextFragment fragment in fragments) {               _doc.Rect.String = fragment.Rect.String;               List<OptionalContent.Layer> states = oc.GetLayersFromStreamAndPosition(fragment.StreamID, fragment.StreamOffset);               if (states.Count > 0)                 _doc.AddText(MakeDescription(states));               _doc.FrameRect();             }           }         }         if (true) {           // The ImageOperation only picks up images and not Form XObjects.           // Until we have an update which allows us to see Form XObject location           // too, we cannot annotate Form XObjects which are marked as optional.           ImageOperation op = new ImageOperation(_doc);           op.PageContents.AddPages(_doc.PageNumber);           foreach (ImageProperties image in op.GetImageProperties()) {             List<OptionalContent.Layer> states = oc.GetLayersFromObject(image.PixMap);             if (states.Count > 0) {               string txt = MakeDescription(states);               foreach (ImageRendition rendition in image.Renditions) {                 rendition.Focus();                 _doc.AddText(txt);                 _doc.FrameRect();               }             }           }         }         if (true) {           foreach (Annotation annot in page.GetAnnotations()) {             List<OptionalContent.Layer> states = oc.GetLayersFromObject(annot);             if (states.Count > 0) {               annot.Focus();               _doc.AddText(MakeDescription(states));               _doc.FrameRect();             }           }         }       }       UpdatePreview();     }     private static string MakeDescription(List<OptionalContent.Layer> states) {       string[] names = new string[states.Count];       for (int i = 0; i < names.Length; i++)         names[i] = states[i].Group != null ? states[i].Group.EntryName.Text : "Membership Dictionary";       string txt = string.Join(" ", names);       return txt;     }     private void removeButton_Click(object sender, EventArgs e) {       if (_doc == null)         return;       try {         Cursor.Current = Cursors.WaitCursor;         Properties props = Properties.FromDoc(_doc, false);         if (props == null)           return;         Page page = (Page)_doc.ObjectSoup[_doc.Page];         Reader reader = Reader.FromPage(props, page);         List<OptionalContent.Layer> layers = reader.GetLayers();         foreach (OptionalContent.Layer layer in layers) {           if (layer.Visible == false) {             if (reader == null)               reader = Reader.FromPage(props, page);             Reader.Redact(ref reader, layer);           }         }         UpdateLayers();         UpdatePreview();       }       finally {         Cursor.Current = Cursors.Default;       }     }     private void purgeButton_Click(object sender, EventArgs e) {       if (_doc == null)         return;       try {         Cursor.Current = Cursors.WaitCursor;         Properties props = Properties.FromDoc(_doc, false);         if (props == null)           return;         HashSet<Group> unused = props.RemoveUnusedGroups();         if (unused.Count > 0) {           UpdateLayers();           UpdatePreview();         }       }       finally {         Cursor.Current = Cursors.Default;       }     }     private List<TemporaryFile> _tempFiles;     private void openExternallyButton_Click(object sender, EventArgs e) {       if (_tempFiles == null)         _tempFiles = new List<TemporaryFile>();       TemporaryFile temp = new TemporaryFile(".pdf");       // when we save we try to keep the object ids constant       _doc.SaveOptions.Linearize = false;       _doc.SaveOptions.Remap = false;       _doc.Save(temp.Path);       _tempFiles.Add(temp);       System.Diagnostics.Process.Start(temp.Path);     }     private void createButton1_Click(object sender, EventArgs e) {       Doc doc = new Doc();       Properties props = Properties.FromDoc(doc, true);       List<Group> groups = new List<Group>();       for (int i = 1; i < 4; i++)         groups.Add(props.AddGroup("Layer " + i.ToString(), null));       doc.FontSize = 36;       doc.Rect.Inset(20, 20);       for (int i = 0; i < 1; i++) {         doc.Page = doc.AddPage();         Page page = (Page)doc.ObjectSoup[doc.Page];         Writer writer = new Writer(props, page);         foreach (Group group in groups) {           OptionalContent.Layer layer = writer.AddGroup(group);           writer.StartLayer(layer);           doc.AddText(group.EntryName.Text + "\r\n");           writer.EndLayer();           doc.AddText("Always Visible\r\n");           writer.StartLayer(layer);           doc.AddText(group.EntryName.Text + "\r\n\r\n");           writer.EndLayer();         }         doc.Flatten();       }       LoadPDF(doc);     }     private void createButton2_Click(object sender, EventArgs e) {       Doc doc = new Doc();       Properties props = Properties.FromDoc(doc, true);       Group parent = null;       List<Group> groups = new List<Group>();       // The Optional Content Group parent determines the nesting in the UI.       // The presentation of the nesting is separate from the actual nesting       // of visibility. In general you will want to ensure the two correspond       // as in the code here.       for (int i = 1; i <= 10; i++) {         Group group = props.AddGroup("Layer " + i.ToString(), parent);         groups.Add(group);         parent = i == 5 ? null : group;       }       doc.Page = doc.AddPage();       doc.FontSize = 36;       doc.Rect.Inset(20, 20);       Page page = (Page)doc.ObjectSoup[doc.Page];       Writer writer = new Writer(props, page);       // This determines the nesting of actual visibility. Here we ensure that this       // corresponds to the hierarchy specified in the UI so that it works in an       // obvious way.       for (int i = 0; i < groups.Count; i++) {         Group group = groups[i];         OptionalContent.Layer layer = writer.AddGroup(group);         if (i == 5)           while (writer.Depth > 0)             writer.EndLayer();         writer.StartLayer(layer);         doc.AddText(group.EntryName.Text + "\r\n");       }       while (writer.Depth > 0)         writer.EndLayer();       doc.Flatten();       LoadPDF(doc);     }     private void createButton3_Click(object sender, EventArgs e) {       Doc doc = new Doc();       Properties props = Properties.FromDoc(doc, true);       List<Group> groups = new List<Group>();       for (int i = 1; i < 4; i++)         groups.Add(props.AddGroup("Layer " + i.ToString(), null));       // membership policies are simple to use but limited in scope       MembershipGroup alloff = props.AddMembershipGroup();       alloff.Policy = MembershipGroup.PolicyEnum.AllOff;       alloff.PolicyGroups = groups;       // membership visibility expressions are more complex but more powerful       MembershipGroup mgve = props.AddMembershipGroup();       ArrayAtom ve = mgve.MakeVisibilityExpression(MembershipGroup.LogicEnum.Or, groups);       mgve.EntryVE = mgve.MakeVisibilityExpression(MembershipGroup.LogicEnum.Not, new ArrayAtom[] { ve });       doc.FontSize = 36;       doc.Rect.Inset(20, 20);       for (int i = 0; i < 3; i++) {         doc.Page = doc.AddPage();         Page page = (Page)doc.ObjectSoup[doc.Page];         Writer writer = new Writer(props, page);         OptionalContent.Layer layer1 = writer.AddGroup(alloff);         doc.AddText("The next line uses a Policy so that it is only visible if all layers are turned off...\r\n");         writer.StartLayer(layer1);         doc.AddText("I am normally invisible\r\n\r\n");         writer.EndLayer();         OptionalContent.Layer layer2 = writer.AddGroup(mgve);         doc.AddText("The next line uses a Visibility Expression so that it is only visible if all layers are turned off...\r\n");         writer.StartLayer(layer2);         doc.AddText("I am normally invisible\r\n");         writer.EndLayer();         doc.Flatten();       }       LoadPDF(doc);     }     private void pageCombo_SelectedIndexChanged(object sender, EventArgs e) {       _doc.PageNumber = pageCombo.SelectedIndex + 1;       UpdateLayers();       UpdatePreview();     }     private void LoadPDF(string file) {       Doc doc = new Doc();       doc.Read(file);       LoadPDF(doc);       textBox2.Text = file;     }     private class ComboBoxItem {       public string Name;       public int Value;       public ComboBoxItem(string name, int value) {         Name = name; Value = value;       }       public override string ToString() {         return Name;       }     }     private void LoadPDF(Doc doc) {       _doc = doc;       _groups = null;       int n = _doc.PageCount;       pageCombo.Items.Clear();       for (int i = 1; i <= n; i++)         pageCombo.Items.Add(new ComboBoxItem("Page " + i.ToString() + " of " + n.ToString(), i));       pageCombo.SelectedIndex = 0;       UpdateLayers();       UpdatePreview();     }     private void UpdateLayers() {       _groups = null;       layersCheckedListBox.Items.Clear();       if (_doc == null)         return;       Properties props = Properties.FromDoc(_doc, false);       if (props == null)         return;       Configuration config = props.GetDefault();       if (config == null)         return;       Page page = (Page)_doc.ObjectSoup[_doc.Page];       List<Group> groups = props.GetGroups(page);       List<int> indents = new List<int>();       props.SortGroupsForPresentation(groups, indents);       Doc doc = _doc;       try {         _doc = null;         int n = groups.Count;         for (int i = 0; i < n; i++) {           Group group = groups[i];           string indent = new string(' ', indents[i] * 3);           layersCheckedListBox.Items.Add(indent + group.EntryName.Text, group.Visible);         }       }       finally {         _doc = doc;         _groups = groups;       }     }     private void UpdatePreview() {       if (_doc == null) {         previewPictureBox.Image = null;         return;       }       _doc.Rect.String = _doc.MediaBox.String;       double scale = previewPictureBox.Width / _doc.Rect.Width;       _doc.Rendering.DotsPerInch = Math.Max(scale, 1.0) * 72.0;       previewPictureBox.Image = _doc.Rendering.GetBitmap();       //if (_doc.Rendering.Log.Length > 0)       //  MessageBox.Show("Render warning: " + _doc.Rendering.Log);     }     private void layersCheckedListBox_ItemCheck(object sender, ItemCheckEventArgs e) {       if ((_doc == null) || (_groups == null) || (e.NewValue == CheckState.Indeterminate))         return;       _groups[e.Index].Visible = e.NewValue == CheckState.Checked;       UpdatePreview();     }     private void openButton_Click(object sender, EventArgs e) {       OpenFileDialog dialog = new OpenFileDialog();       dialog.Filter = "PDF Files (.pdf)|*.pdf|AI Files (*.ai)|*.ai";       dialog.FilterIndex = 1;       if (dialog.ShowDialog() == DialogResult.OK)         LoadPDF(dialog.FileName);     }     private void saveButton_Click(object sender, EventArgs e) {       if (_doc == null)         _doc = new Doc();       SaveFileDialog dialog = new SaveFileDialog();       dialog.Filter = "PDF files (*.pdf)|*.pdf|All files (*.*)|*.*";       dialog.FilterIndex = 1;       dialog.FileName = "Untitled.pdf";       if (dialog.ShowDialog() == DialogResult.OK)         _doc.Save(dialog.FileName);     }   }   internal sealed class TemporaryFile : IDisposable {     private string mPath;     private TemporaryFile() { }     public TemporaryFile(string ext) {       mPath = GetTempFilePath(ext);     }     ~TemporaryFile() {       Dispose(false);     }     public void Dispose() {       Dispose(true);       GC.SuppressFinalize(this);     }     // sealed class cannot introduce virtual method     // warned if sealed class introduces protected member     private /*virtual*/ void Dispose(bool disposing) {       try {         DeleteFile();       }       catch {       }     }     public string Path { get { return mPath; } }     public void DeleteFile() {       if (mPath != null) {         if (File.Exists(mPath))           File.Delete(mPath);         mPath = null;       }     }     private static string GetTempFilePath(string ext) {       if (string.IsNullOrWhiteSpace(ext))         ext = ".dat";       else if (!ext.StartsWith("."))         ext = "." + ext;       return System.IO.Path.Combine(System.IO.Path.GetTempPath(), Guid.NewGuid().ToString() + ext);     }   } }