diff --git a/Signature/Add_ESign/App.config b/Signature/Add_ESign/App.config new file mode 100644 index 0000000..4b657bf --- /dev/null +++ b/Signature/Add_ESign/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/Signature/Add_ESign/App.xaml b/Signature/Add_ESign/App.xaml new file mode 100644 index 0000000..21c06d5 --- /dev/null +++ b/Signature/Add_ESign/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/Signature/Add_ESign/App.xaml.cs b/Signature/Add_ESign/App.xaml.cs new file mode 100644 index 0000000..aa09e11 --- /dev/null +++ b/Signature/Add_ESign/App.xaml.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Threading.Tasks; +using System.Windows; + +namespace PDFViewer_WPF +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + } +} diff --git a/Signature/Add_ESign/Data/Ink signature.pdf b/Signature/Add_ESign/Data/Ink signature.pdf new file mode 100644 index 0000000..4d4b5cd Binary files /dev/null and b/Signature/Add_ESign/Data/Ink signature.pdf differ diff --git a/Signature/Add_ESign/Data/John.png b/Signature/Add_ESign/Data/John.png new file mode 100644 index 0000000..d1dec91 Binary files /dev/null and b/Signature/Add_ESign/Data/John.png differ diff --git a/Signature/Add_ESign/Data/PDF.pfx b/Signature/Add_ESign/Data/PDF.pfx new file mode 100644 index 0000000..940afae Binary files /dev/null and b/Signature/Add_ESign/Data/PDF.pfx differ diff --git a/Signature/Add_ESign/MainWindow.xaml b/Signature/Add_ESign/MainWindow.xaml new file mode 100644 index 0000000..61be2c7 --- /dev/null +++ b/Signature/Add_ESign/MainWindow.xaml @@ -0,0 +1,13 @@ + + + + + + diff --git a/Signature/Add_ESign/MainWindow.xaml.cs b/Signature/Add_ESign/MainWindow.xaml.cs new file mode 100644 index 0000000..cbe38bf --- /dev/null +++ b/Signature/Add_ESign/MainWindow.xaml.cs @@ -0,0 +1,199 @@ +using Syncfusion.Pdf; +using Syncfusion.Pdf.Graphics; +using Syncfusion.Pdf.Security; +using Syncfusion.Windows.PdfViewer; +using System; +using System.Drawing; +using System.IO; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Media; +using Path = System.Windows.Shapes.Path; +using Bitmap = System.Drawing.Bitmap; + +namespace WPF_Sample_FW +{ + /// + /// Interaction logic for MainWindow.xaml + /// + public partial class MainWindow : Window + { + string filePath = "../../../Data/"; + bool addSignature = false; + public MainWindow() + { + InitializeComponent(); + PDFViewer.Load(filePath + "Ink signature.pdf"); + PDFViewer.Loaded += PDFViewer_Loaded; + PDFViewer.ZoomMode = ZoomMode.FitPage; + } + + private void PDFViewer_Loaded(object sender, RoutedEventArgs e) + { + // Find the default toolbar from the PDFViewer control template. + DocumentToolbar toolbar = PDFViewer.Template.FindName("PART_Toolbar", PDFViewer) as DocumentToolbar; + + // Find the stack panel inside the toolbar where buttons are arranged. + StackPanel stackPanel = (StackPanel)toolbar.Template.FindName("PART_ToolbarStack", toolbar); + + // Get the last stack panel in the toolbar stack (usually contains default buttons). + StackPanel stack = stackPanel.Children[stackPanel.Children.Count - 1] as StackPanel; + + // Get the first button from the stack to copy its style and icon. + Button button = stack.Children[0] as Button; + Path oldStylePath = button.Content as Path; + + Button eSignButton = GetButton(oldStylePath, button); + + // Add the new eSign button to the toolbar stack. + stackPanel.Children.Add(eSignButton); + } + + private void eSignButton_Click(object sender, RoutedEventArgs e) + { + addSignature = true; + } + + private Button GetButton(System.Windows.Shapes.Path oldPath, Button button) + { + // Create a new custom button for eSign functionality. + Button eSignButton = new Button(); + + // Create a new Path object to use as the icon for the eSign button. + Path path = new Path(); + path.Data = System.Windows.Media.Geometry.Parse("M218.17 424.14c-2.95-5.92-8.09-6.52-10.17-6.52s-7.22.59-10.02 6.19l-7.67 15.34c-6.37 12.78-25.03 11.37-29.48-2.09L144 386.59l-10.61 31.88c-5.89 17.66-22.38 29.53-41 29.53H80c-8.84 0-16-7.16-16-16s7.16-16 16-16h12.39c4.83 0 9.11-3.08 10.64-7.66l18.19-54.64c3.3-9.81 12.44-16.41 22.78-16.41s19.48 6.59 22.77 16.41l13.88 41.64c19.75-16.19 54.06-9.7 66 14.16 1.89 3.78 5.49 5.95 9.36 6.26v-82.12l128-127.09V160H248c-13.2 0-24-10.8-24-24V0H24C10.7 0 0 10.7 0 24v464c0 13.3 10.7 24 24 24h336c13.3 0 24-10.7 24-24v-40l-128-.11c-16.12-.31-30.58-9.28-37.83-23.75zM384 121.9c0-6.3-2.5-12.4-7-16.9L279.1 7c-4.5-4.5-10.6-7-17-7H256v128h128v-6.1zm-96 225.06V416h68.99l161.68-162.78-67.88-67.88L288 346.96zm280.54-179.63l-31.87-31.87c-9.94-9.94-26.07-9.94-36.01 0l-27.25 27.25 67.88 67.88 27.25-27.25c9.95-9.94 9.95-26.07 0-36.01z"); + + // Copy the fill color from the existing button's icon. + path.Fill = oldPath.Fill; + + // Set the icon as the content of the new button. + eSignButton.Content = path; + + // Match the icon's size and layout to the original button. + path.Stretch = Stretch.Uniform; + path.Height = oldPath.Height; + path.Width = oldPath.Width; + + // Match the button's background and layout properties to the original button. + eSignButton.Height = button.Height; + eSignButton.Width = button.Width; + eSignButton.Margin = button.Margin; + eSignButton.Style = button.Style; + // Attach the click event handler for eSign functionality. + eSignButton.Click += eSignButton_Click; + + return eSignButton; + } + + private void PDFViewer_PageClicked(object sender, PageClickedEventArgs args) + { + if (addSignature) + { + int pageIndex = PDFViewer.CurrentPageIndex - 1; + CreateSignatureImage(); + + //Gets the first page of the document + PdfLoadedPage page = PDFViewer.LoadedDocument.Pages[pageIndex] as PdfLoadedPage; + + //Retrieve the clicked client area position + System.Windows.Point clientPoint = args.Position; + + // Convert client point to page point, which accounts for zoom mode. + System.Windows.Point pagePoint = PDFViewer.ConvertClientPointToPagePoint(clientPoint, pageIndex + 1); + double x = pagePoint.X; + double y = pagePoint.Y; + + //Creates a certificate instance from PFX file with private key. + PdfCertificate pdfCert = new PdfCertificate( filePath + "PDF.pfx", "password123"); + + //Creates a digital signature + PdfSignature Signature = new PdfSignature(PDFViewer.LoadedDocument, page, pdfCert, "Signature"); + + //Sets an image for signature field + PdfBitmap signatureImage = new PdfBitmap( filePath + "ESign.png"); + + // Center the signature on the click position using dimensions in points. + float signWidth = signatureImage.PhysicalDimension.Width; + float signHeight = signatureImage.PhysicalDimension.Height; + Signature.Bounds = new System.Drawing.RectangleF((float)(x), (float)(y), signWidth, signHeight); + + Signature.ContactInfo = "johndoe@owned.us"; + Signature.LocationInfo = "Honolulu, Hawaii"; + Signature.Reason = "I am author of this document."; + + //Draws the signature image + Signature.Appearance.Normal.Graphics.DrawImage(signatureImage, 0, 0); + + //Save the document into stream. + MemoryStream stream = new MemoryStream(); + PDFViewer.LoadedDocument.Save(stream); + stream.Position = 0; + + //Reloads the document + PDFViewer.Load(stream); + addSignature = false; + } + + } + + private void CreateSignatureImage() + { + int pageIndex = PDFViewer.CurrentPageIndex - 1; + if(pageIndex < 0) + return; + + //Creating image for current date and time details + CreateCurrentDataImage(); + + //Combine the name image and date-time image into a single image + CombineSignatureAndDataImage(); + + } + + private void CombineSignatureAndDataImage() + { + // Load the two images + using (System.Drawing.Image nameImage = System.Drawing.Image.FromFile(filePath + "John.png")) + using (System.Drawing.Image signImage = System.Drawing.Image.FromFile(filePath + "DigitalSignatureBlock.png")) + { + // Create a new bitmap with combined width and max height + int signatureWidth = nameImage.Width + signImage.Width; + int signatureHeight = Math.Max(nameImage.Height, signImage.Height); + using (Bitmap combinedImage = new Bitmap(signatureWidth, signatureHeight)) + using (Graphics g = System.Drawing.Graphics.FromImage(combinedImage)) + { + // Draw both images side by side + g.DrawImage(nameImage, 0, 0); + g.DrawImage(signImage, nameImage.Width, 0); + // Save the result + combinedImage.Save(filePath + "ESign.png", System.Drawing.Imaging.ImageFormat.Png); + } + } + } + + private void CreateCurrentDataImage() + { + int width = 200; + int height = 100; + string signerName = "John"; + string dateTime = DateTime.Now.ToString("yyyy.MM.dd\nHH:mm:ss zzz"); + string text = $"Digitally signed by {signerName}\nDate: {dateTime}\n\n"; + string outputPath = filePath + "DigitalSignatureBlock.png"; + Directory.CreateDirectory(System.IO.Path.GetDirectoryName(outputPath)); + using (Bitmap bitmap = new Bitmap(width, height)) + { + using (Graphics graphics = System.Drawing.Graphics.FromImage(bitmap)) + { + using (Font font = new Font("Arial", 9)) + using (SolidBrush backgroundBrush = new SolidBrush(System.Drawing.Color.White)) + { + graphics.FillRectangle(backgroundBrush, 0, 0, width, height); + RectangleF layoutRect = new RectangleF(10, 10, width - 20, height - 20); + graphics.DrawString(text, font, System.Drawing.Brushes.Black, layoutRect); + bitmap.Save(outputPath, System.Drawing.Imaging.ImageFormat.Png); + } + } + } + } + } +} diff --git a/Signature/Add_ESign/PDFViewer_WPF.csproj b/Signature/Add_ESign/PDFViewer_WPF.csproj new file mode 100644 index 0000000..2a6a268 --- /dev/null +++ b/Signature/Add_ESign/PDFViewer_WPF.csproj @@ -0,0 +1,12 @@ + + + + WinExe + + + + + + + + diff --git a/Signature/Add_ESign/PDFViewer_WPF.sln b/Signature/Add_ESign/PDFViewer_WPF.sln new file mode 100644 index 0000000..5f6dbcb --- /dev/null +++ b/Signature/Add_ESign/PDFViewer_WPF.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.36401.2 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PDFViewer_WPF", "PDFViewer_WPF.csproj", "{0FAA7523-B034-4EA9-860A-A8936DFFD40E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0FAA7523-B034-4EA9-860A-A8936DFFD40E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0FAA7523-B034-4EA9-860A-A8936DFFD40E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0FAA7523-B034-4EA9-860A-A8936DFFD40E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0FAA7523-B034-4EA9-860A-A8936DFFD40E}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {BAAD6341-6945-42C7-8438-919E9DB8EB03} + EndGlobalSection +EndGlobal diff --git a/Signature/Add_ESign/Properties/AssemblyInfo.cs b/Signature/Add_ESign/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..6a2c04c --- /dev/null +++ b/Signature/Add_ESign/Properties/AssemblyInfo.cs @@ -0,0 +1,52 @@ +using System.Reflection; +using System.Resources; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Windows; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +//[assembly: AssemblyTitle("PDFViewer_WPF")] +//[assembly: AssemblyDescription("")] +//[assembly: AssemblyConfiguration("")] +//[assembly: AssemblyCompany("")] +//[assembly: AssemblyProduct("PDFViewer_WPF")] +//[assembly: AssemblyCopyright("Copyright © 2025")] +//[assembly: AssemblyTrademark("")] +//[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +//In order to begin building localizable applications, set +//CultureYouAreCodingWith in your .csproj file +//inside a . For example, if you are using US english +//in your source files, set the to en-US. Then uncomment +//the NeutralResourceLanguage attribute below. Update the "en-US" in +//the line below to match the UICulture setting in the project file. + +//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)] + + +//[assembly: ThemeInfo( +// ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located +// //(used if a resource is not found in the page, +// // or application resource dictionaries) +// ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located +// //(used if a resource is not found in the page, +// // app, or any theme specific resource dictionaries) +//)] + + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +//[assembly: AssemblyVersion("1.0.0.0")] +//[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Signature/Add_ESign/Properties/Resources.Designer.cs b/Signature/Add_ESign/Properties/Resources.Designer.cs new file mode 100644 index 0000000..75bb46f --- /dev/null +++ b/Signature/Add_ESign/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace PDFViewer_WPF.Properties +{ + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PDFViewer_WPF.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/Signature/Add_ESign/Properties/Resources.resx b/Signature/Add_ESign/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/Signature/Add_ESign/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Signature/Add_ESign/Properties/Settings.Designer.cs b/Signature/Add_ESign/Properties/Settings.Designer.cs new file mode 100644 index 0000000..67bc83e --- /dev/null +++ b/Signature/Add_ESign/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace PDFViewer_WPF.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/Signature/Add_ESign/Properties/Settings.settings b/Signature/Add_ESign/Properties/Settings.settings new file mode 100644 index 0000000..033d7a5 --- /dev/null +++ b/Signature/Add_ESign/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/Signature/Add_ESign/packages.config b/Signature/Add_ESign/packages.config new file mode 100644 index 0000000..5b33600 --- /dev/null +++ b/Signature/Add_ESign/packages.config @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/Signature/Add_ESign/targets/MultiTargeting.targets b/Signature/Add_ESign/targets/MultiTargeting.targets new file mode 100644 index 0000000..4a85629 --- /dev/null +++ b/Signature/Add_ESign/targets/MultiTargeting.targets @@ -0,0 +1,10 @@ + + + net462;net8.0-windows;net9.0-windows + true + False + True + True + True + + \ No newline at end of file