Browse Source

compdfkit(win) - 水印界面

liuaoran 1 year ago
parent
commit
1a2e5bec67
22 changed files with 921 additions and 120 deletions
  1. 6 2
      Demo/Examples/Compdfkit_Tools/Asset/Styles/ComboBoxStyle.xaml
  2. 54 1
      Demo/Examples/Compdfkit_Tools/Asset/Styles/RadioButtonStyle.xaml
  3. 44 0
      Demo/Examples/Compdfkit_Tools/Common/BaseControl/MatrixRadioControl.xaml
  4. 38 0
      Demo/Examples/Compdfkit_Tools/Common/BaseControl/MatrixRadioControl.xaml.cs
  5. 34 0
      Demo/Examples/Compdfkit_Tools/Common/Convert/TagToBoolConverter.cs
  6. 84 79
      Demo/Examples/Compdfkit_Tools/Common/Helper/CommonHelper.cs
  7. 30 0
      Demo/Examples/Compdfkit_Tools/Common/PropertyControl/PDFLocation/CPDFLocationControl.xaml
  8. 28 0
      Demo/Examples/Compdfkit_Tools/Common/PropertyControl/PDFLocation/CPDFLocationControl.xaml.cs
  9. 51 0
      Demo/Examples/Compdfkit_Tools/Common/PropertyControl/PDFLocation/CPDFRotationControl.xaml
  10. 28 0
      Demo/Examples/Compdfkit_Tools/Common/PropertyControl/PDFLocation/CPDFRotationControl.xaml.cs
  11. 36 0
      Demo/Examples/Compdfkit_Tools/Common/PropertyControl/PDFLocation/CPDFTileControl.xaml
  12. 28 0
      Demo/Examples/Compdfkit_Tools/Common/PropertyControl/PDFLocation/CPDFTileControl.xaml.cs
  13. 1 1
      Demo/Examples/Compdfkit_Tools/Common/PropertyControl/PDFOpacity/CPDFOpactiyUI.xaml
  14. 36 0
      Demo/Examples/Compdfkit_Tools/Compdfkit_Tools.csproj
  15. 35 3
      Demo/Examples/Compdfkit_Tools/Security/Watermark/FileGridListWithPageRangeControl.xaml.cs
  16. 8 5
      Demo/Examples/Compdfkit_Tools/Security/Watermark/PageRangeDialog.xaml
  17. 115 17
      Demo/Examples/Compdfkit_Tools/Security/Watermark/PageRangeDialog.xaml.cs
  18. 27 11
      Demo/Examples/Compdfkit_Tools/Security/Watermark/PreviewControl.xaml.cs
  19. 147 0
      Demo/Examples/Compdfkit_Tools/Security/Watermark/WatermarkDialog.xaml
  20. 74 0
      Demo/Examples/Compdfkit_Tools/Security/Watermark/WatermarkDialog.xaml.cs
  21. 1 1
      Demo/Examples/Compdfkit_Tools/Security/Watermark/WatermarkListDialog.xaml
  22. 16 0
      Demo/Examples/Compdfkit_Tools/Security/Watermark/WatermarkListDialog.xaml.cs

+ 6 - 2
Demo/Examples/Compdfkit_Tools/Asset/Styles/ComboBoxStyle.xaml

@@ -273,7 +273,7 @@
                         <Setter.Value>
                             <ControlTemplate TargetType="ComboBoxItem">
                                 <Border Name="Back" Background="Transparent">
-                                    <ContentPresenter VerticalAlignment="Center" HorizontalAlignment="Left" Margin="5,0,0,0"></ContentPresenter>
+                                    <ContentPresenter x:Name="contentPresenter" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="5,0,0,0"></ContentPresenter>
                                 </Border>
                                 <ControlTemplate.Triggers>
                                     <Trigger Property="IsMouseOver" Value="True">
@@ -281,7 +281,7 @@
                                     </Trigger>
                                     <Trigger Property="IsHighlighted" Value="True">
                                         <Setter TargetName="Back" Property="Background" Value="LightGray"></Setter>
-                                    </Trigger>
+                                    </Trigger> 
                                 </ControlTemplate.Triggers>
                             </ControlTemplate>
                         </Setter.Value>
@@ -410,6 +410,10 @@
                                 </Setter.Value>
                             </Setter>
                         </Trigger>
+
+                        <Trigger Property="IsEnabled" Value="False">
+                            <Setter Property="Opacity" Value="0.5" /> 
+                        </Trigger>
                     </ControlTemplate.Triggers>
                 </ControlTemplate>
             </Setter.Value>

+ 54 - 1
Demo/Examples/Compdfkit_Tools/Asset/Styles/RadioButtonStyle.xaml

@@ -84,7 +84,17 @@
                              Opacity="0"/>
                         </Grid>
                         <Grid x:Name="textGd"  Grid.Column="1" VerticalAlignment="Center">
-                            <ContentPresenter HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
+                            <ContentPresenter HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
+                                <ContentPresenter.Style>
+                                    <Style TargetType="ContentPresenter">
+                                        <Style.Triggers>
+                                            <DataTrigger Binding="{Binding IsEnabled, RelativeSource={RelativeSource TemplatedParent}}" Value="False">
+                                                <Setter Property="Opacity" Value="0.5"/>
+                                            </DataTrigger>
+                                        </Style.Triggers>
+                                    </Style>
+                                </ContentPresenter.Style>
+                            </ContentPresenter>
                         </Grid>
                     </Grid>
                     <ControlTemplate.Triggers>
@@ -94,6 +104,49 @@
                         <Trigger Property="IsMouseOver" Value="True">
                             <Setter TargetName="radioEllipse" Property="Stroke" Value="DodgerBlue"></Setter>
                         </Trigger>
+                        <Trigger Property="IsEnabled" Value="False">
+                            <Setter TargetName="radioEllipse" Property="Fill" Value="#1A000000"></Setter>
+                            <Setter TargetName="radioEllipse" Property="Stroke" Value="#5A000000"></Setter>
+                            <Setter TargetName="innerEllipse" Property="Fill" Value="#1A000000"></Setter>
+                        </Trigger>
+                    </ControlTemplate.Triggers>
+                </ControlTemplate>
+            </Setter.Value>
+        </Setter>
+    </Style>
+
+    <Style x:Key="MatrixRadioButton" TargetType="{x:Type RadioButton}">
+        <Setter Property="Template">
+            <Setter.Value>
+                <ControlTemplate TargetType="{x:Type RadioButton}">
+                    <Grid>
+                        <Grid>
+                            <Rectangle x:Name="radioRectangle"
+                          Width="28"
+                          Height="28"
+                          Fill="#DDE9FF"/>
+                        </Grid>
+                        <Grid x:Name="textGd"  Grid.Column="1" VerticalAlignment="Center">
+                            <ContentPresenter HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
+                                <ContentPresenter.Style>
+                                    <Style TargetType="ContentPresenter">
+                                        <Style.Triggers>
+                                            <DataTrigger Binding="{Binding IsEnabled, RelativeSource={RelativeSource TemplatedParent}}" Value="False">
+                                                <Setter Property="Opacity" Value="0.5"/>
+                                            </DataTrigger>
+                                        </Style.Triggers>
+                                    </Style>
+                                </ContentPresenter.Style>
+                            </ContentPresenter>
+                        </Grid>
+                    </Grid>
+                    <ControlTemplate.Triggers>
+                        <Trigger Property="IsChecked" Value="True">
+                            <Setter TargetName="radioRectangle" Property="Fill" Value="#4982E6"></Setter>
+                        </Trigger>
+                        <Trigger Property="IsMouseOver" Value="True">
+                            <Setter TargetName="radioRectangle" Property="Fill" Value="#93B6F3"></Setter>
+                        </Trigger>
                     </ControlTemplate.Triggers>
                 </ControlTemplate>
             </Setter.Value>

+ 44 - 0
Demo/Examples/Compdfkit_Tools/Common/BaseControl/MatrixRadioControl.xaml

@@ -0,0 +1,44 @@
+<UserControl x:Class="Compdfkit_Tools.Common.MatrixRadioControl"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:local="clr-namespace:Compdfkit_Tools.Common"
+             mc:Ignorable="d" 
+             Height="92" Width="92">
+    <UserControl.Resources>
+        <ResourceDictionary>
+            <local:TagToBoolConverter x:Key="TagToBoolConverter"></local:TagToBoolConverter>
+            <ResourceDictionary.MergedDictionaries>
+                <ResourceDictionary Source="../../Asset/Styles/RadioButtonStyle.xaml"></ResourceDictionary>
+            </ResourceDictionary.MergedDictionaries>
+        </ResourceDictionary>
+    </UserControl.Resources>
+    <Grid>
+        <Grid.RowDefinitions>
+            <RowDefinition />
+            <RowDefinition />
+            <RowDefinition />
+        </Grid.RowDefinitions>
+        <Grid.ColumnDefinitions>
+            <ColumnDefinition />
+            <ColumnDefinition />
+            <ColumnDefinition />
+        </Grid.ColumnDefinitions>
+
+        <!-- Row 1 -->
+        <RadioButton Style="{StaticResource MatrixRadioButton}" Grid.Row="0" Grid.Column="0" Tag="0" IsChecked="{Binding SelectedTag, ConverterParameter=0, RelativeSource={RelativeSource AncestorType={x:Type local:MatrixRadioControl}}, Converter={StaticResource TagToBoolConverter}}"/>
+        <RadioButton Style="{StaticResource MatrixRadioButton}" Grid.Row="0" Grid.Column="1" Tag="1" IsChecked="{Binding SelectedTag, ConverterParameter=1, RelativeSource={RelativeSource AncestorType={x:Type local:MatrixRadioControl}}, Converter={StaticResource TagToBoolConverter}}"/>
+        <RadioButton Style="{StaticResource MatrixRadioButton}" Grid.Row="0" Grid.Column="2" Tag="2" IsChecked="{Binding SelectedTag, ConverterParameter=2, RelativeSource={RelativeSource AncestorType={x:Type local:MatrixRadioControl}}, Converter={StaticResource TagToBoolConverter}}"/>
+
+        <!-- Row 2 -->
+        <RadioButton Style="{StaticResource MatrixRadioButton}" Grid.Row="1" Grid.Column="0" Tag="3"  IsChecked="{Binding SelectedTag, ConverterParameter=3, RelativeSource={RelativeSource AncestorType={x:Type local:MatrixRadioControl}}, Converter={StaticResource TagToBoolConverter}}"/>
+        <RadioButton Style="{StaticResource MatrixRadioButton}" Grid.Row="1" Grid.Column="1" Tag="4"  IsChecked="{Binding SelectedTag, ConverterParameter=4, RelativeSource={RelativeSource AncestorType={x:Type local:MatrixRadioControl}}, Converter={StaticResource TagToBoolConverter}}"/>
+        <RadioButton Style="{StaticResource MatrixRadioButton}" Grid.Row="1" Grid.Column="2" Tag="5"  IsChecked="{Binding SelectedTag, ConverterParameter=5, RelativeSource={RelativeSource AncestorType={x:Type local:MatrixRadioControl}}, Converter={StaticResource TagToBoolConverter}}"/>
+
+        <!-- Row 3 -->
+        <RadioButton Style="{StaticResource MatrixRadioButton}" Grid.Row="2" Grid.Column="0" Tag="6"  IsChecked="{Binding SelectedTag, ConverterParameter=6, RelativeSource={RelativeSource AncestorType={x:Type local:MatrixRadioControl}}, Converter={StaticResource TagToBoolConverter}}"/>
+        <RadioButton Style="{StaticResource MatrixRadioButton}" Grid.Row="2" Grid.Column="1" Tag="7"  IsChecked="{Binding SelectedTag, ConverterParameter=7, RelativeSource={RelativeSource AncestorType={x:Type local:MatrixRadioControl}}, Converter={StaticResource TagToBoolConverter}}"/>
+        <RadioButton Style="{StaticResource MatrixRadioButton}" Grid.Row="2" Grid.Column="2" Tag="8"  IsChecked="{Binding SelectedTag, ConverterParameter=8, RelativeSource={RelativeSource AncestorType={x:Type local:MatrixRadioControl}}, Converter={StaticResource TagToBoolConverter}}"/>
+    </Grid>
+</UserControl>

+ 38 - 0
Demo/Examples/Compdfkit_Tools/Common/BaseControl/MatrixRadioControl.xaml.cs

@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Compdfkit_Tools.Common
+{
+    /// <summary>
+    /// Interaction logic for MetrixRadioControl.xaml
+    /// </summary>
+    public partial class MatrixRadioControl : UserControl
+    {
+        public int SelectedTag
+        {
+            get { return (int)GetValue(SelectedTagProperty); }
+            set { SetValue(SelectedTagProperty, value); }
+        }
+
+        public static readonly DependencyProperty SelectedTagProperty =
+            DependencyProperty.Register("SelectedTag", typeof(int), typeof(MatrixRadioControl), new PropertyMetadata(4));
+         
+        public MatrixRadioControl()
+        {
+            DataContext = this;
+            InitializeComponent();
+        }
+    }
+}

+ 34 - 0
Demo/Examples/Compdfkit_Tools/Common/Convert/TagToBoolConverter.cs

@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Data;
+
+namespace Compdfkit_Tools.Common
+{
+    public class TagToBoolConverter : IValueConverter
+    {
+        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            if (value is int v && parameter is string v1)
+            {
+                if (int.TryParse(v1, out int parameterValue))
+                {
+                    return v == parameterValue;
+                }
+            }
+            return false;
+        }
+
+        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            if (value is bool && parameter is int && (bool)value)
+            {
+                return (int)parameter;
+            }
+            return Binding.DoNothing;
+        }
+    }
+}

+ 84 - 79
Demo/Examples/Compdfkit_Tools/Common/Helper/CommonHelper.cs

@@ -94,7 +94,7 @@ namespace Compdfkit_Tools.Helper
             string second = date.Substring(12, 2);
             return new DateTime(int.Parse(year), int.Parse(month), int.Parse(day), int.Parse(hour), int.Parse(minute), int.Parse(second));
         }
-        
+
         /// <summary>
         /// Returns the file size based on the specified file path, with the smallest unit being bytes (B).
         /// </summary>
@@ -123,7 +123,7 @@ namespace Compdfkit_Tools.Helper
                 return "0B";
             }
         }
-         
+
         public static string GetExistedPathOrEmpty(string filter = "PDF files (*.pdf)|*.pdf")
         {
             string selectedFilePath = string.Empty;
@@ -147,7 +147,7 @@ namespace Compdfkit_Tools.Helper
             }
             return selectedFilePath;
         }
-          
+
         public static string GetGeneratePathOrEmpty(string filter, string defaultFileName = "")
         {
             string selectedFilePath = string.Empty;
@@ -208,75 +208,80 @@ namespace Compdfkit_Tools.Helper
             return pageParam;
         }
 
+        public static List<int> GetDefaultPageList(CPDFDocument document)
+        {
+            List<int> pageRangeList = new List<int>();
+            for (int i = 0; i < document.PageCount; i++)
+            {
+                pageRangeList.Add(i + 1);
+            }
+            return pageRangeList;
+        }
+
         public static bool GetPagesInRange(ref List<int> pageList, string pageRange, int count, char[] enumerationSeparator, char[] rangeSeparator, bool inittag = false)
         {
-            string[] rangeSplit = pageRange.Split(enumerationSeparator); 
+            if (pageRange == null || pageList == null)
+            {
+                return false;
+            }
 
             pageList.Clear();
+            int starttag = inittag ? 0 : 1;
+
+            string[] rangeSplit = pageRange.Split(enumerationSeparator);
 
             foreach (string range in rangeSplit)
             {
-                int starttag = 1;
-                if (inittag)
-                {
-                    starttag = 0;
-                }
-                if (range.Contains("-")) 
+                if (range.Contains("-"))
                 {
-                    try
+                    string[] limits = range.Split(rangeSeparator);
+                    if (limits.Length == 2 && int.TryParse(limits[0], out int start) && int.TryParse(limits[1], out int end))
                     {
-                        string[] limits = range.Split(rangeSeparator); 
-                        if (limits.Length >= 2 && !string.IsNullOrWhiteSpace(limits[0]) && !string.IsNullOrWhiteSpace(limits[1]))
+                        if (start < starttag || end > count || start > end)
                         {
-                            int start = int.Parse(limits[0]);
-                            int end = int.Parse(limits[1]);
+                            return false;
+                        }
 
-                            if ((start < starttag) || (end > count) || (start > end))
-                            { 
+                        for (int i = start; i <= end; i++)
+                        {
+                            if (pageList.Contains(i - 1))
+                            {
                                 return false;
                             }
 
-                            for (int i = start; i <= end; ++i)
-                            {
-                                if (pageList.Contains(i))
-                                { 
-                                    return false;
-                                }
-
-                                pageList.Add(i - 1);
-                            }
-                            continue;
+                            pageList.Add(i - 1);
                         }
                     }
-                    catch (Exception ex)
-                    { 
+                    else
+                    {
                         return false;
                     }
                 }
-                int pageNr;
-                try
-                { 
-                    pageNr = int.Parse(range); 
-                }
-                catch (Exception) 
+                else if (int.TryParse(range, out int pageNr))
                 {
-                    return false;
-                }
-                if (pageNr < starttag || pageNr > count)
-                {
-                    return false; 
+                    if (pageNr < starttag || pageNr > count)
+                    {
+                        return false;
+                    }
+
+                    if (pageList.Contains(pageNr - 1))
+                    {
+                        return false;
+                    }
+
+                    pageList.Add(pageNr - 1);
                 }
-                if (pageList.Contains(pageNr))
+                else
                 {
-                    return false; 
+                    return false;
                 }
-                pageList.Add(pageNr - 1);
             }
             return true;
         }
 
+
         internal static class PageEditHelper
-        { 
+        {
             public static T FindVisualParent<T>(DependencyObject obj) where T : class
             {
                 while (obj != null)
@@ -357,7 +362,7 @@ namespace Compdfkit_Tools.Helper
         }
 
         public class ArrowHelper
-        { 
+        {
             public bool HasStartArrow
             {
                 get
@@ -368,7 +373,7 @@ namespace Compdfkit_Tools.Helper
                     }
                     return false;
                 }
-            } 
+            }
 
             public bool IsStartClosed
             {
@@ -380,7 +385,7 @@ namespace Compdfkit_Tools.Helper
                     }
                     return false;
                 }
-            } 
+            }
 
             public bool HasEndArrow
             {
@@ -392,7 +397,7 @@ namespace Compdfkit_Tools.Helper
                     }
                     return false;
                 }
-            } 
+            }
 
             public bool IsEndClosed
             {
@@ -404,15 +409,15 @@ namespace Compdfkit_Tools.Helper
                     }
                     return false;
                 }
-            } 
-
-            public uint ArrowAngle { get; set; } 
-            public uint ArrowLength { get; set; } 
-            public Point? LineStart { get; set; } 
-            public Point? LineEnd { get; set; } 
-            public PathGeometry Body { get; set; } 
-            public C_LINE_TYPE StartSharp { get; set; } 
-            public C_LINE_TYPE EndSharp { get; set; } 
+            }
+
+            public uint ArrowAngle { get; set; }
+            public uint ArrowLength { get; set; }
+            public Point? LineStart { get; set; }
+            public Point? LineEnd { get; set; }
+            public PathGeometry Body { get; set; }
+            public C_LINE_TYPE StartSharp { get; set; }
+            public C_LINE_TYPE EndSharp { get; set; }
             public ArrowHelper()
             {
                 Body = new PathGeometry();
@@ -423,10 +428,10 @@ namespace Compdfkit_Tools.Helper
             {
                 if (LineStart != null && LineEnd != null)
                 {
-                    PathFigure lineFigure = new PathFigure(); 
+                    PathFigure lineFigure = new PathFigure();
                     lineFigure.StartPoint = (Point)LineStart;
                     LineSegment linePath = new LineSegment();
-                    linePath.Point = (Point)LineEnd; 
+                    linePath.Point = (Point)LineEnd;
                     lineFigure.Segments.Add(linePath);
                     return lineFigure;
                 }
@@ -487,7 +492,7 @@ namespace Compdfkit_Tools.Helper
                         break;
                 }
                 return null;
-            } 
+            }
 
             public PathGeometry BuildArrowBody()
             {
@@ -509,7 +514,7 @@ namespace Compdfkit_Tools.Helper
                 }
                 return Body;
             }
-             
+
             private PathFigure CreateStartOpenArrow()
             {
                 if (ArrowLength == 0 || !HasStartArrow || LineStart == null || LineEnd == null || ArrowAngle == 0)
@@ -531,7 +536,7 @@ namespace Compdfkit_Tools.Helper
                 arrowFigure.IsClosed = IsStartClosed;
                 arrowFigure.IsFilled = IsStartClosed;
                 return arrowFigure;
-            } 
+            }
 
             private PathFigure CreateEndOpenArrow()
             {
@@ -554,7 +559,7 @@ namespace Compdfkit_Tools.Helper
                 arrowFigure.IsClosed = IsEndClosed;
                 arrowFigure.IsFilled = IsEndClosed;
                 return arrowFigure;
-            } 
+            }
 
             private PathFigure CreateStartReverseArrow()
             {
@@ -577,7 +582,7 @@ namespace Compdfkit_Tools.Helper
                 arrowFigure.IsClosed = IsStartClosed;
                 arrowFigure.IsFilled = IsStartClosed;
                 return arrowFigure;
-            } 
+            }
 
             private PathFigure CreateEndReverseArrow()
             {
@@ -601,7 +606,7 @@ namespace Compdfkit_Tools.Helper
                 arrowFigure.IsFilled = IsEndClosed;
                 return arrowFigure;
             }
-             
+
             private PathFigure CreateStartButtArrow()
             {
                 if (ArrowLength == 0 || !HasStartArrow || LineStart == null || LineEnd == null)
@@ -620,7 +625,7 @@ namespace Compdfkit_Tools.Helper
                 buttSegment.Point = ((Point)LineStart + (lineVector * rotateMatrix));
                 arrowFigure.Segments.Add(buttSegment);
                 return arrowFigure;
-            } 
+            }
 
             private PathFigure CreateEndButtArrow()
             {
@@ -641,7 +646,7 @@ namespace Compdfkit_Tools.Helper
                 arrowFigure.Segments.Add(buttSegment);
 
                 return arrowFigure;
-            } 
+            }
 
             private PathFigure CreateStartDiamondArrow()
             {
@@ -680,7 +685,7 @@ namespace Compdfkit_Tools.Helper
                 arrowFigure.IsClosed = IsStartClosed;
                 arrowFigure.IsFilled = IsStartClosed;
                 return arrowFigure;
-            } 
+            }
 
             private PathFigure CreateEndDiamondArrow()
             {
@@ -720,7 +725,7 @@ namespace Compdfkit_Tools.Helper
                 arrowFigure.IsClosed = IsEndClosed;
                 arrowFigure.IsFilled = IsEndClosed;
                 return arrowFigure;
-            } 
+            }
 
             private PathFigure CreateStartRoundArrow()
             {
@@ -747,7 +752,7 @@ namespace Compdfkit_Tools.Helper
                 arrowFigure.Segments.Add(circleSegment);
 
                 return arrowFigure;
-            } 
+            }
 
             private PathFigure CreateEndRoundArrow()
             {
@@ -774,7 +779,7 @@ namespace Compdfkit_Tools.Helper
                 arrowFigure.Segments.Add(circleSegment);
 
                 return arrowFigure;
-            } 
+            }
 
             private PathFigure CreateStartSquareArrow()
             {
@@ -808,7 +813,7 @@ namespace Compdfkit_Tools.Helper
                 arrowFigure.Segments.Add(squreSegment);
 
                 return arrowFigure;
-            } 
+            }
 
             private PathFigure CreateEndSquareArrow()
             {
@@ -843,7 +848,7 @@ namespace Compdfkit_Tools.Helper
                 arrowFigure.Segments.Add(squreSegment);
 
                 return arrowFigure;
-            } 
+            }
 
             private PathFigure CreateStartSlashArrow()
             {
@@ -863,7 +868,7 @@ namespace Compdfkit_Tools.Helper
                 buttSegment.Point = ((Point)LineStart + (lineVector * rotateMatrix));
                 arrowFigure.Segments.Add(buttSegment);
                 return arrowFigure;
-            } 
+            }
 
             private PathFigure CreateEndSlashArrow()
             {
@@ -1002,7 +1007,7 @@ namespace Compdfkit_Tools.Helper
             }
         }
 
-        public static void ExtraImage_Click(Dictionary<int,List<Bitmap>> imageDict)
+        public static void ExtraImage_Click(Dictionary<int, List<Bitmap>> imageDict)
         {
             System.Windows.Forms.FolderBrowserDialog folderDialog = new System.Windows.Forms.FolderBrowserDialog();
             if (folderDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
@@ -1032,7 +1037,7 @@ namespace Compdfkit_Tools.Helper
                 }
             }
         }
-        
+
         public static double CheckZoomLevel(double[] zoomLevelList, double zoom, bool IsGrowth)
         {
             double standardZoom = 100;
@@ -1066,11 +1071,11 @@ namespace Compdfkit_Tools.Helper
     public class SignatureHelper
     {
         public static List<CPDFSignature> SignatureList;
-        
+
         public static void InitEffectiveSignatureList(CPDFDocument document)
         {
             SignatureList = document.GetSignatureList();
-            for(int index = SignatureList.Count - 1; index >= 0; index--)
+            for (int index = SignatureList.Count - 1; index >= 0; index--)
             {
                 if (SignatureList[index].SignerList.Count <= 0)
                 {
@@ -1085,7 +1090,7 @@ namespace Compdfkit_Tools.Helper
             {
                 sig.VerifySignatureWithDocument(document);
             }
-            
+
         }
     }
 }

+ 30 - 0
Demo/Examples/Compdfkit_Tools/Common/PropertyControl/PDFLocation/CPDFLocationControl.xaml

@@ -0,0 +1,30 @@
+<UserControl x:Class="Compdfkit_Tools.Common.CPDFLocationControl"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:local="clr-namespace:Compdfkit_Tools.Common"
+             mc:Ignorable="d" 
+             d:DesignHeight="92" d:DesignWidth="239">
+    <Grid>
+        <Grid.ColumnDefinitions>
+            <ColumnDefinition Width="auto"></ColumnDefinition>
+            <ColumnDefinition></ColumnDefinition>
+        </Grid.ColumnDefinitions>
+        <local:MatrixRadioControl></local:MatrixRadioControl>
+        <Grid Grid.Column="1">
+            <Grid.RowDefinitions>
+                <RowDefinition></RowDefinition>
+                <RowDefinition></RowDefinition>
+            </Grid.RowDefinitions>
+            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="4">
+                <TextBlock Text="X" VerticalAlignment="Center" Margin="0,0,8,0"></TextBlock>
+                <local:NumericUpDownControl Height="32" Width="82"></local:NumericUpDownControl>
+            </StackPanel>
+            <StackPanel Orientation="Horizontal" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="4">
+                <TextBlock Text="Y" VerticalAlignment="Center" Margin="0,0,8,0"></TextBlock>
+                <local:NumericUpDownControl Height="32" Width="82"></local:NumericUpDownControl>
+            </StackPanel>
+        </Grid>
+    </Grid>
+</UserControl>

+ 28 - 0
Demo/Examples/Compdfkit_Tools/Common/PropertyControl/PDFLocation/CPDFLocationControl.xaml.cs

@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Compdfkit_Tools.Common
+{
+    /// <summary>
+    /// Interaction logic for CPDFLocationControl.xaml
+    /// </summary>
+    public partial class CPDFLocationControl : UserControl
+    {
+        public CPDFLocationControl()
+        {
+            InitializeComponent();
+        }
+    }
+}

+ 51 - 0
Demo/Examples/Compdfkit_Tools/Common/PropertyControl/PDFLocation/CPDFRotationControl.xaml

@@ -0,0 +1,51 @@
+<UserControl x:Class="Compdfkit_Tools.Common.CPDFRotationControl"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:local="clr-namespace:Compdfkit_Tools.Common"
+             mc:Ignorable="d" 
+             d:DesignHeight="32" d:DesignWidth="186">
+    <UserControl.Resources>
+        <Style x:Key="TransparentButtonStyle" TargetType="{x:Type Button}">
+            <Setter Property="BorderThickness" Value="0" />
+            <Setter Property="Height" Value="32"></Setter>
+            <Setter Property="Width" Value="32"></Setter>
+            <Setter Property="Template">
+                <Setter.Value>
+                    <ControlTemplate TargetType="Button">
+                        <Border Name="border" Background="Transparent">
+                            <ContentPresenter />
+                        </Border>
+                        <ControlTemplate.Triggers>
+                            <Trigger Property="IsMouseOver" Value="True">
+                                <Setter TargetName="border" Property="Background" Value="#1a000000" />
+                            </Trigger>
+                            <Trigger Property="IsPressed" Value="True">
+                                <Setter TargetName="border" Property="Background" Value="#5a000000" />
+                            </Trigger>
+                        </ControlTemplate.Triggers>
+                    </ControlTemplate>
+                </Setter.Value>
+            </Setter>
+        </Style>
+    </UserControl.Resources>
+    <Grid HorizontalAlignment="Left">
+        <Grid.ColumnDefinitions>
+            <ColumnDefinition Width="auto"></ColumnDefinition>
+            <ColumnDefinition  Width="auto"></ColumnDefinition>
+        </Grid.ColumnDefinitions>
+        <local:NumericUpDownControl Width="82"></local:NumericUpDownControl>
+        <StackPanel Grid.Column="1" Orientation="Horizontal" Margin="8,0,0,0">
+            <Button  Style="{StaticResource TransparentButtonStyle}">
+                <Path HorizontalAlignment="Center" VerticalAlignment="Center" Data="M14.5,0H1.5V16H14.5V0ZM13.5,1V15H2.5V1H13.5ZM6.58579,3.75736L3.75736,6.58579L9.41421,12.2426L12.2426,9.41421L6.58579,3.75736Z" Fill="#001A4E" />
+            </Button>
+            <Button  Style="{StaticResource TransparentButtonStyle}">
+                <Path HorizontalAlignment="Center" VerticalAlignment="Center" Data="M14.5 0H1.5V16H14.5V0ZM13.5 1V15H2.5V1H13.5ZM10 4H6V12H10V4Z" Fill="#001A4E" />
+            </Button>
+            <Button  Style="{StaticResource TransparentButtonStyle}">
+                <Path HorizontalAlignment="Center" VerticalAlignment="Center" Data="M14.5 0H1.5V16H14.5V0ZM13.5 1V15H2.5V1H13.5ZM12.2426 6.58579L9.41421 3.75736L3.75736 9.41421L6.58579 12.2426L12.2426 6.58579Z" Fill="#001A4E" />
+            </Button>
+        </StackPanel>
+    </Grid>
+</UserControl>

+ 28 - 0
Demo/Examples/Compdfkit_Tools/Common/PropertyControl/PDFLocation/CPDFRotationControl.xaml.cs

@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Compdfkit_Tools.Common
+{
+    /// <summary>
+    /// Interaction logic for CPDFRotationControl.xaml
+    /// </summary>
+    public partial class CPDFRotationControl : UserControl
+    {
+        public CPDFRotationControl()
+        {
+            InitializeComponent();
+        }
+    }
+}

+ 36 - 0
Demo/Examples/Compdfkit_Tools/Common/PropertyControl/PDFLocation/CPDFTileControl.xaml

@@ -0,0 +1,36 @@
+<UserControl x:Class="Compdfkit_Tools.Common.CPDFTileControl"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:local="clr-namespace:Compdfkit_Tools.Common"
+             mc:Ignorable="d" 
+             d:DesignHeight="72" d:DesignWidth="242">
+    <Grid>
+        <Grid.RowDefinitions>
+            <RowDefinition></RowDefinition>
+            <RowDefinition></RowDefinition>
+        </Grid.RowDefinitions>
+        <CheckBox VerticalAlignment="Center">
+            <TextBlock  Text="Tile"></TextBlock>
+        </CheckBox>
+        <Grid Grid.Row="1">
+            <StackPanel Orientation="Horizontal">
+                <Canvas Width="16" Height="16" Margin="0,0,4,0">
+                    <Path Fill="Black" Data="M1,4H2V12H1V4ZM4.70703,7.5H11.2952L10.0278,6.23223L10.7349,5.52513L13.2097,8L10.7349,10.4749L10.0278,9.76777L11.2952,8.5H4.70703L5.97487,9.76777L5.26777,10.4749L2.79289,8L5.26777,5.52513L5.97487,6.23223L4.70703,7.5ZM15,4H14V12H15V4Z"/>
+                </Canvas>
+                <local:NumericUpDownControl Height="32" Width="64"  Margin="0,0,4,0"></local:NumericUpDownControl>
+                <TextBlock Text="mm" VerticalAlignment="Center"></TextBlock>
+            </StackPanel>
+            <StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
+                <Canvas Width="16" Height="16"  Margin="0,0,4,0">
+                    <Path Fill="Black" Data="M12,1V2L4,2V1L12,1ZM8.5,4.70703V11.2952L9.76777,10.0278L10.4749,10.7349L8,13.2097L5.52513,10.7349L6.23223,10.0278L7.5,11.2952L7.5,4.70703L6.23223,5.97487L5.52513,5.26777L8,2.79289L10.4749,5.26777L9.76777,5.97487L8.5,4.70703ZM12,15V14H4V15H12Z"/>
+                </Canvas>
+                <local:NumericUpDownControl  Height="32" Width="64"  Margin="0,0,4,0"></local:NumericUpDownControl>
+                <TextBlock Text="mm" VerticalAlignment="Center"></TextBlock>
+            </StackPanel>
+
+
+        </Grid>
+    </Grid>
+</UserControl>

+ 28 - 0
Demo/Examples/Compdfkit_Tools/Common/PropertyControl/PDFLocation/CPDFTileControl.xaml.cs

@@ -0,0 +1,28 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace Compdfkit_Tools.Common
+{
+    /// <summary>
+    /// Interaction logic for CPDFTileControl.xaml
+    /// </summary>
+    public partial class CPDFTileControl : UserControl
+    {
+        public CPDFTileControl()
+        {
+            InitializeComponent();
+        }
+    }
+}

+ 1 - 1
Demo/Examples/Compdfkit_Tools/Common/PropertyControl/PDFOpacity/CPDFOpactiyUI.xaml

@@ -20,7 +20,7 @@
         </Grid.ColumnDefinitions>
         <Slider  Style="{StaticResource SliderStyle}" MinHeight="40" VerticalAlignment="Center" Maximum="100" Minimum="0" TickFrequency="1" 
                  IsSelectionRangeEnabled="True"  IsMoveToPointEnabled="True" 
-                 IsSnapToTickEnabled="True" Value="{Binding OpacityValue, Mode=TwoWay}" Margin="10,0,10,0"></Slider>
+                 IsSnapToTickEnabled="True" Value="{Binding OpacityValue, Mode=TwoWay}" Margin="0,0,10,0"></Slider>
         <local:DropDownNumberBoxControl x:Name="DropDownNumberBoxControl"  Grid.Column="1" Unit="%" Maxium="100" Minimum="1" Height="28" Width="72" Text="{Binding OpacityValue,Mode=TwoWay}"></local:DropDownNumberBoxControl>
     </Grid>
 </UserControl>

+ 36 - 0
Demo/Examples/Compdfkit_Tools/Compdfkit_Tools.csproj

@@ -123,6 +123,9 @@
       <DependentUpon>CustomProgressBarControl.xaml</DependentUpon>
     </Compile>
     <Compile Include="Common\BaseControl\HomePageButton.cs" />
+    <Compile Include="Common\BaseControl\MatrixRadioControl.xaml.cs">
+      <DependentUpon>MatrixRadioControl.xaml</DependentUpon>
+    </Compile>
     <Compile Include="Common\BaseControl\PageNumberControl.xaml.cs">
       <DependentUpon>PageNumberControl.xaml</DependentUpon>
     </Compile>
@@ -140,6 +143,7 @@
     <Compile Include="Common\Convert\StringToVisibilityConverter.cs" />
     <Compile Include="Common\Convert\ShowDefaultCloseButtonConverter.cs" />
     <Compile Include="Common\Convert\ShowIconConverter.cs" />
+    <Compile Include="Common\Convert\TagToBoolConverter.cs" />
     <Compile Include="Common\Convert\WindowStateToPathConverter.cs" />
     <Compile Include="Common\Convert\WindowStateToThicknessConverter.cs" />
     <Compile Include="Common\DeviceSerial\DeviceSerialControl.xaml.cs">
@@ -221,6 +225,15 @@
     <Compile Include="Common\PropertyControl\PDFFont\CPDFFontUI.xaml.cs">
       <DependentUpon>CPDFFontUI.xaml</DependentUpon>
     </Compile>
+    <Compile Include="Common\PropertyControl\PDFLocation\CPDFLocationControl.xaml.cs">
+      <DependentUpon>CPDFLocationControl.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="Common\PropertyControl\PDFLocation\CPDFRotationControl.xaml.cs">
+      <DependentUpon>CPDFRotationControl.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="Common\PropertyControl\PDFLocation\CPDFTileControl.xaml.cs">
+      <DependentUpon>CPDFTileControl.xaml</DependentUpon>
+    </Compile>
     <Compile Include="Common\PropertyControl\PDFThickness\CPDFThicknessControl.xaml.cs">
       <DependentUpon>CPDFThicknessControl.xaml</DependentUpon>
     </Compile>
@@ -479,6 +492,9 @@
     <Compile Include="Security\Watermark\PreviewControl.xaml.cs">
       <DependentUpon>PreviewControl.xaml</DependentUpon>
     </Compile>
+    <Compile Include="Security\Watermark\WatermarkDialog.xaml.cs">
+      <DependentUpon>WatermarkDialog.xaml</DependentUpon>
+    </Compile>
     <Compile Include="Security\Watermark\WatermarkListDialog.xaml.cs">
       <DependentUpon>WatermarkListDialog.xaml</DependentUpon>
     </Compile>
@@ -633,6 +649,10 @@
       <Generator>MSBuild:Compile</Generator>
     </Page>
     <Page Include="Common\BaseControl\CustomProgressBarControl.xaml" />
+    <Page Include="Common\BaseControl\MatrixRadioControl.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
     <Page Include="Common\BaseControl\PageNumberControl.xaml">
       <Generator>MSBuild:Compile</Generator>
       <SubType>Designer</SubType>
@@ -731,6 +751,18 @@
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
     </Page>
+    <Page Include="Common\PropertyControl\PDFLocation\CPDFLocationControl.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
+    <Page Include="Common\PropertyControl\PDFLocation\CPDFRotationControl.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
+    <Page Include="Common\PropertyControl\PDFLocation\CPDFTileControl.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
     <Page Include="Common\PropertyControl\PDFThickness\CPDFThicknessControl.xaml">
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
@@ -1022,6 +1054,10 @@
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
     </Page>
+    <Page Include="Security\Watermark\WatermarkDialog.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
     <Page Include="Security\Watermark\WatermarkListDialog.xaml">
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>

+ 35 - 3
Demo/Examples/Compdfkit_Tools/Security/Watermark/FileGridListWithPageRangeControl.xaml.cs

@@ -30,10 +30,10 @@ namespace Compdfkit_Tools.PDFControl
         public CPDFDocument Document;
         public string Name { get; set; }
         public string Path { get; set; }
-
+        public string Size { get; set; }
+         
         private string _pageRange;
         public string PageRange { get => _pageRange; set => UpdateProper(ref _pageRange, value); }
-        public string Size { get; set; }
 
         private List<int> _pageRangeList = new List<int>();
         public List<int> PageRangeList
@@ -92,7 +92,28 @@ namespace Compdfkit_Tools.PDFControl
                     IsEnsure = _fileNumText > 0;
             }
         }
-
+         
+        public FileInfoWithRange FileForDisplay
+        {
+            get
+            {
+                if (FileDataGrid.Items.Count > 0)
+                {
+                    if (FileDataGrid.SelectedItems.Count > 0)
+                    {
+                        return FileDataGrid.SelectedItems[0] as FileInfoWithRange;
+                    }
+                    else
+                    {
+                        return FileDataGrid.Items[0] as FileInfoWithRange;
+                    }
+                }
+                else
+                {
+                    return null;
+                }
+            }
+        }
 
         private ObservableCollection<FileInfoWithRange> _fileInfoDataList;
         public ObservableCollection<FileInfoWithRange> FileInfoDataList
@@ -119,6 +140,7 @@ namespace Compdfkit_Tools.PDFControl
         {
             PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
         }
+
         protected bool UpdateProper<T>(ref T properValue,
     T newValue,
     [CallerMemberName] string properName = "")
@@ -187,9 +209,19 @@ namespace Compdfkit_Tools.PDFControl
             }
 
             pageRangeDialog.Owner = Window.GetWindow(this);
+            pageRangeDialog.WindowClosed += PageRangeDialog_WindowClosed;
+
             pageRangeDialog.ShowDialog();
         }
 
+        private void PageRangeDialog_WindowClosed(object sender, List<int> result)
+        {
+            if (result != null)
+            {
+              (FileDataGrid.SelectedItems[0] as FileInfoWithRange).PageRangeList = result;
+            }
+        }
+
         private void UserControl_Loaded(object sender, RoutedEventArgs e)
         {
             FileInfoDataList = new ObservableCollection<FileInfoWithRange>();

+ 8 - 5
Demo/Examples/Compdfkit_Tools/Security/Watermark/PageRangeDialog.xaml

@@ -35,17 +35,20 @@
                         <RowDefinition></RowDefinition>
                         <RowDefinition></RowDefinition>
                     </Grid.RowDefinitions>
-                    <RadioButton Margin="0,0,0,8" IsChecked="True">
+                    <RadioButton x:Name="AllRangeRdo" Tag="All" Margin="0,0,0,8" IsChecked="True" Checked="RangeRdo_Checked">
                         <TextBlock Text="All Pages" VerticalAlignment="Center" FontSize="14" FontFamily="Segoe UI"></TextBlock>
                     </RadioButton>
-                    <RadioButton Grid.Row="1" Margin="0,0,0,8">
+                    <RadioButton  x:Name="OddRangeRdo" Tag="Odd" Grid.Row="1" Margin="0,0,0,8" Checked="RangeRdo_Checked">
                         <TextBlock Text="Odd page only" VerticalAlignment="Center" FontSize="14" FontFamily="Segoe UI"></TextBlock>
                     </RadioButton>
-                    <RadioButton Grid.Row="2" Margin="0,0,0,8">
+                    <RadioButton x:Name="EvenRangeRdo" Tag="Even" IsEnabled="{Binding IsEvenEnable}" Grid.Row="2" Margin="0,0,0,8" Checked="RangeRdo_Checked">
                         <TextBlock Text="Even page only" VerticalAlignment="Center" FontSize="14" FontFamily="Segoe UI"></TextBlock>
                     </RadioButton>
-                    <RadioButton Grid.Row="3" Margin="0,0,0,8">
-                        <TextBlock Text="Custom Range" VerticalAlignment="Center" FontSize="14" FontFamily="Segoe UI"></TextBlock>
+                    <RadioButton x:Name="CustomRangeRdo" Tag="Custom" Grid.Row="3" Margin="0,0,0,8" Checked="RangeRdo_Checked">
+                        <StackPanel Orientation="Horizontal">
+                            <TextBlock Text="Custom Range" VerticalAlignment="Center" FontSize="14" FontFamily="Segoe UI"></TextBlock>
+                            <TextBox Margin="12,0,0,0" Text="{Binding PageRange, UpdateSourceTrigger=PropertyChanged}" Height="28" Width="150" IsEnabled="{Binding ElementName=CustomRangeRdo, Path=IsChecked}"></TextBox>
+                        </StackPanel>
                     </RadioButton>
                 </Grid>
             </Border>

+ 115 - 17
Demo/Examples/Compdfkit_Tools/Security/Watermark/PageRangeDialog.xaml.cs

@@ -1,28 +1,23 @@
-using ComPDFKit.PDFDocument;
+using Compdfkit_Tools.Helper;
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
-using System.IO;
 using System.Linq;
 using System.Runtime.CompilerServices;
-using System.Text;
-using System.Threading.Tasks;
 using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Data;
-using System.Windows.Documents;
-using System.Windows.Input;
-using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using System.Windows.Shapes;
+using RadioButton = System.Windows.Controls.RadioButton;
 
 namespace Compdfkit_Tools.PDFControl
 {
     /// <summary>
     /// Interaction logic for PageRangeDialog.xaml
     /// </summary>
-    public partial class PageRangeDialog : Window
+    public partial class PageRangeDialog : Window, INotifyPropertyChanged
     {
+        private int pageCount = 0;
+
+        private List<int> defaultPageList = new List<int>(); 
+         
         private List<int> _pageIndexList = new List<int>();
         public List<int> PageIndexList
         {
@@ -34,8 +29,43 @@ namespace Compdfkit_Tools.PDFControl
             }
         }
 
+        private bool _isEvenEnable = false;
+        public bool IsEvenEnable
+        {
+            get => _isEvenEnable;
+            set
+            {
+                UpdateProper(ref _isEvenEnable, value);
+            }
+        }
+
+        private string _pageRange;
+        public string PageRange
+        {
+            get => _pageRange;
+            set
+            {
+                if (fileInfo != null & UpdateProper(ref _pageRange, value))
+                {
+                    List<int> list = new List<int>();
+                    if (CommonHelper.GetPagesInRange(ref list, PageRange, fileInfo.Document.PageCount, new char[] { ',' }, new char[] { '-' }))
+                    {
+                        PageIndexList = list;
+                    }
+                    else
+                    {
+                        PageIndexList = fileInfo.PageRangeList;
+                    }
+                }
+            }
+        }
+         
         private FileInfoWithRange fileInfo;
 
+        private WeakReference weakReference;
+        public delegate void WindowClosedEventHandler(object sender, List<int> result);
+        public event WindowClosedEventHandler WindowClosed;
+
         public PageRangeDialog()
         {
             this.DataContext = this;
@@ -49,17 +79,85 @@ namespace Compdfkit_Tools.PDFControl
 
         private void ConfirmBtn_Click(object sender, RoutedEventArgs e)
         {
-
+            WindowClosed?.Invoke(weakReference.Target, PageIndexList);
+            this.Close();
         }
 
         private void CancelBtn_Click(object sender, RoutedEventArgs e)
         {
-
+            WindowClosed?.Invoke(weakReference.Target, null);
+            this.Close();
         }
-         
+
         private void Window_Loaded(object sender, RoutedEventArgs e)
-        { 
-            PreviewControl.InitPreview(fileInfo.Document, fileInfo.PageRangeList);
+        {
+            weakReference = new WeakReference(this);
+            PreviewControl.InitPreview(fileInfo.Document);
+            defaultPageList = CommonHelper.GetDefaultPageList(fileInfo.Document);
+            PageIndexList = defaultPageList;
+            pageCount = fileInfo.Document.PageCount;
+            if (pageCount <= 1)
+            {
+                IsEvenEnable = false;
+            }
+            else
+            {
+                IsEvenEnable = true;
+            }
+        }
+
+        private void RangeRdo_Checked(object sender, RoutedEventArgs e)
+        {
+            var radioButton = sender as RadioButton;
+            if (radioButton != null && fileInfo != null)
+            {
+
+                switch (radioButton.Tag)
+                {
+                    case "All":
+                        PageIndexList = defaultPageList;
+                        break;
+                    case "Odd":
+                        PageIndexList = defaultPageList.Where(value => value % 2 != 0).ToList();
+                        break;
+                    case "Even":
+                        if (fileInfo.PageRangeList.Count > 1)
+                        {
+                            PageIndexList = defaultPageList.Where(value => value % 2 == 0).ToList();
+                        }
+                        break;
+                    case "Custom":
+                        List<int> list = new List<int>();
+                        if (CommonHelper.GetPagesInRange(ref list, PageRange, fileInfo.Document.PageCount, new char[] { ',' }, new char[] { '-' }))
+                        {
+                            PageIndexList = list;
+                        }
+                        else
+                        {
+                            PageIndexList = defaultPageList;
+                        }
+                        break;
+                    default:
+                        break;
+                }
+            }
+        }
+
+        public event PropertyChangedEventHandler PropertyChanged;
+        protected virtual void OnPropertyChanged(string propertyName = null)
+        {
+            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+        }
+        protected bool UpdateProper<T>(ref T properValue,
+            T newValue,
+            [CallerMemberName] string properName = "")
+        {
+            if (object.Equals(properValue, newValue))
+                return false;
+
+            properValue = newValue;
+            OnPropertyChanged(properName);
+            return true;
         }
     }
 }

+ 27 - 11
Demo/Examples/Compdfkit_Tools/Security/Watermark/PreviewControl.xaml.cs

@@ -37,6 +37,7 @@ namespace Compdfkit_Tools.PDFControl
             get => _pageIndexList;
             set
             {
+                CurrentIndex = 1;
                 _pageIndexList = value;
                 PageCount = _pageIndexList.Count;
             }
@@ -69,7 +70,7 @@ namespace Compdfkit_Tools.PDFControl
 
                 if (UpdateProper(ref _currentIndex, value))
                 {
-                    ImageSource = LoadImage(Document.PageAtIndex(_currentIndex - 1));
+                    ImageSource = LoadImage(Document.PageAtIndex(PageRangeList[_currentIndex - 1] - 1));
                 }
             }
         }
@@ -114,15 +115,14 @@ namespace Compdfkit_Tools.PDFControl
             DataContext = this;
         }
 
-        public void InitPreview(CPDFDocument document, List<int> pageRangeList)
+        public void InitPreview(CPDFDocument document)
         {
             Document = document;
-            this.PageRangeList = pageRangeList;
         }
 
         private void Image_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
         {
-            lastMousePosition = e.GetPosition(Image);
+            lastMousePosition = e.GetPosition(ImageSv);
             startVerticalOffset = ImageSv.VerticalOffset;
             startHorizontalOffset = ImageSv.HorizontalOffset;
             Image.CaptureMouse();
@@ -139,12 +139,12 @@ namespace Compdfkit_Tools.PDFControl
         {
             if (ImageSv.Visibility == Visibility.Visible && Image.IsMouseCaptured)
             {
-                Point currentMousePosition = e.GetPosition(Image);
+                Point currentMousePosition = e.GetPosition(ImageSv);
                 double deltaVerticalOffset = lastMousePosition.Y - currentMousePosition.Y;
                 double deltaHorizontalOffset = lastMousePosition.X - currentMousePosition.X;
 
-                double newVerticalOffset = startVerticalOffset + deltaVerticalOffset/3;
-                double newHorizontalOffset = startHorizontalOffset + deltaHorizontalOffset/3;
+                double newVerticalOffset = startVerticalOffset + deltaVerticalOffset;
+                double newHorizontalOffset = startHorizontalOffset + deltaHorizontalOffset;
 
                 ImageSv.ScrollToVerticalOffset(newVerticalOffset);
                 ImageSv.ScrollToHorizontalOffset(newHorizontalOffset);
@@ -156,6 +156,7 @@ namespace Compdfkit_Tools.PDFControl
         {
             PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
         }
+
         protected bool UpdateProper<T>(ref T properValue,
             T newValue,
             [CallerMemberName] string properName = "")
@@ -221,12 +222,27 @@ namespace Compdfkit_Tools.PDFControl
 
         private async void UserControl_Loaded(object sender, RoutedEventArgs e)
         {
-            aspectRatio = ImageGd.ActualHeight / ImageGd.ActualWidth;
-            thumbnailWidth = ImageGd.ActualWidth - 20;
-            thumbnailHeight = ImageGd.ActualHeight - 20;
-            await LoadImageAsync(Document.PageAtIndex(0));
+            if(Document == null)
+            {
+                return;
+            }
+            try
+            {
+                await Dispatcher.InvokeAsync(() =>
+                {
+                    aspectRatio = ImageGd.ActualHeight / ImageGd.ActualWidth;
+                    thumbnailWidth = ImageGd.ActualWidth - 20;
+                    thumbnailHeight = ImageGd.ActualHeight - 20;
+                });
+
+                await LoadImageAsync(Document.PageAtIndex(0));
+            }
+            catch (Exception ex)
+            { 
+            }
         }
 
+
         private void CurrentIndexTxt_CanExecute(object sender, CanExecuteRoutedEventArgs e)
         {
             try

+ 147 - 0
Demo/Examples/Compdfkit_Tools/Security/Watermark/WatermarkDialog.xaml

@@ -0,0 +1,147 @@
+<Window x:Class="Compdfkit_Tools.PDFControl.WatermarkDialog"
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+        xmlns:local="clr-namespace:Compdfkit_Tools.PDFControl"
+        xmlns:common="clr-namespace:Compdfkit_Tools.Common"
+        mc:Ignorable="d"
+        Title="WatermarkDialog" Height="612" Width="900">
+    <Window.Resources>
+        <ResourceDictionary>
+            <ResourceDictionary.MergedDictionaries>
+                <ResourceDictionary Source="../../Asset/Styles/RadioButtonStyle.xaml"></ResourceDictionary>
+                <ResourceDictionary Source="../../Asset/Styles/ComboBoxStyle.xaml"></ResourceDictionary>
+            </ResourceDictionary.MergedDictionaries>
+        </ResourceDictionary>
+    </Window.Resources>
+    <Grid Margin="12">
+        <Grid.RowDefinitions>
+            <RowDefinition></RowDefinition>
+            <RowDefinition Height="auto"></RowDefinition>
+        </Grid.RowDefinitions>
+        <Grid.ColumnDefinitions>
+            <ColumnDefinition Width="auto"></ColumnDefinition>
+            <ColumnDefinition/>
+        </Grid.ColumnDefinitions>
+        <Grid  Width="248" Margin="0,0,0,112" Grid.RowSpan="2">
+            <local:PreviewControl  x:Name="PreviewControl"></local:PreviewControl>
+        </Grid>
+        <Grid Grid.Column="1" Grid.ColumnSpan="2" Margin="0,0,0,56" Grid.RowSpan="2">
+            <Grid.RowDefinitions>
+                <RowDefinition></RowDefinition>
+                <RowDefinition></RowDefinition>
+            </Grid.RowDefinitions>
+            <Grid Height="226">
+                <Border BorderThickness="1" BorderBrush="#33000000" Margin="32,10,0,0" VerticalAlignment="Stretch" >
+                    <Grid>
+                        <Grid.RowDefinitions>
+                            <RowDefinition></RowDefinition>
+                            <RowDefinition></RowDefinition>
+                        </Grid.RowDefinitions>
+                        <Grid Margin="20,20,0,0">
+                            <Grid.RowDefinitions>
+                                <RowDefinition Height="auto"></RowDefinition>
+                                <RowDefinition Height="auto"></RowDefinition>
+                                <RowDefinition Height="auto"></RowDefinition>
+                            </Grid.RowDefinitions>
+                            <RadioButton x:Name="TextRdo" IsChecked="True" GroupName="WatermarkType">
+                                <TextBlock Text="Text"></TextBlock>
+                            </RadioButton>
+                            <TextBox Grid.Row="1" Height="28" Width="438" Text="{Binding WatermarkTxt, UpdateSourceTrigger=PropertyChanged}" Margin="32,6,0,0" HorizontalAlignment="Left" VerticalContentAlignment="Center" IsEnabled="{Binding Path=IsChecked, ElementName=TextRdo}"></TextBox>
+                            <StackPanel Grid.Row="2" Orientation="Horizontal" Margin="32,6,0,0" Height="30">
+                                <ComboBox Style="{StaticResource ComboBoxStyle1}" Width="160" Margin="0,0,20,0">
+                                    <ComboBoxItem Tag="Helvetica" IsSelected="True">Helvetica</ComboBoxItem>
+                                    <ComboBoxItem Tag="Arial" IsSelected="True">Arial</ComboBoxItem>
+                                    <ComboBoxItem Tag="Roman" IsSelected="True">Times New Roman</ComboBoxItem>
+                                </ComboBox>
+                                <ComboBox Style="{StaticResource ComboBoxStyle1}" Width="96" Margin="0,0,20,0">
+                                    <ComboBoxItem Tag="24" IsSelected="True">24</ComboBoxItem>
+                                </ComboBox>
+                                <StackPanel Orientation="Horizontal">
+                                    <TextBlock Text="Color" VerticalAlignment="Center" Margin="0,0,8,0"></TextBlock>
+                                    <common:ColorPickerControl></common:ColorPickerControl>
+                                </StackPanel>
+                            </StackPanel>
+                        </Grid>
+
+                        <Grid  Margin="20,20,0,0" Grid.Row="1">
+                            <Grid.RowDefinitions>
+                                <RowDefinition Height="auto"></RowDefinition>
+                                <RowDefinition Height="auto"></RowDefinition>
+                            </Grid.RowDefinitions>
+                            <RadioButton Grid.Row="0"  GroupName="WatermarkType">
+                                <TextBlock Text="File"></TextBlock>
+                            </RadioButton>
+                            <StackPanel Grid.Row="1" Orientation="Horizontal" Margin="32,6,0,0" Height="28">
+                                <Button Width="296" Margin="0,0,20,0">
+                                    <TextBlock Text="{Binding ImagePath}" HorizontalAlignment="Left"></TextBlock>
+                                </Button>
+                                <TextBlock Text="Ratio" VerticalAlignment="Center" Margin="0,0,8,0"></TextBlock>
+                                <common:NumericUpDownControl></common:NumericUpDownControl>
+                            </StackPanel>
+                        </Grid>
+                    </Grid>
+                </Border>
+                <TextBlock Text="Watermark Content" Margin="50,3,0,0" Background="#fff" Height="20" HorizontalAlignment="Left" VerticalAlignment="Top" TextAlignment="Center" FontWeight="DemiBold" FontFamily="Segoe UI"></TextBlock>
+            </Grid>
+            <Grid Grid.Row="1" Margin="0,20,0,0">
+                <Border BorderThickness="1" BorderBrush="#33000000" Margin="32,10,0,0" VerticalAlignment="Stretch" >
+                    <Grid Margin="20">
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition></ColumnDefinition>
+                            <ColumnDefinition Width="242"></ColumnDefinition>
+                        </Grid.ColumnDefinitions>
+                        <Grid>
+                            <Grid.RowDefinitions>
+                                <RowDefinition></RowDefinition>
+                                <RowDefinition></RowDefinition>
+                                <RowDefinition Height="auto"></RowDefinition>
+                                <RowDefinition></RowDefinition>
+                            </Grid.RowDefinitions>
+                            <Grid.ColumnDefinitions>
+                                <ColumnDefinition Width="auto"></ColumnDefinition>
+                                <ColumnDefinition></ColumnDefinition>
+                            </Grid.ColumnDefinitions>
+                            <TextBlock HorizontalAlignment="Right" Text="Rotation"  VerticalAlignment="Center" Margin="0,0,8,0"></TextBlock>
+                            <common:CPDFRotationControl Height="32" Width="186" Grid.Column="1" HorizontalAlignment="Left"></common:CPDFRotationControl>
+                            <TextBlock HorizontalAlignment="Right" Text="Opactiy"  VerticalAlignment="Center" Margin="0,0,8,0" Grid.Row="1"></TextBlock>
+                            <common:CPDFOpacityControl Height="32" Width="200" Grid.Column="1" HorizontalAlignment="Left" Grid.Row="1"></common:CPDFOpacityControl>
+                            <TextBlock Text="Location"  HorizontalAlignment="Right" Grid.Row="2"  Margin="0,8,8,0"></TextBlock>
+                            <Grid Grid.Row="2" Grid.Column="1" Height="64">
+                                <Grid.RowDefinitions>
+                                    <RowDefinition></RowDefinition>
+                                    <RowDefinition></RowDefinition>
+                                </Grid.RowDefinitions>
+                                <RadioButton IsChecked="True">
+                                    <TextBlock Text="Front"></TextBlock>
+                                </RadioButton>
+                                <RadioButton Grid.Row="1">
+                                    <TextBlock Text="Behind"></TextBlock>
+                                </RadioButton>
+                            </Grid>
+                            <TextBlock HorizontalAlignment="Right"  Grid.Row="3"  Text="Page Range"  VerticalAlignment="Center"  Margin="0,0,8,0"></TextBlock>
+                            <common:WritableComboBoxControl IsEnabled="{Binding CanChangeRange}" Height="32" Width="175"  Grid.Row="3" Grid.Column="1" HorizontalAlignment="Left"></common:WritableComboBoxControl>
+                        </Grid>
+                        <Grid Grid.Column="1" Width="242">
+                            <Grid.RowDefinitions>
+                                <RowDefinition  Height="auto"></RowDefinition>
+                                <RowDefinition></RowDefinition>
+                            </Grid.RowDefinitions>
+                            <common:CPDFLocationControl></common:CPDFLocationControl>
+                            <common:CPDFTileControl Grid.Row="1" Height="72" VerticalAlignment="Bottom"></common:CPDFTileControl>
+                        </Grid>
+                    </Grid>
+                </Border>
+                <TextBlock Text="Page Range" Margin="50,3,0,0" Background="#fff" Height="20" Width="75" HorizontalAlignment="Left" VerticalAlignment="Top" TextAlignment="Center" FontWeight="DemiBold" FontFamily="Segoe UI"></TextBlock>
+
+            </Grid>
+        </Grid>
+        <Grid Grid.Row="1" Grid.ColumnSpan="3">
+            <StackPanel Orientation="Horizontal" Margin="0,12,0,12" HorizontalAlignment="Right">
+                <Button Height="32" Width="112" Margin="0,0,12,0"></Button>
+                <Button Height="32" Width="112"></Button>
+            </StackPanel>
+        </Grid>
+    </Grid>
+</Window>

+ 74 - 0
Demo/Examples/Compdfkit_Tools/Security/Watermark/WatermarkDialog.xaml.cs

@@ -0,0 +1,74 @@
+using Compdfkit_Tools.Helper;
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Shapes;
+
+namespace Compdfkit_Tools.PDFControl
+{
+    /// <summary>
+    /// Interaction logic for WatermarkDialog.xaml
+    /// </summary>
+    public partial class WatermarkDialog : Window, INotifyPropertyChanged
+    {
+        private bool _canChangeRange = false;
+        public bool CanChangeRange
+        {
+            get => _canChangeRange;
+            set => UpdateProper(ref _canChangeRange, value);
+        }
+
+        public WatermarkDialog()
+        {
+            DataContext = this;
+            InitializeComponent();
+        }
+
+        public bool InitWithFileInfo(FileInfoWithRange fileInfo)
+        {
+            if (fileInfo == null)
+            {
+                return false;
+            }
+            InitPreviewControl(fileInfo);
+            return true;
+        }
+
+        private void InitPreviewControl(FileInfoWithRange fileInfo)
+        {
+            PreviewControl.Document = fileInfo.Document;
+            PreviewControl.PageRangeList = CommonHelper.GetDefaultPageList(PreviewControl.Document);
+
+        }
+
+        public event PropertyChangedEventHandler PropertyChanged;
+        protected virtual void OnPropertyChanged(string propertyName = null)
+        {
+            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+        }
+
+        protected bool UpdateProper<T>(ref T properValue,
+            T newValue,
+            [CallerMemberName] string properName = "")
+        {
+            if (object.Equals(properValue, newValue))
+                return false;
+
+            properValue = newValue;
+            OnPropertyChanged(properName);
+            return true;
+        }
+
+    }
+}

+ 1 - 1
Demo/Examples/Compdfkit_Tools/Security/Watermark/WatermarkListDialog.xaml

@@ -15,7 +15,7 @@
         <local:FileGridListWithPageRangeControl x:Name="FileGridListWithPageRangeControl"></local:FileGridListWithPageRangeControl>
         <Grid Grid.Row="1">
             <StackPanel Orientation="Horizontal" Margin="0,24,24,12" HorizontalAlignment="Right">
-                <Button x:Name="NextBtn" Content="Next" Height="32" Width="112" IsEnabled="{Binding ElementName=FileGridListWithPageRangeControl, Path=IsEnsure}" Margin="0,0,8,0"></Button>
+                <Button x:Name="NextBtn" Content="Next" Height="32" Width="112" IsEnabled="{Binding ElementName=FileGridListWithPageRangeControl, Path=IsEnsure}" Margin="0,0,8,0" Click="NextBtn_Click"></Button>
                 <Button x:Name="CancelBtn" Height="32" Content="Cancel" Width="112" ></Button>
             </StackPanel>
         </Grid>

+ 16 - 0
Demo/Examples/Compdfkit_Tools/Security/Watermark/WatermarkListDialog.xaml.cs

@@ -23,5 +23,21 @@ namespace Compdfkit_Tools.PDFControl
         {
             InitializeComponent();
         }
+
+        private void NextBtn_Click(object sender, RoutedEventArgs e)
+        {
+            WatermarkDialog watermarkDialog = new WatermarkDialog
+            {
+                Owner = this
+            };
+            if (watermarkDialog.InitWithFileInfo(FileGridListWithPageRangeControl.FileForDisplay))
+            {
+                watermarkDialog.ShowDialog();
+            }
+            else
+            {
+                MessageBox.Show("No file selected.");
+            }
+        }
     }
 }