Ver Fonte

Merge branch 'compdfkit_demo_win_dev' into compdfkit_demo_win_dev_pdftech

# Conflicts:
#	Demo/Examples/ComPDFKit.Tool/CPDFToolManager.cs
#	Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.Annot.cs
#	Demo/Examples/ComPDFKit.Tool/DrawTool/CreateAnnotTool.cs
#	Demo/Examples/ComPDFKit.Tool/DrawTool/SelectedRect.cs
#	Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory.cs
#	Demo/Examples/ComPDFKit.Tool/UndoManger/GroupHistory.cs
#	Demo/Examples/ComPDFKit.Tool/UndoManger/MultiAnnotHistory.cs
#	Demo/Examples/ComPDFKit.Tool/UndoManger/PDFEditHistory/PDFEditHistory.cs
liyijie há 1 mês atrás
pai
commit
c82ea76972
100 ficheiros alterados com 9492 adições e 2061 exclusões
  1. 1 1
      Demo/Examples/Annotations/MainWindow.xaml
  2. 2 2
      Demo/Examples/Annotations/Properties/AssemblyInfo.cs
  3. 139 1
      Demo/Examples/ComPDFKit.Tool/AlignmentsHelp.cs
  4. 444 81
      Demo/Examples/ComPDFKit.Tool/CPDFToolManager.cs
  5. 38 13
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.Annot.cs
  6. 1136 0
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.AnnotSelector.cs
  7. 161 18
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.Command.cs
  8. 2 0
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.CustomizeTool.cs
  9. 29 30
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.DataMethod.cs
  10. 6 0
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.FindReplace.cs
  11. 108 37
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.MultiSelectedRect.cs
  12. 131 0
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.PDFCompareEffect.cs
  13. 35 7
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.SelectImage.cs
  14. 4 1
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.SelectText.cs
  15. 17 1
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.SelectedRect.cs
  16. 1196 59
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.TextEdit.cs
  17. 10 0
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.WidgetTool.cs
  18. 2 4
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.xaml
  19. 232 26
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.xaml.cs
  20. 26 1
      Demo/Examples/ComPDFKit.Tool/ComPDFKit.Tool.csproj
  21. 195 116
      Demo/Examples/ComPDFKit.Tool/DrawTool/AnnotEdit.cs
  22. 210 0
      Demo/Examples/ComPDFKit.Tool/DrawTool/AnnotSelector.cs
  23. 61 18
      Demo/Examples/ComPDFKit.Tool/DrawTool/CreateAnnotTool.cs
  24. 16 1
      Demo/Examples/ComPDFKit.Tool/DrawTool/CreateCustomizeTool.cs
  25. 47 0
      Demo/Examples/ComPDFKit.Tool/DrawTool/DashBorder.cs
  26. 450 0
      Demo/Examples/ComPDFKit.Tool/DrawTool/FrameSelectTool.cs
  27. 193 17
      Demo/Examples/ComPDFKit.Tool/DrawTool/MultiSelectedRect.cs
  28. 301 19
      Demo/Examples/ComPDFKit.Tool/DrawTool/SelectedRect.cs
  29. 404 23
      Demo/Examples/ComPDFKit.Tool/DrawTool/SelectedRect.protected.cs
  30. 83 0
      Demo/Examples/ComPDFKit.Tool/Help/CommonHelper.cs
  31. 20 1
      Demo/Examples/ComPDFKit.Tool/Help/PDFHelp.cs
  32. 87 9
      Demo/Examples/ComPDFKit.Tool/Help/ParamConverter.cs
  33. 70 81
      Demo/Examples/ComPDFKit.Tool/PDFTextSearch.cs
  34. 9 1
      Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/FreeTextParam.cs
  35. 9 2
      Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/InkParam.cs
  36. 23 18
      Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/LineMeasureParam.cs
  37. 5 1
      Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/StampParam.cs
  38. 3 0
      Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/StickyNoteParam.cs
  39. 18 0
      Demo/Examples/ComPDFKit.Tool/SettingParam/DefaultSettingParam.cs
  40. 2 2
      Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory.cs
  41. 18 26
      Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/FreeTextAnnotHistory.cs
  42. 15 0
      Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/InkAnnotHistory.cs
  43. 14 10
      Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/LineMeasureAnnotHistory.cs
  44. 1 1
      Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/PolyLineMeasureAnnotHistory.cs
  45. 1 1
      Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/PolygonMeasureAnnotHistory.cs
  46. 242 9
      Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/StampAnnotHistory.cs
  47. 13 2
      Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/StickyNoteAnnotHistory.cs
  48. 4 28
      Demo/Examples/ComPDFKit.Tool/UndoManger/FormHistory/ComboBoxHistory.cs
  49. 4 29
      Demo/Examples/ComPDFKit.Tool/UndoManger/FormHistory/ListBoxHistory.cs
  50. 4 28
      Demo/Examples/ComPDFKit.Tool/UndoManger/FormHistory/PushButtonHistory.cs
  51. 4 28
      Demo/Examples/ComPDFKit.Tool/UndoManger/FormHistory/TextBoxHistory.cs
  52. 8 7
      Demo/Examples/ComPDFKit.Tool/UndoManger/GroupHistory.cs
  53. 1 1
      Demo/Examples/ComPDFKit.Tool/UndoManger/MultiAnnotHistory.cs
  54. 28 21
      Demo/Examples/ComPDFKit.Tool/UndoManger/PDFEditHistory/PDFEditHistory.cs
  55. 1 1
      Demo/Examples/Compdfkit.Controls/Annotation/CPDFAnnotationPreviewerControl.xaml.cs
  56. 6 1
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationData/CPDFAnnotationData.cs
  57. 65 1
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListControl/CPDFAnnotationListControl.xaml
  58. 203 18
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListControl/CPDFAnnotationListControl.xaml.cs
  59. 134 0
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListUI/AnnotationReplyListControl.xaml
  60. 215 0
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListUI/AnnotationReplyListControl.xaml.cs
  61. 0 239
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListUI/CPDFAnnoationListUI.xaml.cs
  62. 121 24
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListUI/CPDFAnnoationListUI.xaml
  63. 690 0
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListUI/CPDFAnnotationListUI.xaml.cs
  64. 71 0
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListUI/ReplyStatusControl.xaml
  65. 175 0
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListUI/ReplyStatusControl.xaml.cs
  66. 8 4
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationPanel/PDFAnnotationControl/CPDFAnnotationControl.xaml.cs
  67. 1 0
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationPanel/PDFAnnotationUI/CPDFSignatureUI.xaml.cs
  68. 1 1
      Demo/Examples/Compdfkit.Controls/Asset/Styles/ComboBoxStyle.xaml
  69. 0 2
      Demo/Examples/Compdfkit.Controls/Asset/Styles/ListBoxItemStyle.xaml
  70. 4 0
      Demo/Examples/Compdfkit.Controls/Common/BarControl/CPDFTitleBarControl.xaml
  71. 7 1
      Demo/Examples/Compdfkit.Controls/Common/BarControl/CPDFTitleBarControl.xaml.cs
  72. 2 4
      Demo/Examples/Compdfkit.Controls/Common/BaseControl/PageNumberControl.xaml
  73. 3 3
      Demo/Examples/Compdfkit.Controls/Common/Convert/AnnotArgsTypeToVisibilityConverter.cs
  74. 25 0
      Demo/Examples/Compdfkit.Controls/Common/Convert/AntiVisibilityConverter.cs
  75. 8 10
      Demo/Examples/Compdfkit.Controls/Common/Convert/LanguageResourceConverter.cs
  76. 28 0
      Demo/Examples/Compdfkit.Controls/Common/Convert/SubtractionConverter.cs
  77. 1 1
      Demo/Examples/Compdfkit.Controls/Common/PropertyControl/PDFFont/CPDFFontControl.xaml.cs
  78. 48 7
      Demo/Examples/Compdfkit.Controls/Compdfkit.Controls.csproj
  79. 3 1
      Demo/Examples/Compdfkit.Controls/DigitalSignature/DigitalSignatureControl/DigitalSignatureControl.xaml.cs
  80. 102 36
      Demo/Examples/Compdfkit.Controls/Edit/ContentEditCOntrol/ContentEditControl.xaml.cs
  81. 4 2
      Demo/Examples/Compdfkit.Controls/Edit/PDFContentEditControl.xaml.cs
  82. 90 96
      Demo/Examples/Compdfkit.Controls/Edit/PDFImageEdit/PDFImageEditControl/PDFImageEditControl.xaml
  83. 267 140
      Demo/Examples/Compdfkit.Controls/Edit/PDFImageEdit/PDFImageEditControl/PDFImageEditControl.xaml.cs
  84. 53 44
      Demo/Examples/Compdfkit.Controls/Edit/PDFTextEdit/PDFTextEditControl/PDFTextEditControl.xaml
  85. 360 151
      Demo/Examples/Compdfkit.Controls/Edit/PDFTextEdit/PDFTextEditControl/PDFTextEditControl.xaml.cs
  86. 80 77
      Demo/Examples/Compdfkit.Controls/Form/Property/CheckBoxProperty.xaml
  87. 104 101
      Demo/Examples/Compdfkit.Controls/Form/Property/ComboBoxProperty.xaml
  88. 1 1
      Demo/Examples/Compdfkit.Controls/Form/Property/ComboBoxProperty.xaml.cs
  89. 104 101
      Demo/Examples/Compdfkit.Controls/Form/Property/ListBoxProperty.xaml
  90. 1 1
      Demo/Examples/Compdfkit.Controls/Form/Property/ListBoxProperty.xaml.cs
  91. 90 88
      Demo/Examples/Compdfkit.Controls/Form/Property/PushButtonProperty.xaml
  92. 1 1
      Demo/Examples/Compdfkit.Controls/Form/Property/PushButtonProperty.xaml.cs
  93. 3 1
      Demo/Examples/Compdfkit.Controls/Form/Property/RadioButtonProperty.xaml
  94. 29 26
      Demo/Examples/Compdfkit.Controls/Form/Property/SignatureProperty.xaml
  95. 91 88
      Demo/Examples/Compdfkit.Controls/Form/Property/TextFieldProperty.xaml
  96. 1 1
      Demo/Examples/Compdfkit.Controls/Form/Property/TextFieldProperty.xaml.cs
  97. 2 2
      Demo/Examples/Compdfkit.Controls/Measure/MeasureControl.xaml.cs
  98. 3 3
      Demo/Examples/Compdfkit.Controls/Measure/MeasureSettingPanel.xaml.cs
  99. 4 1
      Demo/Examples/Compdfkit.Controls/PDFView/PDFDisplaySettings/PDFDisplaySettingsControl/CPDFDisplaySettingsControl.xaml
  100. 0 0
      Demo/Examples/Compdfkit.Controls/PDFView/PDFSearch/PDFSearchControl/CPDFSearchControl.xaml.cs

+ 1 - 1
Demo/Examples/Annotations/MainWindow.xaml

@@ -148,7 +148,7 @@
                         <ToggleButton.Content>
                             <Path Fill="#43474D" Width="30" Height="30">
                                 <Path.Data>
-                                    M22.5 8.5H7.5V12.25H13H22.5V8.5ZM12.25 13.75H7.5V21.5H12.25V13.75ZM13.75 21.5V13.75H22.5V21.5H13.75ZM7.5 7H6V8.5V21.5V23H7.5H22.5H24V21.5V8.5V7H22.5H7.5Z
+                                    M7.5 8.5H22.5V12.25H17H7.5V8.5ZM17.75 13.75H22.5V21.5H17.75V13.75ZM16.25 21.5V13.75H7.5V21.5H16.25ZM22.5 7H24V8.5V21.5V23H22.5H7.5H6V21.5V8.5V7H7.5H22.5Z
                                 </Path.Data>
                             </Path>
                         </ToggleButton.Content>

+ 2 - 2
Demo/Examples/Annotations/Properties/AssemblyInfo.cs

@@ -51,5 +51,5 @@ using System.Windows;
 // You can specify all the values or you can default the Build and Revision Numbers
 // by using the '*' as shown below:
 // [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.13.0.0")]
-[assembly: AssemblyFileVersion("1.13.0.0")]
+[assembly: AssemblyVersion("2.1.0.0")]
+[assembly: AssemblyFileVersion("2.1.0.0")]

+ 139 - 1
Demo/Examples/ComPDFKit.Tool/AlignmentsHelp.cs

@@ -2,6 +2,7 @@
 using System.Collections;
 using System.Collections.Generic;
 using System.Linq;
+using System.Runtime.CompilerServices;
 using System.Text;
 using System.Threading.Tasks;
 using System.Windows;
@@ -44,7 +45,7 @@ namespace ComPDFKit.Tool
         /// <returns>
         /// X Y direction distance required for alignment of the source rectangle
         /// </returns>
-        public static Point SetAlignHorizonCenter (Rect src, Rect dst)
+        public static Point SetAlignHorizonCenter(Rect src, Rect dst)
         {
             Point movePoint = new Point((dst.Left + dst.Right - src.Left - src.Right) / 2, 0);
             return movePoint;
@@ -214,6 +215,143 @@ namespace ComPDFKit.Tool
             return dictionary;
         }
 
+        /// <summary>
+        /// Set the source rectangle to a horizontal distribution and align it within the target rectangle to maintain consistent gaps
+        /// </summary>
+        /// <param name="src">
+        /// Array of source rectangles needed
+        /// </param>
+        /// <param name="dst">
+        /// Target rectangle
+        /// </param>
+        /// <returns>
+        /// Dictionary of XY direction distance required for alignment of each source rectangle
+        /// </returns>
+        public static Dictionary<Rect, Point> SetGapDistributeHorizontal(List<Rect> src, Rect dst)
+        {
+            Dictionary<Rect, Point> dictionary = new Dictionary<Rect, Point>();
+            List<double> Leftlist = new List<double>();
+
+            // Sort the data according to the leftmost position of each rectangle, not the array order
+            double weight = 0;
+            foreach (Rect srcRect in src)
+            {
+                double left = srcRect.Left;
+                if (Leftlist.Contains(left))
+                {
+                    left += src.IndexOf(srcRect) * 0.01;
+                }
+                Leftlist.Add(left);
+                weight += srcRect.Width;
+            }
+            double[] datalist = Leftlist.ToArray();
+            Sort(datalist, 0, Leftlist.Count - 1);
+
+            double startX = dst.Left;
+            double endX = dst.Right;
+            double interval = ((endX - startX) - weight) / (Leftlist.Count - 1);
+            for (int i = 0; i < datalist.Count(); i++)
+            {
+                int index = Leftlist.IndexOf(datalist[i]);
+                Point movePoint = new Point();
+                if (i == 0 || i == datalist.Count() - 1)
+                {
+                    movePoint = new Point(0, 0);
+                }
+                else
+                {
+                    double width = 0;
+                    for (int f = 0; f < i; f++)
+                    {
+                        int index2 = 0;
+                        if (f != 0)
+                        {
+                            index2 = Leftlist.IndexOf(datalist[i - 1]);
+                            width += src[index2].Width;
+                        }
+                        int index0 = Leftlist.IndexOf(datalist[0]);
+                        if (f == 0)
+                        {
+                            width += src[index0].Right;
+                        }
+                        width += interval;
+
+                    }
+                    movePoint = new Point(width - src[index].X , 0);
+                }
+                dictionary.Add(src[index], movePoint);
+            }
+            return dictionary;
+        }
+
+        /// <summary>
+        /// Vertically distribute source rectangles within the target rectangle to maintain consistent gaps (sorted by the leftmost position of each rectangle, rather than array order)
+        /// </summary>
+        /// <param name="src">
+        /// Array of source rectangles needed
+        /// </param>
+        /// <param name="dst">
+        /// Target rectangle
+        /// </param>
+        /// <returns>
+        /// Dictionary of XY direction distance required for alignment of each source rectangle
+        /// </returns>
+        public static Dictionary<Rect, Point> SetGapDistributeVertical(List<Rect> src, Rect dst)
+        {
+            Dictionary<Rect, Point> dictionary = new Dictionary<Rect, Point>();
+            List<double> Leftlist = new List<double>();
+
+            // Sort the data according to the leftmost position of each rectangle, not the array order
+            double tall = 0;
+            foreach (Rect srcRect in src)
+            {
+                double top = srcRect.Top;
+                if (Leftlist.Contains(top)) {
+                    top += src.IndexOf(srcRect)*0.01;
+                }
+                Leftlist.Add(top);
+                tall += srcRect.Height;
+            }
+            double[] datalist = Leftlist.ToArray();
+            Sort(datalist, 0, Leftlist.Count - 1);
+
+            double startY = dst.Top;
+            double endY = dst.Bottom;
+            double interval = ((endY - startY) - tall) / (Leftlist.Count - 1);
+            for (int i = 0; i < datalist.Count(); i++)
+            {
+                int index = Leftlist.IndexOf(datalist[i]);
+                Point movePoint = new Point();
+                if (i == 0 || i == datalist.Count() - 1)
+                {
+                    movePoint = new Point(0, 0);
+                }
+                else
+                {
+                    double height = 0;
+                    for (int f = 0; f < i; f++)
+                    {
+                        int index2 = 0;
+                        if (f != 0)
+                        {
+                            index2 = Leftlist.IndexOf(datalist[i - 1]);
+                            height += src[index2].Height;
+                        }
+                        int index0 = Leftlist.IndexOf(datalist[0]);
+                        if (f == 0)
+                        {
+                            height += src[index0].Bottom;
+                        }
+                        height +=interval;
+
+                    }
+                    movePoint = new Point(0, height - src[index].Y);
+                }
+                dictionary.Add(src[index], movePoint);
+            }
+            return dictionary;
+        }
+
         #region Quick sort
 
         private static int SortUnit(double[] array, int low, int high)

+ 444 - 81
Demo/Examples/ComPDFKit.Tool/CPDFToolManager.cs

@@ -20,9 +20,12 @@ using ComPDFKit.Tool.Help;
 using ComPDFKit.Measure;
 using System.Dynamic;
 using System.Globalization;
-using System.Windows.Controls;
+using ComPDFKitViewer.Layer;
 using ComPDFKitViewer;
-using System.Reflection;
+using ComPDFKitViewer.Annot;
+using System.Windows.Annotations;
+using ComPDFKit.Viewer.Annot;
+using System.Windows.Controls;
 using ComPDFKit.PDFDocument.Action;
 
 namespace ComPDFKit.Tool
@@ -74,6 +77,24 @@ namespace ComPDFKit.Tool
         /// </summary>
         private string createImagePath = string.Empty;
 
+        private bool isActiveCropping = true;
+
+        /// <summary>
+        ///  add TextEdit Cursor
+        /// </summary>
+        private Cursor addTextEditCursor = Cursors.IBeam;
+
+        /// <summary>
+        /// add ImageEdit Cursor 
+        /// </summary>
+        private Cursor addImageEditCursor = Cursors.Arrow;
+
+        public bool SaveEmptyStickyAnnot { get; set; } = true;
+        public void SetActiveCropping(bool isActiveCropping)
+        {
+            this.isActiveCropping = isActiveCropping;
+        }
+
         public CPDFToolManager(CPDFViewerTool cPDFTool) : base()
         {
             viewerTool = cPDFTool;
@@ -326,19 +347,17 @@ namespace ComPDFKit.Tool
                 default:
                     break;
             }
+
             if (oldToolType == ToolType.ContentEdit)
             {
-                viewerTool.GetCPDFViewer().GetDocument().ReleasePages();
-
-                viewerTool.GetCPDFViewer().UndoManager.RemoveRedoHistoryForType(typeof(PDFEditHistory));
-                viewerTool.GetCPDFViewer().UndoManager.RemoveUndoHistoryForType(typeof(PDFEditHistory));
+                viewerTool.GetCPDFViewer().GetDocument()?.ReleasePages();
+                //Undo delete logic
+                viewerTool.GetCPDFViewer().UndoManager.ClearHistory();
+                // viewerTool.GetCPDFViewer().UndoManager.RemoveRedoHistoryForType(typeof(PDFEditHistory));
+                //viewerTool.GetCPDFViewer().UndoManager.RemoveUndoHistoryForType(typeof(PDFEditHistory));
                 viewerTool.GetCPDFViewer().UpdateVirtualNodes();
                 viewerTool.GetCPDFViewer().UpdateRenderFrame();
             }
-            else
-            {
-                viewerTool.GetCPDFViewer().UpdateRenderFrame();
-            }
         }
 
         public CPDFEditArea GetSelectedEditAreaObject(ref int pageIndex)
@@ -355,6 +374,37 @@ namespace ComPDFKit.Tool
             return editAreaObject?.cPDFEditArea;
         }
 
+        /// <summary>
+        /// Get the index of the multi choice comment list
+        /// </summary>
+        /// <param name="pageIndexs"></param>
+        /// <returns></returns>
+        public List<CPDFEditArea> GetSelectedEditAreaListObject(ref List<int> pageIndexs)
+        {
+            List<CPDFEditArea> editAreaObjectlist = new List<CPDFEditArea>();
+            MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(viewerTool.PDFViewer.GetViewForTag(viewerTool.MultiSelectedRectViewTag));
+            if (multiSelectedRect != null && multiSelectedRect.Children.Count > 0)
+            {
+                foreach (SelectedRect selectedRect in multiSelectedRect.Children)
+                {
+                    EditAreaObject editAreaObject = viewerTool.GetEditAreaObjectListForRect(selectedRect);
+                    if (editAreaObject == null)
+                    {
+                        //pageIndexs.Add(-1);
+                    }
+                    else
+                    {
+                        if (!editAreaObjectlist.Contains(editAreaObject?.cPDFEditArea))
+                        {
+                            pageIndexs.Add(editAreaObject.PageIndex);
+                            editAreaObjectlist.Add(editAreaObject?.cPDFEditArea);
+                        }
+                    }
+                }
+            }
+            return editAreaObjectlist;
+        }
+
         public CPDFAnnotation GetCPDFAnnotation()
         {
             return cPDFAnnotation;
@@ -435,20 +485,24 @@ namespace ComPDFKit.Tool
             {
                 case C_ANNOTATION_TYPE.C_ANNOTATION_WIDGET:
                     {
-                    currentParam = ParamConverter.WidgetConverter(viewerTool.GetCPDFViewer().GetDocument(), e.annotData.Annot);
-                    (e.annotData.Annot as CPDFWidget).UpdateFormAp();
-                    break;
+                        currentParam = ParamConverter.WidgetConverter(viewerTool.GetCPDFViewer().GetDocument(), e.annotData.Annot);
+                        (e.annotData.Annot as CPDFWidget).UpdateFormAp();
+                        break;
                     }
 
                 default:
                     {
-                    currentParam = ParamConverter.AnnotConverter(viewerTool.GetCPDFViewer().GetDocument(), e.annotData.Annot);
+                        currentParam = ParamConverter.AnnotConverter(viewerTool.GetCPDFViewer().GetDocument(), e.annotData.Annot);
                         if (e.annotData.AnnotType != C_ANNOTATION_TYPE.C_ANNOTATION_SOUND)
                         {
-                    e.annotData.Annot.UpdateAp();
+                            e.annotData.Annot.UpdateAp();
+                            if(e.annotData.Annot is CPDFTextAnnotation)
+                            {
+                                CommonHelper.UpdateStickyAP(e.annotData.Annot as CPDFTextAnnotation);
+                            }
                         }
-                    break;
-            }
+                        break;
+                    }
             }
 
             annotHistory.PreviousParam = previousParam;
@@ -456,7 +510,7 @@ namespace ComPDFKit.Tool
             annotHistory.CurrentParam = currentParam;
             annotHistory.Action = HistoryAction.Update;
             viewerTool.GetCPDFViewer().UndoManager.AddHistory(annotHistory);
-            viewerTool.GetCPDFViewer().UpdateRenderFrame();
+            viewerTool.GetCPDFViewer().UpdateAnnotFrame();
             AnnotDefaultEditedHandler?.Invoke(this, e);
         }
 
@@ -488,8 +542,9 @@ namespace ComPDFKit.Tool
             CPDFDocument cPDFDocument = viewerTool.GetCPDFViewer().GetDocument();
             CPDFPage cPDFPage = cPDFDocument.PageAtIndex(e.PageIndex);
             CPDFEditPage cPDFEditPage = cPDFPage.GetEditPage();
-            cPDFEditPage.BeginEdit(CPDFEditType.EditText | CPDFEditType.EditImage);
-            List<CPDFEditArea> cPDFEditAreas = cPDFEditPage.GetEditAreaList(true);
+            //cPDFEditPage.BeginEdit(CPDFEditType.EditText | CPDFEditType.EditImage);
+            List<CPDFEditArea> cPDFEditAreas = cPDFEditPage.GetEditAreaList(false);
+            float zoom = (float)viewerTool.PDFViewer.GetZoom();
             for (int i = 0; i < e.MultiObjectIndex.Count; i++)
             {
                 if (e.MultiObjectIndex[i] < cPDFEditAreas.Count)
@@ -498,20 +553,66 @@ namespace ComPDFKit.Tool
                     pDFEditHistory.PageIndex = e.PageIndex;
                     pDFEditHistory.EditPage = cPDFEditPage;
                     CRect cRect = cPDFEditAreas[e.MultiObjectIndex[i]].GetFrame();
+                    if (cPDFEditAreas[e.MultiObjectIndex[i]].Type == CPDFEditType.EditImage)
+                    {
+                        cRect = (cPDFEditAreas[e.MultiObjectIndex[i]] as CPDFEditImageArea).GetClipRect();
+                    }
                     Point point = DpiHelper.StandardPointToPDFPoint(e.MoveOffset);
-                    cRect.left += (float)point.X;
-                    cRect.right += (float)point.X;
-                    cRect.top += (float)point.Y;
-                    cRect.bottom += (float)point.Y;
+                    point.X = point.X / zoom;
+                    point.Y = point.Y / zoom;
+                    if (point.X != 0 && point.Y != 0 && e.ZoomX == 1 && e.ZoomY == 1)
+                    {
+                        cRect.left += (float)point.X;
+                        cRect.right += (float)point.X;
+                        cRect.top += (float)point.Y;
+                        cRect.bottom += (float)point.Y;
+                    }
+                    else
+                    {
+                        //Mobile scaling ratio logic
+                        if ((float)point.X == 0)
+                        {
+                            cRect.left += (float)point.X;
+                            cRect.right = cRect.left + (cRect.right - cRect.left) + (float)DpiHelper.StandardNumToPDFNum(e.ChangeX) / zoom;
+                        }
+                        else
+                        {
+                            cRect.left += (float)point.X;
+                            if (e.ZoomX == 1)
+                            {
+                                cRect.right += (float)point.X;
+                            }
+                        }
+                        if ((float)point.Y == 0)
+                        {
+                            cRect.top += (float)point.Y;
+                            cRect.bottom = cRect.top + (cRect.bottom - cRect.top) + (float)DpiHelper.StandardNumToPDFNum(e.ChangeY) / zoom;
+                        }
+                        else
+                        {
 
-                    cRect.right = cRect.right * e.ZoomX;
-                    cRect.bottom = cRect.bottom * e.ZoomY;
+                            cRect.top += (float)point.Y;
+                            if (e.ZoomY == 1)
+                            {
+                                cRect.bottom += (float)point.Y;
+                            }
+                        }
+                    }
+                    //Original Logic
+                    //cRect.left += (float)point.X;
+                    //cRect.right += (float)point.X;
+                    //cRect.top += (float)point.Y;
+                    //cRect.bottom += (float)point.Y;
+
+                    //cRect.right = cRect.right* e.ZoomX;
+                    //cRect.bottom = cRect.bottom * e.ZoomY;
                     cPDFEditAreas[e.MultiObjectIndex[i]].SetFrame(cRect);
                     groupHistory.Histories.Add(pDFEditHistory);
                 }
             }
+            //Add end edit
+            cPDFEditPage.EndEdit();
             viewerTool.GetCPDFViewer().UndoManager.AddHistory(groupHistory);
-
             viewerTool.GetCPDFViewer().UpdateRenderFrame();
         }
 
@@ -546,7 +647,7 @@ namespace ComPDFKit.Tool
             switch (e.annotData.AnnotType)
             {
                 case C_ANNOTATION_TYPE.C_ANNOTATION_LINE:
-                    if ((e.annotData.Annot as CPDFLineAnnotation).IsMersured())
+                    if ((e.annotData.Annot as CPDFLineAnnotation).IsMeasured())
                     {
                         List<Point> cPoints = new List<Point>();
                         for (int i = 0; i < e.Points.Count; i++)
@@ -611,7 +712,7 @@ namespace ComPDFKit.Tool
                         }
                         lineMeasure.UpdateAnnotMeasure();
                         annotLine.UpdateAp();
-                        if (annotLine.IsMersured())
+                        if (annotLine.IsMeasured())
                         {
                             PostMeasureInfo(this, annotLine);
                         }
@@ -661,7 +762,7 @@ namespace ComPDFKit.Tool
                             (float)top));
                         annotLine.GetAreaMeasure().UpdateAnnotMeasure();
                         annotLine.UpdateAp();
-                        if (annotLine.IsMersured())
+                        if (annotLine.IsMeasured())
                         {
                             PostMeasureInfo(this, annotLine);
                         }
@@ -693,7 +794,7 @@ namespace ComPDFKit.Tool
 
                         annotLine.GetPerimeterMeasure().UpdateAnnotMeasure();
                         annotLine.UpdateAp();
-                        if (annotLine.IsMersured())
+                        if (annotLine.IsMeasured())
                         {
                             PostMeasureInfo(this, annotLine);
                         }
@@ -728,7 +829,14 @@ namespace ComPDFKit.Tool
             annotHistory.CurrentParam = currentParam;
             annotHistory.Action = HistoryAction.Update;
             viewerTool.GetCPDFViewer().UndoManager.AddHistory(annotHistory);
-            viewerTool.GetCPDFViewer().UpdateRenderFrame();
+            if (e.annotData.Annot.IsMeasured())
+            {
+                viewerTool.GetCPDFViewer().UpdateRenderFrame();
+            }
+            else
+            {
+                viewerTool.GetCPDFViewer().UpdateAnnotFrame();
+            }
         }
 
         private void ViewerTool_MouseLeftButtonUpHandler(object sender, MouseEventObject e)
@@ -739,7 +847,7 @@ namespace ComPDFKit.Tool
             viewerTool.DrawEndSelectedMultiRect();
             viewerTool.DrawEndPageSelectedRect();
             if (currentToolType != ToolType.SelectedPage &&
-                viewerTool.IsCanSave()&&
+                viewerTool.IsCanSave() &&
                 cPDFAnnotation?.Type != C_ANNOTATION_TYPE.C_ANNOTATION_FREETEXT)
             {
                 viewerTool.PDFViewer.EnableZoom(true);
@@ -752,9 +860,9 @@ namespace ComPDFKit.Tool
             {
                 viewerTool.PDFViewer.Cursor = viewerTool.Cursor = Cursors.IBeam;
             }
-            else if(currentToolType == ToolType.ContentEdit)
+            else if (currentToolType == ToolType.ContentEdit)
             {
-                if(createContentEditType == CPDFEditType.EditText)
+                if (createContentEditType == CPDFEditType.EditText)
                     viewerTool.PDFViewer.Cursor = viewerTool.Cursor = Cursors.IBeam;
                 else
                     viewerTool.PDFViewer.Cursor = viewerTool.Cursor = viewerTool.DrawMoveTest(viewerTool.GetLastSelectedRect());
@@ -763,7 +871,7 @@ namespace ComPDFKit.Tool
             {
                 viewerTool.PDFViewer.Cursor = viewerTool.Cursor = Cursors.Arrow;
             }
-            
+
             if (currentToolType == ToolType.Customize)
             {
                 viewerTool.CleanCustomizeTool();
@@ -811,7 +919,7 @@ namespace ComPDFKit.Tool
                             annotHistory.CurrentParam = annotParam;
                             annotHistory.PDFDoc = cPDFDocument;
                             viewerTool.GetCPDFViewer().UndoManager.AddHistory(annotHistory);
-                            viewerTool.GetCPDFViewer().UpdateRenderFrame();
+                            viewerTool.GetCPDFViewer().UpdateAnnotFrame();
                             e.annotType = cPDFAnnotation.Type;
                             e.IsCreate = true;
                             dynamic expandData = new ExpandoObject();
@@ -827,7 +935,21 @@ namespace ComPDFKit.Tool
                     {
                         if (viewerTool.GetLastSelectedRect() != null)
                         {
-                            viewerTool.DrawEndTextEdit(viewerTool.GetLastSelectedRect());
+                            //Crop Save Processing
+                            if (!viewerTool.GetIsCropMode())
+                            {
+                                viewerTool.DrawEndTextEdit(viewerTool.GetLastSelectedRect());
+                            }
+                            else
+                            {
+                                if (isActiveCropping)
+                                {
+                                    CropSelectRect();
+                                    viewerTool.SetClipThickness();
+                                }
+                                //Originally saved cropping logic
+                            }
+
                             editSelected = false;
                         }
                         else
@@ -872,10 +994,17 @@ namespace ComPDFKit.Tool
                             }
                             else if (createContentEditType == CPDFEditType.EditText)
                             {
-                                e.IsCreate = viewerTool.DrawEndTest();
+                                if (viewerTool.CanAddTextEdit)
+                                {
+                                    e.IsCreate = viewerTool.DrawEndTest();
+                                }
                             }
                             else
                             {
+                                //Draw a box to select multiple boxes
+                                Rect rectFrameSelect = viewerTool.DrawEndFrameSelect();
+                                viewerTool.FrameSelectAddRect(rectFrameSelect);
+
                                 e.IsCreate = true;
                             }
                         }
@@ -898,6 +1027,25 @@ namespace ComPDFKit.Tool
             }
         }
 
+        /// <summary>
+        /// Create cropping logic
+        /// </summary>
+        public void CropSelectRect()
+        {
+            if (viewerTool.GetLastSelectedRect() != null)
+            {
+                if (viewerTool.GetIsCropMode())
+                {
+                    viewerTool.DrawEndTextEdit(viewerTool.GetLastSelectedRect());
+                }
+            }
+            viewerTool.DrawEndSelectText();
+            if (viewerTool.IsCanSave())
+            {
+                cPDFAnnotation = null;
+            }
+        }
+
         private void SaveCurrentAnnot()
         {
             viewerTool.SetIsCanSave(true);
@@ -932,7 +1080,7 @@ namespace ComPDFKit.Tool
                             annotHistory.CurrentParam = annotParam;
                             annotHistory.PDFDoc = cPDFDocument;
                             viewerTool.GetCPDFViewer().UndoManager.AddHistory(annotHistory);
-                            viewerTool.GetCPDFViewer().UpdateRenderFrame();
+                            viewerTool.GetCPDFViewer().UpdateAnnotFrame();
                             e.annotType = cPDFAnnotation.Type;
                             e.IsCreate = true;
                             dynamic expandData = new ExpandoObject();
@@ -968,7 +1116,7 @@ namespace ComPDFKit.Tool
                 {
                     case C_ANNOTATION_TYPE.C_ANNOTATION_LINE:
                         {
-                            if ((cPDFAnnotation as CPDFLineAnnotation).IsMersured())
+                            if ((cPDFAnnotation as CPDFLineAnnotation).IsMeasured())
                             {
                                 MeasureSetting measureSetting = viewerTool.GetMeasureSetting();
                                 if (viewerTool.GetMoveLength() > measureSetting.MoveDetectionLength)
@@ -979,7 +1127,7 @@ namespace ComPDFKit.Tool
                         }
                         break;
                     case C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON:
-                        if ((cPDFAnnotation as CPDFPolygonAnnotation).IsMersured())
+                        if ((cPDFAnnotation as CPDFPolygonAnnotation).IsMeasured())
                         {
                             DefaultSettingParam defSetting = viewerTool.GetDefaultSettingParam();
                             if (defSetting.IsCreateSquarePolygonMeasure)
@@ -1061,7 +1209,7 @@ namespace ComPDFKit.Tool
                         e.IsCreate = true;
                         e.annotType = C_ANNOTATION_TYPE.C_ANNOTATION_INK;
                         e.Data = GetAnnotExpandObject(annotation);
-                        if (e.mouseButtonEventArgs!=null)
+                        if (e.mouseButtonEventArgs != null)
                         {
                             MouseLeftButtonUpHandler?.Invoke(this, e);
                         }
@@ -1078,7 +1226,7 @@ namespace ComPDFKit.Tool
                         return;
                     case C_ANNOTATION_TYPE.C_ANNOTATION_LINE:
                         {
-                            if ((annotation as CPDFLineAnnotation).IsMersured())
+                            if ((annotation as CPDFLineAnnotation).IsMeasured())
                             {
                                 if (measurepoints.Count > 1)
                                 {
@@ -1122,31 +1270,52 @@ namespace ComPDFKit.Tool
                         break;
                     case C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON:
                         {
-                            if ((annotation as CPDFPolygonAnnotation).IsMersured())
+                            if (measurepoints.Count >= 3)
                             {
-                                List<CPoint> cPoints = new List<CPoint>();
-                                foreach (Point item in measurepoints)
+                                if ((annotation as CPDFPolygonAnnotation).IsMeasured())
                                 {
-                                    cPoints.Add(DataConversionForWPF.PointConversionForCPoint(DpiHelper.StandardPointToPDFPoint(item)));
-                                }
+                                    List<CPoint> cPoints = new List<CPoint>();
+                                    foreach (Point item in measurepoints)
+                                    {
+                                        cPoints.Add(DataConversionForWPF.PointConversionForCPoint(DpiHelper.StandardPointToPDFPoint(item)));
+                                    }
                                 (annotation as CPDFPolygonAnnotation).SetPoints(cPoints);
-                                (annotation as CPDFPolygonAnnotation).GetAreaMeasure().UpdateAnnotMeasure();
-                                PostMeasureInfo(this, annotation);
+                                    (annotation as CPDFPolygonAnnotation).GetAreaMeasure().UpdateAnnotMeasure();
+                                    PostMeasureInfo(this, annotation);
+                                }
+                            }
+                            else
+                            {
+                                annotation.RemoveAnnot();
+                                annotation = null;
+                                viewerTool.ClearDrawAnnot();
+                                return;
                             }
+
                         }
                         break;
                     case C_ANNOTATION_TYPE.C_ANNOTATION_POLYLINE:
                         {
-                            if ((annotation as CPDFPolylineAnnotation).IsMersured())
+                            if(measurepoints.Count>=3)
                             {
-                                List<CPoint> cPoints = new List<CPoint>();
-                                foreach (Point item in measurepoints)
+                                if ((annotation as CPDFPolylineAnnotation).IsMeasured())
                                 {
-                                    cPoints.Add(DataConversionForWPF.PointConversionForCPoint(DpiHelper.StandardPointToPDFPoint(item)));
+                                    List<CPoint> cPoints = new List<CPoint>();
+                                    foreach (Point item in measurepoints)
+                                    {
+                                        cPoints.Add(DataConversionForWPF.PointConversionForCPoint(DpiHelper.StandardPointToPDFPoint(item)));
+                                    }
+                               (annotation as CPDFPolylineAnnotation).SetPoints(cPoints);
+                                    (annotation as CPDFPolylineAnnotation).GetPerimeterMeasure().UpdateAnnotMeasure();
+                                    PostMeasureInfo(this, annotation);
                                 }
-                                (annotation as CPDFPolylineAnnotation).SetPoints(cPoints);
-                                (annotation as CPDFPolylineAnnotation).GetPerimeterMeasure().UpdateAnnotMeasure();
-                                PostMeasureInfo(this, annotation);
+                            }
+                            else
+                            {
+                                annotation.RemoveAnnot();
+                                annotation = null;
+                                viewerTool.ClearDrawAnnot();
+                                return;
                             }
                         }
                         break;
@@ -1167,6 +1336,7 @@ namespace ComPDFKit.Tool
                 {
                     switch (createAnnotType)
                     {
+                        case C_ANNOTATION_TYPE.C_ANNOTATION_LINK:
                         case C_ANNOTATION_TYPE.C_ANNOTATION_HIGHLIGHT:
                         case C_ANNOTATION_TYPE.C_ANNOTATION_UNDERLINE:
                         case C_ANNOTATION_TYPE.C_ANNOTATION_SQUIGGLY:
@@ -1208,7 +1378,7 @@ namespace ComPDFKit.Tool
                                     }
                                 }
 
-                                if(createAnnotType == C_ANNOTATION_TYPE.C_ANNOTATION_REDACT && textSelectInfo.PageSelectPointList.Count ==0)
+                                if (createAnnotType == C_ANNOTATION_TYPE.C_ANNOTATION_REDACT && textSelectInfo.PageSelectPointList.Count == 0)
                                 {
                                     viewerTool.GetCPDFViewer().UpdateAnnotFrame();
                                 }
@@ -1328,7 +1498,7 @@ namespace ComPDFKit.Tool
                     annotation = null;
                     return;
                 }
-                //CRect cRect = new CRect((float)rect.Left + annotation.GetBorderWidth(), (float)rect.Bottom - annotation.GetBorderWidth(), (float)rect.Right - annotation.GetBorderWidth(), (float)rect.Top + annotation.GetBorderWidth());
+
                 CRect cRect = new CRect(
                     (float)rect.Left,
                     (float)rect.Bottom,
@@ -1336,7 +1506,16 @@ namespace ComPDFKit.Tool
                     (float)rect.Top);
 
                 annotation.SetRect(cRect);
-                annotation.UpdateAp();
+                SaveSharpAnnotBoundText(annotation);
+                if (annotation.Type!=C_ANNOTATION_TYPE.C_ANNOTATION_TEXT)
+                {
+                    annotation.UpdateAp();
+                }
+                else
+                {
+                    CommonHelper.UpdateStickyAP(annotation as CPDFTextAnnotation);
+                }
+               
 
                 AnnotHistory annotHistory = ParamConverter.CreateHistory(annotation);
                 if (annotHistory == null)
@@ -1356,10 +1535,25 @@ namespace ComPDFKit.Tool
                 annotHistory.CurrentParam = currentParam;
                 annotHistory.Action = HistoryAction.Add;
                 annotHistory.PDFDoc = viewerTool.PDFViewer.GetDocument();
-                viewerTool.GetCPDFViewer().UndoManager.AddHistory(annotHistory);
 
                 viewerTool.ClearDrawAnnot();
-                viewerTool.GetCPDFViewer().UpdateRenderFrame();
+                viewerTool.GetCPDFViewer().UpdateAnnotFrame();
+                viewerTool.GetCPDFViewer().UndoManager.AddHistory(annotHistory);
+
+                if (annotation.Type == C_ANNOTATION_TYPE.C_ANNOTATION_TEXT && SaveEmptyStickyAnnot == false)
+                {
+                    BaseLayer baseLayer1 = viewerTool.GetCPDFViewer().GetViewForTag(viewerTool.GetCPDFViewer().GetAnnotViewTag());
+                    int checkPageIndex = currentParam.PageIndex;
+                    int checkAnnotIndex = currentParam.AnnotIndex;
+                    BaseAnnot selectAnnot = (baseLayer1 as AnnotLayer).GetSelectedAnnot(ref checkPageIndex, ref checkAnnotIndex);
+                    if (selectAnnot != null)
+                    {
+                        StickyNoteAnnot stickyAnnot = selectAnnot as StickyNoteAnnot;
+                        StickyNoteAnnot.StickyPopupClosed -= StickyAnnot_StickyPopupClosed;
+                        StickyNoteAnnot.StickyPopupClosed += StickyAnnot_StickyPopupClosed;
+                        stickyAnnot.PopStickyNote();
+                    }
+                }
                 {
                     e.annotType = annotation.Type;
                     e.IsCreate = true;
@@ -1369,9 +1563,71 @@ namespace ComPDFKit.Tool
                     expandData.AnnotParam = currentParam;
                     e.Data = expandData;
                 }
+
             }
         }
 
+        private void SaveSharpAnnotBoundText(CPDFAnnotation boundAnnot)
+        {
+            if (boundAnnot == null || boundAnnot.Page == null || boundAnnot.Page.IsValid() == false)
+            {
+                return;
+            }
+
+            if (boundAnnot.Type != C_ANNOTATION_TYPE.C_ANNOTATION_CIRCLE && boundAnnot.Type != C_ANNOTATION_TYPE.C_ANNOTATION_SQUARE)
+            {
+                return;
+            }
+
+            CPDFTextPage textPage=  boundAnnot.Page.GetTextPage();
+            if (textPage == null || textPage.IsValid()==false)
+            {
+                return;
+            }
+
+            string boundText = textPage.GetBoundedText(boundAnnot.GetRect());
+            if(string.IsNullOrEmpty(boundText)==false)
+            {
+                boundAnnot.SetContent(boundText);
+            }
+        }
+
+        private void StickyAnnot_StickyPopupClosed(object sender, EventArgs e)
+        {
+            StickyNoteAnnot.StickyPopupClosed -= StickyAnnot_StickyPopupClosed;
+            StickyNoteAnnot stickyAnnot = sender as StickyNoteAnnot;
+            if (stickyAnnot == null)
+            {
+                return;
+            }
+            AnnotData annotData = stickyAnnot.GetAnnotData();
+            AnnotParam currentParam = ParamConverter.AnnotConverter(viewerTool.GetCPDFViewer().GetDocument(), annotData.Annot);
+            AnnotHistory annotHistory = ParamConverter.CreateHistory(annotData.Annot);
+            string content = annotData.Annot.GetContent();
+            if (string.IsNullOrEmpty(content))
+            {
+                if (annotData.Annot.RemoveAnnot())
+                {
+                    viewerTool.ClearDrawAnnot();
+                    viewerTool.GetCPDFViewer().UpdateAnnotFrame();
+                    viewerTool.SelectedAnnotForIndex(-1, -1);
+                    annotHistory.CurrentParam = currentParam;
+                    annotHistory.Action = HistoryAction.Remove;
+                    annotHistory.PDFDoc = viewerTool.PDFViewer.GetDocument();
+                    viewerTool.GetCPDFViewer().UndoManager.AddHistory(annotHistory);
+                }
+
+                return;
+            }
+            AnnotParam previousParam = ParamConverter.AnnotConverter(viewerTool.GetCPDFViewer().GetDocument(), annotData.Annot);
+            previousParam.Content = string.Empty;
+            annotHistory.PreviousParam = previousParam;
+            annotHistory.CurrentParam = currentParam;
+            annotHistory.Action = HistoryAction.Update;
+            annotHistory.PDFDoc = viewerTool.PDFViewer.GetDocument();
+            viewerTool.GetCPDFViewer().UndoManager.AddHistory(annotHistory);
+        }
+
         internal void PostMeasureInfo(object sender, CPDFAnnotation rawAnnot)
         {
             if (rawAnnot == null)
@@ -1383,7 +1639,7 @@ namespace ComPDFKit.Tool
                 if (rawAnnot.Type == C_ANNOTATION_TYPE.C_ANNOTATION_LINE)
                 {
                     CPDFLineAnnotation lineAnnot = rawAnnot as CPDFLineAnnotation;
-                    if (lineAnnot.IsMersured() && lineAnnot.Points != null && lineAnnot.Points.Count() == 2)
+                    if (lineAnnot.IsMeasured() && lineAnnot.Points != null && lineAnnot.Points.Count() == 2)
                     {
                         CPDFDistanceMeasure lineMeasure = lineAnnot.GetDistanceMeasure();
                         CPDFMeasureInfo measureInfo = lineMeasure.MeasureInfo;
@@ -1416,7 +1672,7 @@ namespace ComPDFKit.Tool
                 if (rawAnnot.Type == C_ANNOTATION_TYPE.C_ANNOTATION_POLYLINE)
                 {
                     CPDFPolylineAnnotation polylineAnnot = rawAnnot as CPDFPolylineAnnotation;
-                    if (polylineAnnot.IsMersured() && polylineAnnot.Points != null && polylineAnnot.Points.Count() >= 2)
+                    if (polylineAnnot.IsMeasured() && polylineAnnot.Points != null && polylineAnnot.Points.Count() >= 2)
                     {
                         double totalInch = 0;
                         for (int i = 0; i < polylineAnnot.Points.Count - 1; i++)
@@ -1456,7 +1712,7 @@ namespace ComPDFKit.Tool
                 if (rawAnnot.Type == C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON)
                 {
                     CPDFPolygonAnnotation polygonAnnot = rawAnnot as CPDFPolygonAnnotation;
-                    if (polygonAnnot.IsMersured() && polygonAnnot.Points != null && polygonAnnot.Points.Count() >= 2)
+                    if (polygonAnnot.IsMeasured() && polygonAnnot.Points != null && polygonAnnot.Points.Count() >= 2)
                     {
                         double totalInch = 0;
                         for (int i = 0; i < polygonAnnot.Points.Count - 1; i++)
@@ -1667,7 +1923,7 @@ namespace ComPDFKit.Tool
                 }
             }
             viewerTool.ClearDrawAnnot();
-            viewerTool.GetCPDFViewer().UpdateRenderFrame();
+            viewerTool.GetCPDFViewer().UpdateAnnotFrame();
             InkAnnotHistory inkAnnotHistory = new InkAnnotHistory();
             AnnotParam annotParam = ParamConverter.AnnotConverter(viewerTool.PDFViewer.GetDocument(), cPDFAnnotation);
             annotParam.AnnotIndex = cPDFAnnotation.Page.GetAnnotCount() - 1;
@@ -1679,6 +1935,26 @@ namespace ComPDFKit.Tool
 
         #endregion
 
+        /// <summary>
+        /// Set mouse pattern when creating content editing
+        /// </summary>
+        /// <param name="AddTextEditCursor">add text</param>
+        /// <param name="AddImageEditCursor">add image</param>
+        public void SetAddContentEditCursor(Cursor AddTextEditCursor, Cursor AddImageEditCursor)
+        {
+            if (AddTextEditCursor == null)
+            {
+                AddTextEditCursor = Cursors.IBeam;
+            }
+            if (AddImageEditCursor == null)
+            {
+                AddImageEditCursor = Cursors.Arrow;
+            }
+            this.addTextEditCursor = AddTextEditCursor;
+            this.addImageEditCursor = AddImageEditCursor;
+
+        }
+
         private void ViewerTool_MouseMoveHandler(object sender, MouseEventObject e)
         {
             if (viewerTool == null)
@@ -1733,7 +2009,7 @@ namespace ComPDFKit.Tool
                     if (currentToolType == ToolType.CreateAnnot)
                     {
                         if (!viewerTool.PDFViewer.GetIsShowStampMouse())
-                        { 
+                        {
                             // Annotation drawing only occurs if the mouse is not set to stamp/data application mode.// Annotation drawing only occurs if the mouse is not set to stamp/data application mode.
                             viewerTool.MoveDrawAnnot();
                         }
@@ -1793,12 +2069,14 @@ namespace ComPDFKit.Tool
                 if (createContentEditType != CPDFEditType.EditImage)
                 {
                     Cursor cursor = Cursors.Arrow;
+                    MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(viewerTool.PDFViewer.GetViewForTag(viewerTool.MultiSelectedRectViewTag));
+
                     if (viewerTool.GetLastSelectedRect() != null)
                     {
                         if (editSelected)
                         {
                             viewerTool.DrawMoveTextEdit(viewerTool.GetLastSelectedRect(), clickEditSelected);
-                            if(clickEditSelected)
+                            if (clickEditSelected)
                                 cursor = Cursors.IBeam;
                             else
                                 cursor = viewerTool.DrawMoveTest(viewerTool.GetLastSelectedRect());
@@ -1810,19 +2088,60 @@ namespace ComPDFKit.Tool
                     }
                     else
                     {
-                        viewerTool.HideDrawSelectedMultiRect();
                         cursor = viewerTool.DrawMoveTest(viewerTool.GetLastSelectedRect());
+                        if (multiSelectedRect == null || multiSelectedRect.Children.Count == 0)
+                        {
+                            //Selection of mobile drawing logic
+                            if (e.mouseButtonEventArgs.LeftButton == MouseButtonState.Pressed && createContentEditType == CPDFEditType.None)
+                            {
+                                viewerTool.DrawMoveFrameSelect();
+                            }
+                        }
+
                     }
 
                     if (cursor == Cursors.Arrow && createContentEditType == CPDFEditType.EditText)
                     {
-                        cursor = Cursors.IBeam;
+                        cursor = addTextEditCursor;
                     }
                     viewerTool.Cursor = cursor;
                     viewerTool.PDFViewer.Cursor = cursor;
                 }
                 else
                 {
+                    Cursor cursor = Cursors.Arrow;
+                    MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(viewerTool.PDFViewer.GetViewForTag(viewerTool.MultiSelectedRectViewTag));
+
+                    if (viewerTool.GetLastSelectedRect() != null)
+                    {
+                        if (editSelected)
+                        {
+                            viewerTool.DrawMoveTextEdit(viewerTool.GetLastSelectedRect(), clickEditSelected);
+                            if (clickEditSelected)
+                                cursor = Cursors.IBeam;
+                            else
+                                cursor = viewerTool.DrawMoveTest(viewerTool.GetLastSelectedRect());
+                        }
+                        else
+                        {
+                            cursor = viewerTool.DrawMoveTest(viewerTool.GetLastSelectedRect());
+                        }
+                    }
+                    else
+                    {
+                        cursor = viewerTool.DrawMoveTest(viewerTool.GetLastSelectedRect());
+                    }
+
+                    if (cursor == Cursors.Arrow && createContentEditType == CPDFEditType.EditText)
+                    {
+                        cursor = Cursors.IBeam;
+                    }
+                    if (cursor == Cursors.Arrow && createContentEditType == CPDFEditType.EditImage)
+                    {
+                        cursor = addImageEditCursor;
+                    }
+                    viewerTool.Cursor = cursor;
+                    viewerTool.PDFViewer.Cursor = cursor;
                     //viewerTool.Cursor = Cursors.None;
                     //viewerTool.PDFViewer.Cursor = Cursors.None;
                 }
@@ -1882,6 +2201,7 @@ namespace ComPDFKit.Tool
                                                     viewerTool.EndDrawAnnot();
                                                 }
                                                 break;
+                                            case C_ANNOTATION_TYPE.C_ANNOTATION_LINK:
                                             case C_ANNOTATION_TYPE.C_ANNOTATION_REDACT:
                                                 if (viewerTool.IsText())
                                                 {
@@ -1896,7 +2216,7 @@ namespace ComPDFKit.Tool
                                                     CPDFLineAnnotation LineAnnotation = (cPDFAnnotation as CPDFLineAnnotation);
                                                     if (LineAnnotation != null)
                                                     {
-                                                        if (LineAnnotation.IsMersured())
+                                                        if (LineAnnotation.IsMeasured())
                                                         {
                                                             cansave = false;
                                                         }
@@ -1908,10 +2228,10 @@ namespace ComPDFKit.Tool
                                                 {
                                                     bool cansave = true;
                                                     CPDFPolygonAnnotation PolyAnnotation = (cPDFAnnotation as CPDFPolygonAnnotation);
-                                                    PolyAnnotation?.IsMersured();
+                                                    PolyAnnotation?.IsMeasured();
                                                     if (PolyAnnotation != null)
                                                     {
-                                                        if (PolyAnnotation.IsMersured())
+                                                        if (PolyAnnotation.IsMeasured())
                                                         {
                                                             cansave = false;
                                                         }
@@ -1923,10 +2243,10 @@ namespace ComPDFKit.Tool
                                                 {
                                                     bool cansave = true;
                                                     CPDFPolylineAnnotation PolyAnnotation = (cPDFAnnotation as CPDFPolylineAnnotation);
-                                                    PolyAnnotation?.IsMersured();
+                                                    PolyAnnotation?.IsMeasured();
                                                     if (PolyAnnotation != null)
                                                     {
-                                                        if (PolyAnnotation.IsMersured())
+                                                        if (PolyAnnotation.IsMeasured())
                                                         {
                                                             cansave = false;
                                                         }
@@ -1941,7 +2261,7 @@ namespace ComPDFKit.Tool
                                     else
                                     {
                                         viewerTool.MultipleClick();
-                                        e.IsDrawing=true;
+                                        e.IsDrawing = true;
                                     }
                                     break;
                                 case 2:
@@ -1960,6 +2280,7 @@ namespace ComPDFKit.Tool
                         {
                             cPDFAnnotation = viewerTool.StartDrawWidget(createWidgetType);
                             viewerTool.CreateDefaultWidget(cPDFAnnotation, createWidgetType, null);
+                            viewerTool?.InvokeWidgetCreated(cPDFAnnotation);
                         }
                         else if (currentToolType == ToolType.Pan || currentToolType == ToolType.Viewer)
                         {
@@ -2007,7 +2328,7 @@ namespace ComPDFKit.Tool
                         if (list.Contains(e.annotType))
                         {
                             viewerTool.CleanSelectedRect();
-                            if (!e.IsMersured||!list.Contains(createAnnotType))
+                            if (!e.IsMersured || !list.Contains(createAnnotType))
                             {
                                 viewerTool.StartDrawEditAnnot();
                             }
@@ -2045,6 +2366,15 @@ namespace ComPDFKit.Tool
                         clickEditSelected = true;
                         switch ((e.mouseButtonEventArgs as MouseButtonEventArgs).ClickCount)
                         {
+                            case 1:
+                                if (viewerTool.GetIsCropMode())
+                                {
+                                    //Preconditions for determining crop acquisition points
+                                    viewerTool.HandleTextSelectClick(viewerTool.GetLastSelectedRect(), true);
+                                    clickEditSelected = false;
+                                    MouseLeftButtonDownHandler?.Invoke(this, e);
+                                }
+                                break;
                             case 2:
                                 viewerTool.HandleTextSelectClick(viewerTool.GetLastSelectedRect(), true);
                                 clickEditSelected = false;
@@ -2063,8 +2393,19 @@ namespace ComPDFKit.Tool
                         viewerTool.HideDrawSelectedMultiRect();
                         if (viewerTool.GetLastSelectedRect() != null)
                         {
+                            viewerTool.DrawEndFrameSelect();
                             Point point = Mouse.GetPosition(viewerTool);
-                            PointControlType pointControlType = viewerTool.GetLastSelectedRect().GetHitControlIndex(point);
+                            PointControlType pointControlType = PointControlType.None;
+                            if (viewerTool.GetIsCropMode())
+                            {
+                                //Crop acquisition point judgment
+                                pointControlType = viewerTool.GetLastSelectedRect().GetHitCropControlIndex(point);
+                            }
+                            else
+                            {
+                                pointControlType = viewerTool.GetLastSelectedRect().GetHitControlIndex(point);
+                            }
+
                             EditAreaObject editAreaObject = viewerTool.GetEditAreaObjectForRect(viewerTool.GetLastSelectedRect());
                             if (pointControlType != PointControlType.None &&
                                 (editAreaObject.cPDFEditArea.Type == CPDFEditType.EditImage || pointControlType != PointControlType.Body))
@@ -2094,12 +2435,23 @@ namespace ComPDFKit.Tool
                                     default:
                                         break;
                                 }
-                                viewerTool.DrawStartTextEdit(viewerTool.GetLastSelectedRect());
+                                if (e.mouseButtonEventArgs.LeftButton == MouseButtonState.Pressed)
+                                {
+                                    viewerTool.DrawStartTextEdit(viewerTool.GetLastSelectedRect(), editAreaObject);
+                                }
+
                                 clickEditSelected = false;
                             }
                         }
                         else
                         {
+                            //If it is multiple selection, do not create a new input box
+                            MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(viewerTool.PDFViewer.GetViewForTag(viewerTool.MultiSelectedRectViewTag));
+                            if (multiSelectedRect != null && multiSelectedRect.Children.Count > 0)
+                            {
+                                viewerTool.PDFViewer.UpdateRenderFrame();
+                                return;
+                            }
                             Point point = Mouse.GetPosition(viewerTool);
                             viewerTool.GetCPDFViewer().GetPointPageInfo(point, out int index, out Rect paintRect, out Rect pageBound);
                             if (index < 0)
@@ -2109,7 +2461,18 @@ namespace ComPDFKit.Tool
                             }
                             if (createContentEditType == CPDFEditType.EditText)
                             {
-                                viewerTool.DrawTest(pageBound, index);
+                                if (viewerTool.CanAddTextEdit)
+                                {
+                                    viewerTool.DrawTest(pageBound, index);
+                                }
+                            }
+                            if (createContentEditType == CPDFEditType.None)
+                            {
+                                viewerTool.DrawFrameSelect();
+                            }
+                            else
+                            {
+                                viewerTool.DrawEndFrameSelect();
                             }
                             clickEditSelected = false;
                         }

+ 38 - 13
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.Annot.cs

@@ -322,7 +322,7 @@ namespace ComPDFKit.Tool
             {
                 return;
             }
-            (baseLayer as CreateAnnotTool).MultipleClick(point);
+            (baseLayer as CreateAnnotTool).MultipleClick(point, index);
         }
 
         public void SetScrollAndZoomTypeForAnnot(C_ANNOTATION_TYPE annotType)
@@ -462,7 +462,7 @@ namespace ComPDFKit.Tool
                     List<CRect> coreRectList = new List<CRect>();
                     foreach (Rect copyRect in pageSelectRectList)
                     {
-                        coreRectList.Add(new CRect((float)copyRect.Left, (float)copyRect.Top, (float)copyRect.Right, (float)copyRect.Bottom));
+                        coreRectList.Add(new CRect((float)copyRect.Left, (float)copyRect.Bottom, (float)copyRect.Right, (float)copyRect.Top));
                     }
                     CreateDefaultAnnot(annotCore, annotType, null);
                     string markupContent = textSelectInfo.PageSelectText[pageIndex];
@@ -557,6 +557,17 @@ namespace ComPDFKit.Tool
                                 historyGroup.Histories.Add(redactHistory);
                             }
                             break;
+                        case C_ANNOTATION_TYPE.C_ANNOTATION_LINK:
+                            {
+                                LinkAnnotHistory linkHistory = new LinkAnnotHistory();
+                                AnnotParam annotParam = ParamConverter.AnnotConverter(cPDFDocument, annotCore);
+                                linkHistory.Action = HistoryAction.Add;
+                                linkHistory.CurrentParam = (LinkParam)annotParam;
+                                linkHistory.PDFDoc = cPDFDocument;
+                                linkHistory.Action = HistoryAction.Add;
+                                historyGroup.Histories.Add(linkHistory);
+                            }
+                            break;
                         default:
                             break;
                     }
@@ -636,7 +647,7 @@ namespace ComPDFKit.Tool
                 {
                     return;
                 }
-                AnnotData annotData = currentAnnot.GetAnnotData(); 
+                AnnotData annotData = currentAnnot.GetAnnotData();
 
                 if (annotData.PaintRect == Rect.Empty)
                 {
@@ -676,7 +687,7 @@ namespace ComPDFKit.Tool
                     double Height = DpiHelper.PDFNumToStandardNum(drawRect.height());
                     textui = new TextBox();
                     textui.Name = "PdfViewerTextBox";
-                    textBorder = new Border();
+                    textBorder = new DashedBorder();
                     textBorder.Child = textui;
                     textBorder.MinWidth = Width * PDFViewer.GetZoom();
                     textBorder.MinHeight = Height * PDFViewer.GetZoom();
@@ -714,15 +725,27 @@ namespace ComPDFKit.Tool
 
                     textBorder.Padding = new Thickness(0);
                     textBorder.BorderBrush = new SolidColorBrush(borderColor);
-                    textBorder.BorderThickness = new Thickness(DpiHelper.PDFNumToStandardNum(textWidget.GetBorderWidth() * annotData.CurrentZoom));
+                    double rawWidth = textWidget.GetBorderWidth();
+                    double drawWidth = DpiHelper.PDFNumToStandardNum(rawWidth * annotData.CurrentZoom);
+                    textBorder.BorderThickness = new Thickness(drawWidth);
                     textui.BorderThickness = new Thickness(0);
                     textui.Text = textWidget.Content;
+                    if (textWidget.BorderStyle != C_BORDER_STYLE.BS_SOLID && textWidget.Dash != null && textWidget.Dash.Length > 0)
+                    {
+                        //补充保存虚线样式
+                        DashedBorder dashBorder = textBorder as DashedBorder;
+                        DoubleCollection dashCollection = new DoubleCollection();
+                        foreach (float num in textWidget.Dash)
+                        {
+                            dashCollection.Add(num);
+                        }
+                        dashBorder?.DrawDashBorder(true, drawWidth, rawWidth, dashCollection);
+                    }
 
-                    string fontName = string.Empty;
-                    string fontFamily = string.Empty;
-                    CPDFFont.GetFamilyStyleName(textWidget.FreeTextDa.FontName, ref fontFamily, ref fontName);
-                    textui.FontFamily = new FontFamily(fontFamily);
-
+                    //string fontName = string.Empty;
+                    //string fontFamily = string.Empty;
+                    //CPDFFont.GetFamilyStyleName(textWidget.FreeTextDa.FontName, ref fontFamily, ref fontName);
+                    textui.FontFamily = new FontFamily(textWidget.FreeTextDa.FontName + ",Microsoft YaHei");
                     textui.AcceptsReturn = true;
                     textui.TextWrapping = TextWrapping.Wrap;
                     textui.TextAlignment = TextAlignment.Left;
@@ -830,7 +853,7 @@ namespace ComPDFKit.Tool
                                 viewer.UpdateAnnotFrame();
                             }
                             RemovePopTextUI();
-                        } 
+                        }
                     };
 
                     BaseLayer createAnnotTool = PDFViewer?.GetView(createAnnotTag) as CreateAnnotTool;
@@ -900,8 +923,10 @@ namespace ComPDFKit.Tool
                     textBorder.BorderBrush = new SolidColorBrush(borderColor);
                     textBorder.BorderThickness = new Thickness(DpiHelper.PDFNumToStandardNum(textWidget.GetBorderWidth() * annotData.CurrentZoom));
                     textui.BorderThickness = new Thickness(0);
-                    textui.Text = textWidget.Content;
-
+                    if (string.IsNullOrEmpty(textui.Text) == false)
+                    {
+                        textui.CaretIndex = textui.Text.Length;
+                    }
                     textui.FontFamily = new FontFamily(GetFontName(textAttribute.FontName));
                     textui.FontWeight = IsBold(textAttribute.FontName) ? FontWeights.Bold : FontWeights.Normal;
                     textui.FontStyle = IsItalic(textAttribute.FontName) ? FontStyles.Italic : FontStyles.Normal;

Diff do ficheiro suprimidas por serem muito extensas
+ 1136 - 0
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.AnnotSelector.cs


+ 161 - 18
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.Command.cs

@@ -16,6 +16,7 @@ using ComPDFKitViewer.Widget;
 using System;
 using System.Collections.Generic;
 using System.Dynamic;
+using System.Linq;
 using System.Text;
 using System.Windows;
 using System.Windows.Input;
@@ -161,10 +162,19 @@ namespace ComPDFKit.Tool
                         CheckViewerCommandStatus(uiCommand, e);
                         break;
                     case ToolType.CreateAnnot:
-                    case ToolType.WidgetEdit:
                     case ToolType.Pan:
                         CheckAnnotCommandStatus(uiCommand, e);
                         break;
+                    case ToolType.WidgetEdit:
+                        if (AnnotSelectCommandSupport(uiCommand))
+                        {
+                            e.CanExecute = true;
+                        }
+                        else
+                        {
+                            CheckAnnotCommandStatus(uiCommand, e);
+                        }
+                        break;
                     case ToolType.Customize:
                         break;
                     case ToolType.ContentEdit:
@@ -206,10 +216,19 @@ namespace ComPDFKit.Tool
                             ExecuteViewerCommand(uiCommand);
                             break;
                         case ToolType.CreateAnnot:
-                        case ToolType.WidgetEdit:
                         case ToolType.Pan:
                             ExecuteAnnotCommand(uiCommand);
                             break;
+                        case ToolType.WidgetEdit:
+                            if(AnnotSelectCommandSupport(uiCommand))
+                            {
+                                AnnotSelectCommandExecute(uiCommand);
+                            }
+                            else
+                            {
+                                ExecuteAnnotCommand(uiCommand);
+                            }
+                            break;
                         case ToolType.ContentEdit:
                             {
                                 ExecutePDFEditCommand(uiCommand, out editType);
@@ -225,8 +244,8 @@ namespace ComPDFKit.Tool
                     commandData.CurrentParam = PasteParam;
                     CommandExecutedHandler?.Invoke(this, commandData);
                 }
-                catch (Exception ex) 
-                { 
+                catch (Exception ex)
+                {
 
                 }
             }
@@ -252,6 +271,12 @@ namespace ComPDFKit.Tool
                         {
                             e.CanExecute = true;
                         }
+                        //Add multi status
+                        MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(MultiSelectedRectViewTag));
+                        if (multiSelectedRect != null && multiSelectedRect.Children.Count > 0)
+                        {
+                            e.CanExecute = true;
+                        }
                         break;
                     }
                 case "Paste":
@@ -465,6 +490,70 @@ namespace ComPDFKit.Tool
                         }
                     }
                 }
+                else
+                {
+                    //Add multi status
+                    MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(MultiSelectedRectViewTag));
+                    if (multiSelectedRect != null && multiSelectedRect.Children.Count > 0)
+                    {
+                        foreach (SelectedRect selectedRect in multiSelectedRect.Children)
+                        {
+                            EditAreaObject editAreaObject = GetEditAreaObjectListForRect(selectedRect);
+                            if (editAreaObject != null)
+                            {
+
+                                PDFEditCommandData commandData = new PDFEditCommandData();
+                                if (editAreaObject.cPDFEditArea.Type == CPDFEditType.EditText)
+                                {
+                                    editType = CPDFEditType.EditText;
+                                    CPDFEditTextArea editTextArea = editAreaObject.cPDFEditArea as CPDFEditTextArea;
+                                    commandData.TextContent = editTextArea.SelectText;
+                                    if (!string.IsNullOrEmpty(commandData.TextContent))
+                                    {
+                                        CPDFEditPage editPage = editAreaObject.cPDFEditPage;
+                                        commandData.EditType = CPDFEditType.EditText;
+                                        commandData.EditAreaCopied = editPage.CopyEditArea(editAreaObject.cPDFEditArea);
+                                        if (commandData.EditAreaCopied)
+                                        {
+                                            List<CPDFCopyEditArea> copyList = editPage.GetCopyEditAreaList();
+                                            CPDFCopyEditArea CopyArea = copyList[copyList.Count - 1];
+                                            commandData.TextContent = CopyArea.GetCopyTextAreaContent();
+                                            commandData.CopyArea = CopyArea;
+                                            commandData.EditPage = editPage;
+                                        }
+                                    }
+                                    try
+                                    {
+                                        Clipboard.Clear();
+                                        Clipboard.SetText(commandData.TextContent);
+                                        Clipboard.Flush();
+                                    }
+                                    catch (Exception)
+                                    {
+
+                                    }
+                                    commandData.PDFRect = DataConversionForWPF.CRectConversionForRect(editAreaObject.cPDFEditArea.GetFrame());
+                                    lastPDFEditArgsList.Add(commandData);
+                                }
+                                if (editAreaObject.cPDFEditArea.Type == CPDFEditType.EditImage)
+                                {
+                                    editType = CPDFEditType.EditImage;
+                                    CPDFEditPage editPage = editAreaObject.cPDFEditPage;
+                                    commandData.PDFRect = DataConversionForWPF.CRectConversionForRect(editAreaObject.cPDFEditArea.GetFrame());
+                                    commandData.EditAreaCopied = editPage.CopyEditArea(editAreaObject.cPDFEditArea);
+                                    commandData.EditType = CPDFEditType.EditImage;
+                                    if (commandData.EditAreaCopied)
+                                    {
+                                        List<CPDFCopyEditArea> copyList = editPage.GetCopyEditAreaList();
+                                        commandData.CopyArea = copyList[copyList.Count - 1];
+                                        commandData.EditPage = editPage;
+                                        lastPDFEditArgsList.Add(commandData);
+                                    }
+                                }
+                            }
+                        } 
+                    }
+                }
             }
             catch
             {
@@ -487,35 +576,77 @@ namespace ComPDFKit.Tool
                     editType = CPDFEditType.EditText;
                     CPDFEditTextArea editTextArea = currentEditAreaObject.cPDFEditArea as CPDFEditTextArea;
                     string selectContent = editTextArea.SelectText;
-                    if (string.IsNullOrEmpty(selectContent) == false && !selectAllCharsForLine)
+                    if (!selectAllCharsForLine)
                     {
                         DeleteChars();
-                        EndEdit();
                     }
                     else
                     {
-                        if (string.IsNullOrEmpty(selectContent))
-                        {
-                            editTextArea.SelectAllChars();
-                        }
                         RemoveTextBlock();
                     }
-                    PDFEditHistory deleteHistory = new PDFEditHistory();
-                    deleteHistory.EditPage = currentEditAreaObject.cPDFEditPage;
-                    deleteHistory.PageIndex = currentEditAreaObject.PageIndex;
-                    groupHistory.Histories.Add(deleteHistory);
                 }
+
                 if (currentEditAreaObject.cPDFEditArea.Type == CPDFEditType.EditImage)
                 {
                     editType = CPDFEditType.EditImage;
                     RemoveImageBlock();
                 }
 
-                //After removing the data, you need to get the data again.
-                PDFViewer.UpdateRenderFrame();
                 if (PDFViewer != null && PDFViewer.UndoManager != null)
                 {
                     PDFViewer.UndoManager.AddHistory(groupHistory);
+                    //After removing the data, you need to get the data again.
+                    PDFViewer.UpdateRenderFrame();
+                }
+            }
+            else
+            {
+                //Add multi status
+                MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(MultiSelectedRectViewTag));
+                if (multiSelectedRect != null && multiSelectedRect.Children.Count > 0)
+                {
+                    List<EditAreaObject> editAreaObjectList = new List<EditAreaObject>();
+                    foreach (SelectedRect selectedRect in multiSelectedRect.Children)
+                    {
+                        EditAreaObject editAreaObject = GetEditAreaObjectListForRect(selectedRect);
+                        editAreaObjectList.Add(editAreaObject);
+                    }
+
+                    if (editAreaObjectList != null && editAreaObjectList.Count > 0)
+                    {
+                        editAreaObjectList = editAreaObjectList.OrderByDescending(x => x.EditAreaIndex).ToList();
+                        GroupHistory groupHistory = new GroupHistory();
+                        foreach (EditAreaObject editareaobject in editAreaObjectList)
+                        {
+                            PDFEditHistory editHistory = new PDFEditHistory();
+                            editHistory.EditPage = editareaobject.cPDFEditPage;
+                            editHistory.PageIndex = editareaobject.PageIndex;
+                            groupHistory.Histories.Add(editHistory);
+                            if (editareaobject.cPDFEditArea.Type == CPDFEditType.EditText)
+                            {
+                                editType = CPDFEditType.EditText;
+                                CPDFEditTextArea editTextArea = editareaobject.cPDFEditArea as CPDFEditTextArea;
+                                string selectContent = editTextArea.SelectText;
+                                RemoveTextBlock(editareaobject);
+                            }
+
+                            if (editareaobject.cPDFEditArea.Type == CPDFEditType.EditImage)
+                            {
+                                editType = CPDFEditType.EditImage;
+                                RemoveImageBlock(editareaobject);
+                            }
+                        }
+
+                        if (PDFViewer != null && PDFViewer.UndoManager != null)
+                        {
+                            PDFViewer.UndoManager.AddHistory(groupHistory);
+                            //After removing the data, you need to get the data again.
+                            PDFViewer.UpdateRenderFrame();
+                        }
+                    }
+
+                    CleanSelectedMultiRect();
+                    OpenSelectedMulti(false);
                 }
             }
         }
@@ -814,7 +945,6 @@ namespace ComPDFKit.Tool
 
         #endregion
 
-
         #region Annot
 
         private bool CheckCacheHitTestAnnot(string cmdName = "")
@@ -1099,7 +1229,7 @@ namespace ComPDFKit.Tool
                             CPDFAnnotation cPDFAnnotation = cPDFPage.CreateAnnot(item.CurrentType);
                             CreateDefaultAnnot(cPDFAnnotation, item.CurrentType, item);
                             cPDFAnnotation.SetRect(setRect);
-                            cPDFAnnotation.UpdateAp();
+                            CommonHelper.UpdateStickyAP(cPDFAnnotation as CPDFTextAnnotation);
                             AnnotParam annotParam = ParamConverter.AnnotConverter(cPDFDocument, cPDFAnnotation);
                             (annotHistory as StickyNoteAnnotHistory).CurrentParam = (StickyNoteParam)annotParam;
                         }
@@ -1285,6 +1415,13 @@ namespace ComPDFKit.Tool
                             CPDFAnnotation cPDFAnnotation = cPDFPage.CreateAnnot(item.CurrentType);
                             CreateDefaultAnnot(cPDFAnnotation, item.CurrentType, item);
                             cPDFAnnotation.SetRect(setRect);
+                            CPDFTextPage textPage = cPDFPage.GetTextPage();
+                            if (textPage != null)
+                            {
+                                string newContent = textPage.GetBoundedText(setRect);
+                                cPDFAnnotation.SetContent(newContent);
+                            }
+
                             cPDFAnnotation.UpdateAp();
                             AnnotParam annotParam = ParamConverter.AnnotConverter(cPDFDocument, cPDFAnnotation);
                             (annotHistory as SquareAnnotHistory).CurrentParam = (SquareParam)annotParam;
@@ -1329,6 +1466,12 @@ namespace ComPDFKit.Tool
                             CPDFAnnotation cPDFAnnotation = cPDFPage.CreateAnnot(item.CurrentType);
                             CreateDefaultAnnot(cPDFAnnotation, item.CurrentType, item);
                             cPDFAnnotation.SetRect(setRect);
+                            CPDFTextPage textPage = cPDFPage.GetTextPage();
+                            if (textPage != null)
+                            {
+                                string newContent = textPage.GetBoundedText(setRect);
+                                cPDFAnnotation.SetContent(newContent);
+                            }
                             cPDFAnnotation.UpdateAp();
                             AnnotParam annotParam = ParamConverter.AnnotConverter(cPDFDocument, cPDFAnnotation);
                             (annotHistory as CircleAnnotHistory).CurrentParam = (CircleParam)annotParam;

+ 2 - 0
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.CustomizeTool.cs

@@ -70,9 +70,11 @@ namespace ComPDFKit.Tool
             CPDFDocument cPDFDocument = PDFViewer.GetDocument();
             CPDFPage cPDFPage = cPDFDocument.PageAtIndex(index);
             BaseLayer layer = PDFViewer.GetViewForTag(PDFViewer.GetAnnotViewTag());
+            (baseLayer as CreateCustomizeTool).ErasePageIndex = -1;
             if (ToolType == CustomizeToolType.kErase)
             {
                 (baseLayer as CreateCustomizeTool).SetAnnotLayer(layer as AnnotLayer);
+                (baseLayer as CreateCustomizeTool).ErasePageIndex = index;
             }
            (baseLayer as CreateCustomizeTool).StartDraw(point, cPDFPage, paintRect, pageBound, ToolType);
         }

+ 29 - 30
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.DataMethod.cs

@@ -183,6 +183,10 @@ namespace ComPDFKit.Tool
             }
 
             TextAnnotation.SetColor(StickyNoteParamDef.StickyNoteColor);
+            if(string.IsNullOrEmpty(StickyNoteParamDef.IconName)==false)
+            {
+                TextAnnotation.SetIconName(StickyNoteParamDef.IconName);
+            }
             DefaultAnnot(cPDFAnnotation, StickyNoteParamDef);
         }
 
@@ -254,7 +258,6 @@ namespace ComPDFKit.Tool
             {
                 freeTextAnnotation.SetLineColor(FreeTextParam.LineColor);
             }
-            freeTextAnnotation.SetBorderWidth(1);
             freeTextAnnotation.SetTransparency(FreeTextParam.Transparency);
             freeTextAnnotation.SetLineWidth((float)FreeTextParam.LineWidth);
 
@@ -262,6 +265,13 @@ namespace ComPDFKit.Tool
             {
                 freeTextAnnotation.SetBgColor(FreeTextParam.BgColor);
             }
+
+            if(FreeTextParam.Dash!=null && FreeTextParam.Dash.Length>0)
+            {
+                //补充保存虚线样式
+                freeTextAnnotation.SetBorderStyle(C_BORDER_STYLE.BS_DASHDED, FreeTextParam.Dash);
+            }
+
             CTextAttribute textAttr = new CTextAttribute();
             textAttr.FontColor = FreeTextParam.FontColor;
             textAttr.FontSize = (float)FreeTextParam.FontSize;
@@ -625,7 +635,16 @@ namespace ComPDFKit.Tool
             }
 
             InkAnnotation.SetThickness((float)inkParam.Thickness);
-            (cPDFAnnotation as CPDFInkAnnotation).SetInkPath(inkParam.InkPath);
+            CPDFInkAnnotation inkAnnot = cPDFAnnotation as CPDFInkAnnotation;
+            inkAnnot.SetInkPath(inkParam.InkPath);
+            if(inkParam.Dash!=null && inkParam.Dash.Length>0)
+            {
+                inkAnnot.SetBorderStyle(C_BORDER_STYLE.BS_DASHDED,inkParam.Dash);
+            }
+            else
+            {
+                inkAnnot.SetBorderStyle(C_BORDER_STYLE.BS_SOLID, new float[0]);
+            }
             DefaultAnnot(cPDFAnnotation, inkParam);
         }
 
@@ -720,7 +739,7 @@ namespace ComPDFKit.Tool
             {
                 return;
             }
-            if (!LineAnnotation.IsMersured() && annotParam != null)
+            if (!LineAnnotation.IsMeasured() && annotParam != null)
             {
                 return;
             }
@@ -783,7 +802,7 @@ namespace ComPDFKit.Tool
             {
                 return;
             }
-            if (!PolyAnnotation.IsMersured() && annotParam != null)
+            if (!PolyAnnotation.IsMeasured() && annotParam != null)
             {
                 return;
             }
@@ -850,7 +869,7 @@ namespace ComPDFKit.Tool
             {
                 return;
             }
-            if (!PolyAnnotation.IsMersured() && annotParam != null)
+            if (!PolyAnnotation.IsMeasured() && annotParam != null)
             {
                 return;
             }
@@ -999,11 +1018,7 @@ namespace ComPDFKit.Tool
             CTextAttribute textAttr = new CTextAttribute();
             textAttr.FontColor = pushButtonParam.FontColor;
             textAttr.FontSize = (float)pushButtonParam.FontSize;
-            FontType checkFontType = CFontNameHelper.GetFontType(pushButtonParam.FontName);
-            textAttr.FontName = CFontNameHelper.ObtainFontName(
-                checkFontType == FontType.Unknown ? FontType.Helvetica : checkFontType,
-                pushButtonParam.IsBold,
-                 pushButtonParam.IsItalic);
+            textAttr.FontName = pushButtonParam.FontName;
             widget.SetTextAttribute(textAttr);
 
             if (!string.IsNullOrEmpty(pushButtonParam.FieldName))
@@ -1156,11 +1171,7 @@ namespace ComPDFKit.Tool
             CTextAttribute textAttr = new CTextAttribute();
             textAttr.FontColor = textBoxParam.FontColor;
             textAttr.FontSize = (float)textBoxParam.FontSize;
-            FontType checkFontType = CFontNameHelper.GetFontType(textBoxParam.FontName);
-            textAttr.FontName = CFontNameHelper.ObtainFontName(
-                checkFontType == FontType.Unknown ? FontType.Helvetica : checkFontType,
-                textBoxParam.IsBold,
-                 textBoxParam.IsItalic);
+            textAttr.FontName = textBoxParam.FontName;
             widget.SetTextAttribute(textAttr);
 
             if (!string.IsNullOrEmpty(textBoxParam.FieldName))
@@ -1205,11 +1216,7 @@ namespace ComPDFKit.Tool
             CTextAttribute textAttr = new CTextAttribute();
             textAttr.FontColor = comboBoxParam.FontColor;
             textAttr.FontSize = (float)comboBoxParam.FontSize;
-            FontType checkFontType = CFontNameHelper.GetFontType(comboBoxParam.FontName);
-            textAttr.FontName = CFontNameHelper.ObtainFontName(
-                checkFontType == FontType.Unknown ? FontType.Helvetica : checkFontType,
-                comboBoxParam.IsBold,
-                 comboBoxParam.IsItalic);
+            textAttr.FontName = comboBoxParam.FontName;
             widget.SetTextAttribute(textAttr);
 
             if (!string.IsNullOrEmpty(comboBoxParam.FieldName))
@@ -1260,11 +1267,7 @@ namespace ComPDFKit.Tool
             CTextAttribute textAttr = new CTextAttribute();
             textAttr.FontColor = listBoxParam.FontColor;
             textAttr.FontSize = (float)listBoxParam.FontSize;
-            FontType checkFontType = CFontNameHelper.GetFontType(listBoxParam.FontName);
-            textAttr.FontName = CFontNameHelper.ObtainFontName(
-                checkFontType == FontType.Unknown ? FontType.Helvetica : checkFontType,
-                listBoxParam.IsBold,
-                 listBoxParam.IsItalic);
+            textAttr.FontName = listBoxParam.FontName;
             widget.SetTextAttribute(textAttr);
 
             if (!string.IsNullOrEmpty(listBoxParam.FieldName))
@@ -1316,11 +1319,7 @@ namespace ComPDFKit.Tool
             textAttr.FontSize = (float)signatureParam.FontSize;
             bool isBold = IsBold(textAttr.FontName);
             bool isItalic = IsItalic(textAttr.FontName);
-            FontType checkFontType = CFontNameHelper.GetFontType(signatureParam.FontName);
-            textAttr.FontName = CFontNameHelper.ObtainFontName(
-                checkFontType == FontType.Unknown ? FontType.Helvetica : checkFontType,
-                isBold,
-                 isItalic);
+            textAttr.FontName = signatureParam.FontName;
             widget.SetTextAttribute(textAttr);
 
             if (!string.IsNullOrEmpty(signatureParam.FieldName))

+ 6 - 0
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.FindReplace.cs

@@ -184,6 +184,12 @@ namespace ComPDFKit.Tool
                 }
             }
 
+            if (currentSelectionIndex < 0 || (editTextFindSelectionList!=null && currentSelectionIndex >= editTextFindSelectionList.Count))
+            {
+                isOtherPage = false;
+                canLoop = true;
+                return false;
+            }
             editTextFindSelection = editTextFindSelectionList[currentSelectionIndex];
             GoToFoundDestination(editTextFindSelection);
             isOtherPage = false;

+ 108 - 37
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.MultiSelectedRect.cs

@@ -1,12 +1,8 @@
 using ComPDFKit.Tool.DrawTool;
 using ComPDFKit.Tool.Help;
 using ComPDFKit.Viewer.Layer;
-using ComPDFKitViewer.Layer;
 using System;
 using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 using System.Windows;
 using System.Windows.Input;
 
@@ -31,15 +27,29 @@ namespace ComPDFKit.Tool
         public float ZoomX { get; set; }
 
         public float ZoomY { get; set; }
+
+        /// <summary>
+        /// Multiple selection of movement distance
+        /// </summary>
+        public float ChangeX { get; set; }
+
+        /// <summary>
+        /// Multiple selection of movement distance
+        /// </summary>
+        public float ChangeY { get; set; }
     }
 
     public partial class CPDFViewerTool
     {
-        int multiSelectedRectViewTag = -1;
-        List<int> editAreaMultiIndex = new List<int>();
-        int multiPage = -1;
         public event EventHandler<MultiSelectedData> MultiDataChanging;
         public event EventHandler<MultiSelectedData> MultiDataChanged;
+        public int MultiSelectedRectViewTag { get; set; } = -1;
+
+        private List<int> editAreaMultiIndex = new List<int>();
+        private int multiPage = -1;
+        private bool isOpen = false;
+        private Key multiKey = Key.LeftCtrl;
+
         private void InsertMultiSelectedRectView()
         {
             int selectedRectViewIndex = PDFViewer.GetMaxViewIndex();
@@ -50,18 +60,20 @@ namespace ComPDFKit.Tool
             multiSelectedRect.DataChanged += MultiSelectedRect_DataChanged;
             multiSelectedRect.DataChanging += MultiSelectedRect_DataChanging;
             PDFViewer.InsertView(selectedRectViewIndex, customizeLayer);
-            multiSelectedRectViewTag = customizeLayer.GetResTag();
+            MultiSelectedRectViewTag = customizeLayer.GetResTag();
             //multiSelectedRect.Children.Add(multiSelectedRect);
         }
 
         private void MultiSelectedRect_DataChanging(object sender, Point e)
         {
             MultiSelectedData multiSelectedAnnotData = new MultiSelectedData();
-            MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(multiSelectedRectViewTag));
+            MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(MultiSelectedRectViewTag));
             if (isOpen && multiSelectedRect != null)
             {
                 multiSelectedAnnotData.ZoomX = multiSelectedRect.GetZoomX();
                 multiSelectedAnnotData.ZoomY = multiSelectedRect.GetZoomY();
+                multiSelectedAnnotData.ChangeX = multiSelectedRect.GetChangeX();
+                multiSelectedAnnotData.ChangeY = multiSelectedRect.GetChangeY();
                 multiSelectedAnnotData.MoveOffset = e;
                 multiSelectedAnnotData.ObjectType = multiSelectedRect.GetSelectedType();
                 multiSelectedAnnotData.MultiObjectIndex = new List<int>();
@@ -74,11 +86,13 @@ namespace ComPDFKit.Tool
         private void MultiSelectedRect_DataChanged(object sender, Point e)
         {
             MultiSelectedData multiSelectedAnnotData = new MultiSelectedData();
-            MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(multiSelectedRectViewTag));
+            MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(MultiSelectedRectViewTag));
             if (isOpen && multiSelectedRect != null)
             {
                 multiSelectedAnnotData.ZoomX = multiSelectedRect.GetZoomX();
                 multiSelectedAnnotData.ZoomY = multiSelectedRect.GetZoomY();
+                multiSelectedAnnotData.ChangeX = multiSelectedRect.GetChangeX();
+                multiSelectedAnnotData.ChangeY = multiSelectedRect.GetChangeY();
                 multiSelectedAnnotData.MoveOffset = e;
                 multiSelectedAnnotData.ObjectType = multiSelectedRect.GetSelectedType();
                 multiSelectedAnnotData.MultiObjectIndex = new List<int>();
@@ -88,19 +102,23 @@ namespace ComPDFKit.Tool
             }
         }
 
-        bool isOpen = false;
-        public void OpenSelectedMulti(bool open)
+        /// <summary>
+        /// Set multiple selection shortcut keys
+        /// </summary>
+        /// <param name="multikey"></param>
+        public void SetMultiSelectKey(Key multikey)
+        {
+            multiKey = multikey;
+        }
+
+        private void OpenSelectedMulti(bool open)
         {
-            if (!open)
-            {
-                CleanSelectedMultiRect();
-            }
             isOpen = open;
         }
 
         public bool HitTestMultiSelectedRect()
         {
-            MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(multiSelectedRectViewTag));
+            MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(MultiSelectedRectViewTag));
             if (isOpen && multiSelectedRect != null)
             {
                 if (multiSelectedRect.GetHitControlIndex(Mouse.GetPosition(this)) != PointControlType.None)
@@ -113,10 +131,16 @@ namespace ComPDFKit.Tool
 
         public void SelectedMultiRect(Rect selectedRects, Rect MaxRect, SelectedType type)
         {
-            MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(multiSelectedRectViewTag));
-            if (isOpen && multiSelectedRect != null)
+            MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(MultiSelectedRectViewTag));
+            bool open = isOpen;
+            if (!Keyboard.IsKeyDown(multiKey))
             {
-
+                open = false;
+            }
+            if (open && multiSelectedRect != null)
+            {
+                lastSelectedRect.ClearDraw();
+                lastSelectedRect.HideDraw();
                 GetSelectedEditAreaForIndex(out int pageIndex, out int editAreaIndex);
                 if (multiPage != pageIndex && editAreaMultiIndex.Count > 0)
                 {
@@ -134,21 +158,64 @@ namespace ComPDFKit.Tool
                     multiPage = pageIndex;
                 }
                 multiPage = pageIndex;
-                editAreaMultiIndex.Add(editAreaIndex);
+                if (startSelectedRect != null && startSelectedPageIndex == multiPage && !editAreaMultiIndex.Contains(startSelectedIndex))
+                {
+                    //Add the first selected object
+                    editAreaMultiIndex.Add(startSelectedIndex);
 
+                    SelectedRect startselectedrect = new SelectedRect(GetDefaultDrawParam(), type);
+                    startselectedrect.SetEditPen(editPen, editHoverPen);
+                    startselectedrect.SetDrawMoveType(DrawMoveType.kReferenceLine);
+                    startselectedrect.SetRect(startSelectedRect.GetRect(), currentZoom);
+                    startselectedrect.SetMaxRect(MaxRect);
+                    editAreaList.Add(startselectedrect, startSelectedEditAreaObject);
+                    multiSelectedRect.Children.Add(startselectedrect);
+
+                    multiSelectedRect.SetMulitSelectedRect(startselectedrect, startSelectedEditAreaObject.PageIndex, startSelectedEditAreaObject.EditAreaIndex);
+                    multiSelectedRect.SetRect(startselectedrect.GetRect());
+                    multiSelectedRect.SetMaxRect(startselectedrect.GetMaxRect());
+                    multiSelectedRect.Draw();
+                }
+                startSelectedRect = null;
+                startSelectedIndex = -1;
+                startSelectedPageIndex = -1;
+                startSelectedEditAreaObject = null;
+                editAreaMultiIndex.Add(editAreaIndex);
                 multiSelectedRect.SetSelectedType(type);
                 SelectedRect selectedRect = new SelectedRect(GetDefaultDrawParam(), type);
+                selectedRect.SetEditPen(editPen, editHoverPen);
                 selectedRect.SetDrawMoveType(DrawMoveType.kReferenceLine);
-                selectedRect.SetRect(selectedRects,currentZoom);
+                selectedRect.SetRect(selectedRects, currentZoom);
                 selectedRect.SetMaxRect(MaxRect);
+                EditAreaObject editAreaObject = GetEditAreaObjectForRect(lastSelectedRect);
+                editAreaList.Add(selectedRect, editAreaObject);
                 multiSelectedRect.Children.Add(selectedRect);
-                multiSelectedRect.SetMulitSelectedRect(selectedRect);
+                multiSelectedRect.SetMulitSelectedRect(selectedRect, editAreaObject.PageIndex, editAreaObject.EditAreaIndex);
 
                 multiSelectedRect.SetRect(selectedRects);
                 multiSelectedRect.SetMaxRect(MaxRect);
                 multiSelectedRect.Draw();
             }
-
+            else
+            {
+                //Remember the first selected object
+                isOpen = false;
+                GetSelectedEditAreaForIndex(out int pageIndex, out int editAreaIndex);
+                SelectedRect selectedRect = new SelectedRect(GetDefaultDrawParam(), type);
+                selectedRect.SetEditPen(editPen, editHoverPen);
+                selectedRect.SetDrawMoveType(DrawMoveType.kReferenceLine);
+                selectedRect.SetRect(selectedRects, currentZoom);
+                selectedRect.SetMaxRect(MaxRect);
+                EditAreaObject editAreaObject = GetEditAreaObjectForRect(lastSelectedRect);
+                if (startSelectedIndex != editAreaIndex || startSelectedPageIndex != pageIndex)
+                {
+                    startSelectedIndex = editAreaIndex;
+                    startSelectedPageIndex = pageIndex;
+                    startSelectedEditAreaObject = editAreaObject;
+                    startSelectedRect = selectedRect;
+                    editAreaList.Add(startSelectedRect, editAreaObject);
+                }
+            }
         }
 
         public void HideDrawSelectedMultiRect()
@@ -165,18 +232,20 @@ namespace ComPDFKit.Tool
 
         public void CleanSelectedMultiRect()
         {
-            MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(multiSelectedRectViewTag));
+            MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(MultiSelectedRectViewTag));
             if (multiSelectedRect != null)
             {
                 multiSelectedRect.Children.Clear();
                 multiSelectedRect.CleanMulitSelectedRect();
                 editAreaMultiIndex.Clear();
+                //Delete Multiple Selection Record List
+                editAreaList.Clear();
             }
         }
 
         public void DrawStartSelectedMultiRect()
         {
-            MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(multiSelectedRectViewTag));
+            MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(MultiSelectedRectViewTag));
 
             if (multiSelectedRect != null)
             {
@@ -188,9 +257,9 @@ namespace ComPDFKit.Tool
 
         public void DrawMoveSelectedMultiRect()
         {
-            MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(multiSelectedRectViewTag));
+            MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(MultiSelectedRectViewTag));
 
-            if (multiSelectedRect != null)
+            if (multiSelectedRect != null&& multiSelectedRect.Children.Count>0)
             {
                 Point point = Mouse.GetPosition(this);
                 multiSelectedRect.OnMouseMove(point, out bool Tag, PDFViewer.ActualWidth, PDFViewer.ActualHeight);
@@ -199,7 +268,7 @@ namespace ComPDFKit.Tool
 
         public void DrawEndSelectedMultiRect()
         {
-            MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(multiSelectedRectViewTag));
+            MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(MultiSelectedRectViewTag));
 
             if (multiSelectedRect != null)
             {
@@ -210,8 +279,8 @@ namespace ComPDFKit.Tool
 
         public void ReDrawSelectedMultiRect()
         {
-            MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(multiSelectedRectViewTag));
-
+            MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(MultiSelectedRectViewTag));
+            DrawEndFrameSelect();
             if (multiSelectedRect != null)
             {
                 multiSelectedRect.ClearDraw();
@@ -241,18 +310,20 @@ namespace ComPDFKit.Tool
 
         private void SelectPDFEdit(MultiSelectedRect multiSelectedRect)
         {
+            //Delete Multiple Selection Box
             foreach (int item in editAreaMultiIndex)
             {
                 SelectedRect OldRect = GetEditAreaForIndex(multiPage, item);
                 if (OldRect != null)
                 {
                     multiSelectedRect.SetSelectedType(SelectedType.PDFEdit);
-                    SelectedRect selectedRect = new SelectedRect(GetDefaultDrawParam(), SelectedType.PDFEdit);
-                    selectedRect.SetDrawMoveType(DrawMoveType.kReferenceLine);
-                    selectedRect.SetRect(OldRect.GetRect(),currentZoom);
-                    selectedRect.SetMaxRect(OldRect.GetMaxRect());
-                    multiSelectedRect.Children.Add(selectedRect);
-                    multiSelectedRect.SetMulitSelectedRect(selectedRect);
+                    //Optimize logic to prevent overlapping of multiple selected objects
+                    //SelectedRect selectedRect = new SelectedRect(GetDefaultDrawParam(), SelectedType.PDFEdit);
+                    //selectedRect.SetDrawMoveType(DrawMoveType.kReferenceLine);
+                    //selectedRect.SetRect(OldRect.GetRect(), currentZoom);
+                    //selectedRect.SetMaxRect(OldRect.GetMaxRect());
+                    //multiSelectedRect.Children.Add(selectedRect);
+                    multiSelectedRect.SetMulitSelectedRect(OldRect, multiPage,item);
                     multiSelectedRect.SetRect(OldRect.GetRect());
                     multiSelectedRect.SetMaxRect(OldRect.GetMaxRect());
                     OldRect.HideDraw();

+ 131 - 0
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.PDFCompareEffect.cs

@@ -0,0 +1,131 @@
+using ComPDFKit.Tool.Help;
+using ComPDFKit.Viewer.Layer;
+using ComPDFKitViewer;
+using ComPDFKitViewer.Helper;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Media;
+
+namespace ComPDFKit.Tool
+{
+    public partial class CPDFViewerTool
+    {
+        private int PDFCompareViewID { get; set; } = -1;
+        private int PDFComparePageIndex {  get; set; } = -1;
+        private List<Rect> PDFCompareRectList {  get; set; }
+        private SolidColorBrush PDFCompareBrush { get; set; }
+        private Pen PDFComparePen { get; set; }
+        private CustomizeLayer GetPDFCompareDrawView()
+        {
+            if(PDFViewer==null)
+            {
+                return null;
+            }
+            if (PDFCompareViewID != -1)
+            {
+                return PDFViewer.GetViewForTag(PDFCompareViewID) as CustomizeLayer;
+            }
+            int maxId = PDFViewer.GetMaxViewIndex();
+            CustomizeLayer customizeLayer = new CustomizeLayer();
+            PDFViewer.InsertView(maxId, customizeLayer);
+            PDFCompareViewID = customizeLayer.GetResTag();
+            PDFViewer.DrawChanged -= DrawChangedNotify;
+            PDFViewer.DrawChanged += DrawChangedNotify;
+            return customizeLayer;
+        }
+
+        private void DrawPDFCompare()
+        {
+            if (PDFCompareViewID==-1)
+            {
+                return;
+            }
+            CustomizeLayer drawLayer = GetPDFCompareDrawView();
+            if (drawLayer == null)
+            {
+                return;
+            }
+
+            if (PDFViewer.CurrentRenderFrame == null)
+            {
+                return;
+            }
+
+            RenderFrame frame = PDFViewer.CurrentRenderFrame;
+            List<RenderData> drawDataList = frame.GetRenderDatas();
+            if (drawDataList == null || drawDataList.Count == 0)
+            {
+                return;
+            }
+
+            RenderData drawData = null;
+            foreach (RenderData data in drawDataList)
+            {
+                if (data.PageIndex == PDFComparePageIndex)
+                {
+                    drawData = data;
+                    break;
+                }
+            }
+
+          DrawingContext drawDC=  drawLayer.RenderOpen();
+
+            if (drawData != null && PDFCompareRectList != null)
+            {
+                foreach(Rect drawRect in PDFCompareRectList)
+                {
+                    Rect standRect = DpiHelper.PDFRectToStandardRect(drawRect);
+
+                    Rect paintRect = new Rect(
+                        standRect.Left * frame.ZoomFactor,
+                        standRect.Top * frame.ZoomFactor,
+                        standRect.Width * frame.ZoomFactor,
+                        standRect.Height * frame.ZoomFactor);
+
+                    Rect offsetRect = new Rect(
+                        paintRect.Left + drawData.PageBound.Left,
+                        paintRect.Top + drawData.PageBound.Top,
+                        paintRect.Width,
+                        paintRect.Height);
+
+                    drawDC.DrawRectangle(PDFCompareBrush,PDFComparePen,offsetRect);
+                }
+            }
+
+            drawDC.Close();
+        }
+
+        private void DrawChangedNotify(object sender, EventArgs e)
+        {
+            DrawPDFCompare();
+        }
+
+        public void SetPDFCompareView(SolidColorBrush FillBrush,Pen BorderPen,int PageIndex,List<Rect> PDFRectList)
+        {
+            PDFCompareRectList=PDFRectList;
+            PDFComparePageIndex = PageIndex;
+            PDFCompareBrush = FillBrush;
+            PDFComparePen = BorderPen;
+            if(PDFCompareViewID==-1)
+            {
+                GetPDFCompareDrawView();
+            }
+            DrawPDFCompare();
+        }
+
+        public void ClearPDFCompareView()
+        {
+            CustomizeLayer drawLayer = GetPDFCompareDrawView();
+            if (drawLayer != null && PDFViewer != null)
+            {
+                PDFViewer.RemoveView(drawLayer);
+                PDFCompareViewID = -1;
+            }
+        }
+    }
+}

+ 35 - 7
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.SelectImage.cs

@@ -13,6 +13,8 @@ namespace ComPDFKit.Tool
     public partial class CPDFViewerTool
     {
         int selectImageTag = -1;
+        private bool enableImageSelect = true;
+
         private void InsertSelectImageView()
         {
             SelectImage createAnnotTool = new SelectImage();
@@ -20,10 +22,24 @@ namespace ComPDFKit.Tool
             PDFViewer.InsertView(SelectTextindex, createAnnotTool);
             selectImageTag = createAnnotTool.GetResTag();
         }
+
+        public void SetImageSelectEnable(bool enable)
+        {
+            enableImageSelect=enable;
+            if (enableImageSelect==false && PDFViewer!=null)
+            {
+                SelectImage imageLayer = PDFViewer.GetViewForTag(selectImageTag) as SelectImage;
+                if (imageLayer != null)
+                {
+                    imageLayer.CleanDraw(PDFViewer);
+                }
+            }
+        }
+
         public bool DrawMoveSelectImage()
         {
             bool isSelect = false;
-            if (PDFViewer.CurrentRenderFrame == null)
+            if (PDFViewer.CurrentRenderFrame == null || enableImageSelect == false)
             {
                 return isSelect;
             }
@@ -40,7 +56,7 @@ namespace ComPDFKit.Tool
         public bool DrawDownSelectImage(bool isNeedClear)
         {
             bool isSelect = false;
-            if (PDFViewer.CurrentRenderFrame == null)
+            if (PDFViewer.CurrentRenderFrame == null || enableImageSelect == false)
             {
                 return isSelect;
             }
@@ -57,24 +73,36 @@ namespace ComPDFKit.Tool
 
         public void ReDrawSelectImage()
         {
+            if(enableImageSelect == false)
+            {
+                return;
+            }
             BaseLayer baseLayer = PDFViewer.GetViewForTag(selectImageTag);
             (baseLayer as SelectImage).Draw(PDFViewer);
         }
 
         public void CleanDrawSelectImage()
         {
+            if (enableImageSelect == false)
+            {
+                return;
+            }
             BaseLayer baseLayer = PDFViewer.GetViewForTag(selectImageTag);
             (baseLayer as SelectImage).CleanDraw(PDFViewer);
         }
 
-        public PageImageItem GetSelectImage()
-        {
-            BaseLayer baseLayer = PDFViewer.GetViewForTag(selectImageTag);
-            return (baseLayer as SelectImage).GetHoverImageItem();
-        }
+        //public PageImageItem GetSelectImage()
+        //{
+        //    BaseLayer baseLayer = PDFViewer.GetViewForTag(selectImageTag);
+        //    return (baseLayer as SelectImage).GetHoverImageItem();
+        //}
 
         public Dictionary<int, List<PageImageItem>> GetSelectImageItems()
         {
+            if (enableImageSelect == false)
+            {
+                return new Dictionary<int, List<PageImageItem>>();
+            }
             BaseLayer baseLayer = PDFViewer.GetViewForTag(selectImageTag);
             return (baseLayer as SelectImage).GetSelectImageItems();
         }

+ 4 - 1
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.SelectText.cs

@@ -51,7 +51,10 @@ namespace ComPDFKit.Tool
             }
             BaseLayer baseLayer = PDFViewer.GetViewForTag(selectTextTag);
             PDFViewer.GetMousePointToPage(out int pageindex, out Point pagepoint);
-            (baseLayer as SelectText).MoveDraw(new Point(DpiHelper.StandardNumToPDFNum(pagepoint.X / PDFViewer.CurrentRenderFrame.ZoomFactor), DpiHelper.StandardNumToPDFNum(pagepoint.Y / PDFViewer.CurrentRenderFrame.ZoomFactor)), pageindex, PDFViewer, new Point(10, 10), DoubleClick);
+            if(pageindex>=0)
+            {
+                (baseLayer as SelectText).MoveDraw(new Point(DpiHelper.StandardNumToPDFNum(pagepoint.X / PDFViewer.CurrentRenderFrame.ZoomFactor), DpiHelper.StandardNumToPDFNum(pagepoint.Y / PDFViewer.CurrentRenderFrame.ZoomFactor)), pageindex, PDFViewer, new Point(10, 10), DoubleClick);
+            }
         }
 
         public void DrawEndSelectText()

+ 17 - 1
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.SelectedRect.cs

@@ -19,6 +19,7 @@ namespace ComPDFKit.Tool
     {
         bool isDrawSelectRect = false;
         int selectedRectViewTag = -1;
+        private bool isOutSideScaling = false;
         public event EventHandler<SelectedAnnotData> SelectedDataChanging;
         public event EventHandler<SelectedAnnotData> SelectedDataChanged;
 
@@ -37,6 +38,15 @@ namespace ComPDFKit.Tool
             selectedRectViewTag= customizeLayer.GetResTag();
         }
 
+        /// <summary>
+        /// Set whether the border can be moved outside the border
+        /// </summary>
+        /// <param name="IsOutSideScaling"></param>
+        public void SetOutSideScaling(bool IsOutSideScaling)
+        {
+            isOutSideScaling = IsOutSideScaling;
+        }
+
         private void SelectedRect_DataChanging(object sender, SelectedAnnotData e)
         {
             SelectedDataChanging?.Invoke(this, e);
@@ -89,6 +99,7 @@ namespace ComPDFKit.Tool
             SelectedRect selectedRect = CommonHelper.FindVisualChild<SelectedRect>(baseLayer as CustomizeLayer);
             if (selectedRect != null)
             {
+                selectedRect.SetOutSideScaling(isOutSideScaling);
                 selectedRect.OnMouseMove(point, out DrawTag,PDFViewer.ActualWidth,PDFViewer.ActualHeight);
                 selectedRect.Draw();
             }
@@ -137,11 +148,16 @@ namespace ComPDFKit.Tool
             {
                 return ;
             }
+            SelectAnnot(cacheHitTestAnnot.GetAnnotData());
+        }
+
+        private void SelectAnnot(AnnotData selectData)
+        {
             BaseLayer baseLayer = PDFViewer.GetViewForTag(selectedRectViewTag);
             SelectedRect selectedRect = CommonHelper.FindVisualChild<SelectedRect>(baseLayer as CustomizeLayer);
             if (selectedRect != null)
             {
-                selectedRect.SetAnnotData(cacheHitTestAnnot.GetAnnotData());
+                selectedRect.SetAnnotData(selectData);
             }
         }
 

Diff do ficheiro suprimidas por serem muito extensas
+ 1196 - 59
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.TextEdit.cs


+ 10 - 0
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.WidgetTool.cs

@@ -39,6 +39,7 @@ namespace ComPDFKit.Tool
         public static DependencyProperty PopupAttachDataProperty = DependencyProperty.Register("PopupAttachData", typeof(BaseAnnot), typeof(CPDFViewerTool));
 
         public event EventHandler<WidgetClickArgs> WidgetActionHandler;
+        public event EventHandler<CPDFAnnotation> WidgetCreatedHandler;
 
         private CustomizeLayer formPopLayer=null;
         // Inner default pop-up control
@@ -162,6 +163,7 @@ namespace ComPDFKit.Tool
                     }
 
                     TextBox textui = new TextBox();
+                    textui.Name = "PdfViewerTextBox";
                     CTextAttribute textAttribute = textWidget.GetTextAttribute();
                     byte transparency = textWidget.GetTransparency();
                     textui.FontSize = textAttribute.FontSize* annotData.CurrentZoom/72D*96D;
@@ -871,5 +873,13 @@ namespace ComPDFKit.Tool
                 }
             }
         }
+
+        internal void InvokeWidgetCreated(CPDFAnnotation annot)
+        {
+            if(annot!=null && annot.IsValid())
+            {
+                WidgetCreatedHandler?.Invoke(this, annot);
+            }
+        }
     }
 }

+ 2 - 4
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.xaml

@@ -12,9 +12,7 @@
              >
     <ScrollViewer Name="ScrollContainer" Focusable="False" CanContentScroll="True"
                   HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"
-                  MouseUp="ScrollViewer_MouseUp" MouseDown="ScrollViewer_MouseDown">
-        <compdfkitviewer:CPDFViewer x:Name="PDFViewer">
-
-        </compdfkitviewer:CPDFViewer>
+                  MouseUp="ScrollViewer_MouseUp" MouseDown="ScrollViewer_MouseDown" ScrollChanged="ScrollViewer_ScrollChanged">
+        <compdfkitviewer:CPDFViewer x:Name="PDFViewer"></compdfkitviewer:CPDFViewer>
     </ScrollViewer>
 </UserControl>

+ 232 - 26
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.xaml.cs

@@ -1,10 +1,13 @@
-using ComPDFKit.PDFAnnotation;
+using ComPDFKit.Import;
+using ComPDFKit.PDFAnnotation;
 using ComPDFKit.PDFDocument;
 using ComPDFKit.PDFDocument.Action;
 using ComPDFKit.PDFPage;
 using ComPDFKit.Tool.DrawTool;
+using ComPDFKit.Tool.Help;
 using ComPDFKit.Tool.SettingParam;
 using ComPDFKit.Viewer.Helper;
+using ComPDFKit.Viewer.Layer;
 using ComPDFKitViewer;
 using ComPDFKitViewer.Annot;
 using ComPDFKitViewer.BaseObject;
@@ -48,6 +51,7 @@ namespace ComPDFKit.Tool
         ImageSelect,
         MultiTextEdit,
         SelectedPageRect,
+        MultiSelector
     }
 
     public enum ToolType
@@ -94,8 +98,12 @@ namespace ComPDFKit.Tool
             InsertMultiSelectedRectView();
             InsertCustomizeToolView();
             InsertSelectTextView();
+            //Frame Select
+            InsertFrameSelectToolView();
             InsertTextEditView();
             InsertPageSelectedRectView();
+
+            AnnotSelectInsert();
         }
 
         public void ReplaceCPDFViewer(CPDFViewer newViewer)
@@ -130,6 +138,7 @@ namespace ComPDFKit.Tool
         public event EventHandler<MouseEventObject> MouseLeftButtonUpHandler;
         public event EventHandler<MouseEventObject> MouseMoveHandler;
         public event EventHandler<MouseEventObject> MouseRightButtonDownHandler;
+        public event EventHandler<ScrollChangedEventArgs> ScrollChangedHandler;
         public event EventHandler DrawChanged;
         public event EventHandler DocumentModifiedChanged;
         public event EventHandler<PopupControlInfo> PopUpControlHandler;
@@ -146,6 +155,33 @@ namespace ComPDFKit.Tool
         private bool isMultiSelected;
         private bool isDocumentModified = false;
 
+
+
+        public bool CanAddTextEdit = true;
+
+        protected bool isContinueCreateTextEdit = false;
+
+        public bool GetIsMultiSelected()
+        {
+            return isMultiSelected;
+        }
+
+        /// <summary>
+        /// Set whether continuous text editing is required
+        /// </summary>
+        /// <param name="isContinueCreateTextEdit"></param>
+        public void SetContinueCreateTextEdit(bool isContinueCreateTextEdit)
+        {
+
+            this.isContinueCreateTextEdit = isContinueCreateTextEdit;
+            CanAddTextEdit = true;
+        }
+
+
+        /// <summary>
+        ///  Does it support multiple selection
+        /// </summary>
+        /// <param name="isMulti">true Can MultiSelected</param>
         public void SetIsMultiSelected(bool isMulti)
         {
             isMultiSelected = isMulti;
@@ -161,6 +197,22 @@ namespace ComPDFKit.Tool
             return defaultDrawParam;
         }
 
+        /// <summary>
+        /// Set default painting parameters
+        /// </summary>
+        /// <param name="defaultDrawParam"></param>
+        public void SetDefaultDrawParam(DefaultDrawParam defaultDrawParam = null)
+        {
+            if (defaultDrawParam == null)
+            {
+                this.defaultDrawParam = new DefaultDrawParam();
+            }
+            else
+            {
+                this.defaultDrawParam = defaultDrawParam;
+            }
+        }
+
         public MeasureSetting GetMeasureSetting()
         {
             return measureSetting;
@@ -298,10 +350,24 @@ namespace ComPDFKit.Tool
 
         protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e)
         {
+            if (isContinueCreateTextEdit)
+            {
+
+                if (lastSelectedRect != null)
+                {
+                    CanAddTextEdit = false;
+                }
+                else
+                {
+                    CanAddTextEdit = true;
+                }
+            }
+
             if (PDFViewer == null || PDFViewer.CurrentRenderFrame == null)
             {
                 return;
             }
+
             if (!HitTestBorder())
             {
                 RemovePopTextUI();
@@ -326,7 +392,7 @@ namespace ComPDFKit.Tool
                         BuildPopTextUI(cacheHitTestAnnot);
                         isDrawSelectRect = false;
                         mouseEventObject.annotType = cacheHitTestAnnot.GetAnnotData().AnnotType;
-                        mouseEventObject.IsMersured = cacheHitTestAnnot.GetAnnotData().Annot.IsMersured();
+                        mouseEventObject.IsMersured = cacheHitTestAnnot.GetAnnotData().Annot.IsMeasured();
                         MouseLeftButtonDownHandler?.Invoke(this, mouseEventObject);
                         return;
                     }
@@ -340,7 +406,7 @@ namespace ComPDFKit.Tool
                 {
                     mouseEventObject.hitTestType = MouseHitTestType.SelectRect;
                     mouseEventObject.annotType = cacheHitTestAnnot.GetAnnotData().AnnotType;
-                    mouseEventObject.IsMersured = cacheHitTestAnnot.GetAnnotData().Annot.IsMersured();
+                    mouseEventObject.IsMersured = cacheHitTestAnnot.GetAnnotData().Annot.IsMeasured();
                     MouseLeftButtonDownHandler?.Invoke(this, mouseEventObject);
                     return;
                 }
@@ -357,7 +423,7 @@ namespace ComPDFKit.Tool
                 {
                     mouseEventObject.hitTestType = MouseHitTestType.SelectRect;
                     mouseEventObject.annotType = cacheHitTestAnnot.GetAnnotData().AnnotType;
-                    mouseEventObject.IsMersured = cacheHitTestAnnot.GetAnnotData().Annot.IsMersured();
+                    mouseEventObject.IsMersured = cacheHitTestAnnot.GetAnnotData().Annot.IsMeasured();
                     MouseLeftButtonDownHandler?.Invoke(this, mouseEventObject);
                     return;
                 }
@@ -389,7 +455,7 @@ namespace ComPDFKit.Tool
                         };
                         if (cacheHitTestAnnot != null && list.Contains(cacheHitTestAnnot.CurrentType))
                         {
-                            mouseEventObject.IsMersured = cacheHitTestAnnot.GetAnnotData().Annot.IsMersured();
+                            mouseEventObject.IsMersured = cacheHitTestAnnot.GetAnnotData().Annot.IsMeasured();
                             SetEditAnnotObject();
                         }
                         else
@@ -420,7 +486,7 @@ namespace ComPDFKit.Tool
             }
             else if ((currentModel == ToolType.Pan || currentModel == ToolType.Viewer))
             {
-                if (DrawDownSelectImage(true))
+                if (!IsText() && DrawDownSelectImage(true))
                 {
                     mouseEventObject.hitTestType = MouseHitTestType.ImageSelect;
                 }
@@ -433,14 +499,29 @@ namespace ComPDFKit.Tool
             // Form creation mode
             else if (currentModel == ToolType.WidgetEdit)
             {
-                if (AnnotWidgetHitTest())
+                if (!AnnotSelectAreaHitTest())
                 {
-                    cacheHitTestAnnot = PDFViewer?.AnnotHitTest() as BaseWidget;
-                    SelectedAnnot();
-                    mouseEventObject.hitTestType = MouseHitTestType.Annot;
+                    if (AnnotWidgetHitTest())
+                    {
+                        BaseWidget hitWidget = PDFViewer?.AnnotHitTest() as BaseWidget;
+                        cacheHitTestAnnot = null;
+                        if (AnnotSelectGetCount() == 0 && hitWidget != null)
+                        {
+                            AnnotSelectAddItem(hitWidget.GetAnnotData());
+                            cacheHitTestAnnot = hitWidget;
+                            SelectedAnnot();
+                        }
 
-                    mouseEventObject.annotType = cacheMoveWidget.GetAnnotData().AnnotType;
+                        mouseEventObject.hitTestType = MouseHitTestType.Annot;
+                        mouseEventObject.annotType = cacheMoveWidget.GetAnnotData().AnnotType;
+                    }
+                    else
+                    {
+                        AnnotSelectAreaHit();
+                    }
                 }
+
+                AnnotSelectMoveHit();
             }
             // Content editing mode
             else if (currentModel == ToolType.ContentEdit)
@@ -454,6 +535,30 @@ namespace ComPDFKit.Tool
 
                 if (lastSelectedRect != null)
                 {
+                    //Multi selection processing optimization, other click effects
+                    DrawEndFrameSelect();
+                    if (!Keyboard.IsKeyDown(multiKey) || !isMultiSelected)
+                    {
+                        CleanSelectedMultiRect();
+                        OpenSelectedMulti(false);
+                        if (PDFViewer.CurrentRenderFrame != null)
+                        {
+                            currentZoom = PDFViewer.CurrentRenderFrame.ZoomFactor;
+                            if (PDFViewer.CurrentRenderFrame.IsCacheEditPage == true && currentModel == ToolType.ContentEdit)
+                            {
+                                SetEditTextRect(PDFViewer.CurrentRenderFrame);
+                                if (selectedEditPageIndex != -1 && selectedEditAreaIndex != -1)
+                                {
+                                    DrawSelectedEditAreaForIndex();
+                                }
+                            }
+                        }
+                        ReDrawSelectedMultiRect();
+                    }
+                    if (lastSelectedRect == null)
+                    {
+                        return;
+                    }
                     SelectedMultiRect(lastSelectedRect.GetRect(), lastSelectedRect.GetMaxRect(), SelectedType.PDFEdit);
                     HideDrawSelectedMultiRect();
                     lastSelectedRect.DataChanged -= SelectedRect_DataChanged;
@@ -461,14 +566,38 @@ namespace ComPDFKit.Tool
                 }
                 else
                 {
+                    if (Keyboard.IsKeyDown(multiKey) && isMultiSelected)
+                    {
+                        DelMultiSelectRect();
+                    }
+
                     if (HitTestMultiSelectedRect())
                     {
                         mouseEventObject.hitTestType = MouseHitTestType.MultiTextEdit;
                     }
                     else
                     {
-                        CleanSelectedMultiRect();
+                        //Clear the currently selected object
+                        startSelectedRect = null;
+                        startSelectedIndex = -1;
+                        startSelectedPageIndex = -1;
+                        startSelectedEditAreaObject = null;
 
+                        CleanSelectedMultiRect();
+                        OpenSelectedMulti(false);
+                        if (PDFViewer.CurrentRenderFrame != null)
+                        {
+                            currentZoom = PDFViewer.CurrentRenderFrame.ZoomFactor;
+                            if (PDFViewer.CurrentRenderFrame.IsCacheEditPage == true && currentModel == ToolType.ContentEdit)
+                            {
+                                SetEditTextRect(PDFViewer.CurrentRenderFrame);
+                                if (selectedEditPageIndex != -1 && selectedEditAreaIndex != -1)
+                                {
+                                    DrawSelectedEditAreaForIndex();
+                                }
+                            }
+                        }
+                        ReDrawSelectedMultiRect();
                     }
                 }
             }
@@ -495,6 +624,46 @@ namespace ComPDFKit.Tool
             {
                 return;
             }
+            if (currentModel == ToolType.WidgetEdit)
+            {
+                bool areaSelectAdd = AnnotSelectAreaSelect(true);
+                if (AnnotWidgetHitTest())
+                {
+                    BaseWidget checkItem = PDFViewer?.AnnotHitTest() as BaseWidget;
+                    AnnotSelectAddItem(checkItem?.GetAnnotData(), !AnnotSelectAreaHitTest());
+                }
+                if (AnnotSelectGetCount() > 1)
+                {
+                    CleanSelectedRect();
+                }
+                if (IsMoved == false && AnnotSelectAreaHitTest() == false && AnnotWidgetHitTest() == false)
+                {
+                    AnnotSelectClean();
+                }
+                if (AnnotSelectGetCount() == 1)
+                {
+                    cacheHitTestAnnot = AnnotSelectGetAnnot();
+                    if (cacheHitTestAnnot != null)
+                    {
+                        BaseLayer baseLayer = PDFViewer.GetViewForTag(selectedRectViewTag);
+                        SelectedRect selectedRect = CommonHelper.FindVisualChild<SelectedRect>(baseLayer as CustomizeLayer);
+                        if (selectedRect != null)
+                        {
+                            if (IsMoved && areaSelectAdd == false)
+                            {
+                                selectedRect.UpdateAnnotData(cacheHitTestAnnot.GetAnnotData());
+                            }
+                            else
+                            {
+                                selectedRect.SetAnnotData(cacheHitTestAnnot.GetAnnotData());
+                            }
+                            selectedRect.Draw();
+                        }
+                        isDrawSelectRect = true;
+                    }
+                }
+            }
+
             MouseEventObject mouseEventObject = new MouseEventObject
             {
                 mouseButtonEventArgs = e,
@@ -502,6 +671,7 @@ namespace ComPDFKit.Tool
                 annotType = C_ANNOTATION_TYPE.C_ANNOTATION_NONE,
                 IsCreate = false
             };
+
             if (isDrawSelectRect || IsDrawEditAnnot)
             {
                 mouseEventObject.hitTestType = MouseHitTestType.SelectRect;
@@ -513,16 +683,23 @@ namespace ComPDFKit.Tool
                 {
                     mouseEventObject.annotType = C_ANNOTATION_TYPE.C_ANNOTATION_NONE;
                 }
-                MouseLeftButtonUpHandler?.Invoke(this, mouseEventObject);
-                ReleaseMouseCapture();
-                return;
             }
             MouseLeftButtonUpHandler?.Invoke(this, mouseEventObject);
             ReleaseMouseCapture();
+            if (currentModel == ToolType.WidgetEdit)
+            {
+                AnnotSelectUpdate();
+                AnnotSelectDraw();
+                AnnotSelectSave();
+                AreaMoveData = new AnnotSelectAreaData();
+            }
+            IsMoved = false;
         }
 
         protected override void OnMouseMove(MouseEventArgs e)
         {
+            IsMoved = e.LeftButton == MouseButtonState.Pressed;
+
             if (PDFViewer == null || PDFViewer.CurrentRenderFrame == null)
             {
                 return;
@@ -574,7 +751,7 @@ namespace ComPDFKit.Tool
                     }
 
                     mouseEventObject.annotType = caheMoveAnnot.GetAnnotData().AnnotType;
-                    mouseEventObject.IsMersured = caheMoveAnnot.GetAnnotData().Annot.IsMersured();
+                    mouseEventObject.IsMersured = caheMoveAnnot.GetAnnotData().Annot.IsMeasured();
                 }
                 else
                 {
@@ -588,7 +765,10 @@ namespace ComPDFKit.Tool
                     caheMoveAnnot = null;
                     if ((currentModel == ToolType.Pan || currentModel == ToolType.Viewer))
                     {
-                        DrawMoveSelectImage();
+                        if (GetTextSelectInfo() == null)
+                        {
+                            DrawMoveSelectImage();
+                        }
                     }
                 }
             }
@@ -622,7 +802,7 @@ namespace ComPDFKit.Tool
                     if (cacheHitTestAnnot != null)
                     {
                         mouseEventObject.annotType = cacheHitTestAnnot.GetAnnotData().AnnotType;
-                        mouseEventObject.IsMersured = cacheHitTestAnnot.GetAnnotData().Annot.IsMersured();
+                        mouseEventObject.IsMersured = cacheHitTestAnnot.GetAnnotData().Annot.IsMeasured();
                     }
                     else
                     {
@@ -631,6 +811,15 @@ namespace ComPDFKit.Tool
                 }
             }
 
+            if (currentModel == ToolType.WidgetEdit)
+            {
+                AnnotSelectAreaDraw();
+                if (!AnnotSelectMoveDraw())
+                {
+                    AnnotSelectAreaHover();
+                }
+            }
+
             MouseMoveHandler?.Invoke(this, mouseEventObject);
             PDFViewer.SetCustomMousePoint(Mouse.GetPosition(this).Y, Mouse.GetPosition(this).X);
             if (oldCursor != newCursor)
@@ -743,18 +932,26 @@ namespace ComPDFKit.Tool
             // Form creation mode
             if (currentModel == ToolType.WidgetEdit)
             {
-                if (AnnotWidgetHitTest())
+                if (!AnnotSelectAreaHitTest())
                 {
-                    cacheHitTestAnnot = PDFViewer?.AnnotHitTest() as BaseWidget;
-                    SelectedAnnot();
-                    DrawSelectedLayer();
-                    mouseEventObject.hitTestType = MouseHitTestType.Annot;
-
-                    mouseEventObject.annotType = cacheMoveWidget.GetAnnotData().AnnotType;
+                    if (AnnotWidgetHitTest())
+                    {
+                        cacheHitTestAnnot = PDFViewer?.AnnotHitTest() as BaseWidget;
+                        SelectedAnnot();
+                        DrawSelectedLayer();
+                        mouseEventObject.hitTestType = MouseHitTestType.Annot;
+                        mouseEventObject.annotType = cacheMoveWidget.GetAnnotData().AnnotType;
+                        AnnotSelectClean();
+                        AnnotSelectAddItem(cacheHitTestAnnot?.GetAnnotData());
+                    }
+                    else
+                    {
+                        CleanSelectedRect();
+                    }
                 }
                 else
                 {
-                    CleanSelectedRect();
+                    mouseEventObject.hitTestType = MouseHitTestType.MultiSelector;
                 }
             }
 
@@ -809,6 +1006,8 @@ namespace ComPDFKit.Tool
                 {
                     lastSelectedRect.SetCurrentDrawPointType(DrawPointType.Crop);
                     ignoreList.Add(PointControlType.Body);
+                    // Initialize ClipRect
+                    ClipThickness = new Thickness(0, 0, 0, 0);
                     if (editArea.TryGetValue(lastSelectedRect, out EditAreaObject editAreaObject))
                     {
                         cropIndex = editAreaObject.EditAreaIndex;
@@ -890,6 +1089,8 @@ namespace ComPDFKit.Tool
         private void PDFViewer_DrawChanged(object sender, EventArgs e)
         {
             SizeChangeds();
+            AnnotSelectUpdate();
+            AnnotSelectDraw();
             DrawChanged?.Invoke(this, e);
         }
 
@@ -990,5 +1191,10 @@ namespace ComPDFKit.Tool
         {
 
         }
+
+        private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e)
+        {
+            ScrollChangedHandler?.Invoke(this, e);
+        }
     }
 }

+ 26 - 1
Demo/Examples/ComPDFKit.Tool/ComPDFKit.Tool.csproj

@@ -9,7 +9,7 @@
     <AppDesignerFolder>Properties</AppDesignerFolder>
     <RootNamespace>ComPDFKit.Tool</RootNamespace>
     <AssemblyName>ComPDFKit.Tool</AssemblyName>
-    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
+    <TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
     <FileAlignment>512</FileAlignment>
     <Deterministic>true</Deterministic>
     <TargetFrameworkProfile />
@@ -106,6 +106,7 @@
     <Compile Include="AlignmentsHelp.cs" />
     <Compile Include="CPDFViewerTool.Annot.cs" />
     <Compile Include="CPDFViewerTool.AnnotEdit.cs" />
+    <Compile Include="CPDFViewerTool.AnnotSelector.cs" />
     <Compile Include="CPDFViewerTool.Command.cs" />
     <Compile Include="CPDFViewerTool.CreateWidget.cs" />
     <Compile Include="CPDFViewerTool.CustomizeTool.cs" />
@@ -113,6 +114,7 @@
     <Compile Include="CPDFViewerTool.FindReplace.cs" />
     <Compile Include="CPDFViewerTool.MultiSelectedRect.cs" />
     <Compile Include="CPDFViewerTool.PageSelected.cs" />
+    <Compile Include="CPDFViewerTool.PDFCompareEffect.cs" />
     <Compile Include="CPDFViewerTool.SelectImage.cs" />
     <Compile Include="CPDFViewerTool.WidgetTool.cs" />
     <Compile Include="CPDFViewerTool.SelectedRect.cs" />
@@ -123,10 +125,13 @@
     </Compile>
     <Compile Include="CustomCommands.cs" />
     <Compile Include="DrawTool\AnnotEdit.cs" />
+    <Compile Include="DrawTool\AnnotSelector.cs" />
     <Compile Include="DrawTool\CaretVisual.cs" />
     <Compile Include="DrawTool\CreateAnnotTool.cs" />
     <Compile Include="DrawTool\CreateCustomizeTool.cs" />
     <Compile Include="DrawTool\CreateWidgetTool.cs" />
+    <Compile Include="DrawTool\DashBorder.cs" />
+    <Compile Include="DrawTool\FrameSelectTool.cs" />
     <Compile Include="DrawTool\MultiSelectedRect.cs" />
     <Compile Include="DrawTool\PageSelectedRect.cs" />
     <Compile Include="DrawTool\SelectedRect.cs" />
@@ -217,5 +222,25 @@
       <Name>ComPDFKit.Viewer</Name>
     </ProjectReference>
   </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\compdfkit_windows\ComPDFKit\ComPDFKitCSharp\ComPDFKit.NET.csproj">
+      <Project>{56e518ad-c126-4b48-9a09-0a64c87020e4}</Project>
+      <Name>ComPDFKit.NET</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\compdfkit_windows_rebuild\ComPDFKit.Viewer\ComPDFKit.Viewer.csproj">
+      <Project>{783263cf-0da3-4095-9df8-2c4a6b3ff908}</Project>
+      <Name>ComPDFKit.Viewer</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\..\..\..\compdfkit_windows\ComPDFKit\ComPDFKitCSharp\ComPDFKit.NET.csproj">
+      <Project>{56e518ad-c126-4b48-9a09-0a64c87020e4}</Project>
+      <Name>ComPDFKit.NET</Name>
+    </ProjectReference>
+    <ProjectReference Include="..\..\..\..\compdfkit_windows_rebuild\ComPDFKit.Viewer\ComPDFKit.Viewer.csproj">
+      <Project>{783263cf-0da3-4095-9df8-2c4a6b3ff908}</Project>
+      <Name>ComPDFKit.Viewer</Name>
+    </ProjectReference>
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
 </Project>

+ 195 - 116
Demo/Examples/ComPDFKit.Tool/DrawTool/AnnotEdit.cs

@@ -13,6 +13,7 @@ using System.Linq;
 using System.Net;
 using System.Windows;
 using System.Windows.Controls;
+using System.Windows.Input;
 using System.Windows.Media;
 using System.Windows.Media.TextFormatting;
 using static ComPDFKit.Tool.Help.ImportWin32;
@@ -79,6 +80,7 @@ namespace ComPDFKit.Tool.DrawTool
         /// Move offset during movement
         /// </summary>
         protected Point moveOffset { get; set; } = new Point(0, 0);
+        private Point LineMeasureOffset { get; set; }= new Point(0, 0);
 
         /// <summary>
         /// Point size
@@ -160,6 +162,7 @@ namespace ComPDFKit.Tool.DrawTool
                 case C_ANNOTATION_TYPE.C_ANNOTATION_FREETEXT:
                     break;
                 case C_ANNOTATION_TYPE.C_ANNOTATION_LINE:
+                    List<Point> sortPointList= new List<Point>();
                     for (int i = 0; i < (annotData.Annot as CPDFLineAnnotation).Points.Length; i++)
                     {
                         Point point = DpiHelper.PDFPointToStandardPoint(new Point((annotData.Annot as CPDFLineAnnotation).Points[i].x, (annotData.Annot as CPDFLineAnnotation).Points[i].y));
@@ -167,9 +170,15 @@ namespace ComPDFKit.Tool.DrawTool
                             point.X * annotData.CurrentZoom + annotData.PaintOffset.X - annotData.CropLeft * annotData.CurrentZoom,
                             point.Y * annotData.CurrentZoom + annotData.PaintOffset.Y - annotData.CropTop * annotData.CurrentZoom
                             );
-                        activePoints.Add(point);
+                        sortPointList.Add(point);
+                    }
+                    sortPointList.Sort((a, b) => { if (a.X > b.X) return 1; else return 0; });
+                    foreach (Point checkPoint in sortPointList)
+                    {
+                        activePoints.Add(checkPoint);
                     }
-                    if ((annotData.Annot as CPDFLineAnnotation).IsMersured())
+                   
+                    if ((annotData.Annot as CPDFLineAnnotation).IsMeasured())
                     {
                         CRect rawRect = annotData.Annot.GetRect();
                         Rect rect = DataConversionForWPF.CRectConversionForRect(rawRect);
@@ -197,7 +206,7 @@ namespace ComPDFKit.Tool.DrawTool
                             );
                         activePoints.Add(point);
                     }
-                    if ((annotData.Annot as CPDFPolygonAnnotation).IsMersured())
+                    if ((annotData.Annot as CPDFPolygonAnnotation).IsMeasured())
                     {
                         CRect rawRect = annotData.Annot.GetRect();
                         Rect rect = DataConversionForWPF.CRectConversionForRect(rawRect);
@@ -220,7 +229,7 @@ namespace ComPDFKit.Tool.DrawTool
                             );
                         activePoints.Add(point);
                     }
-                    if ((annotData.Annot as CPDFPolylineAnnotation).IsMersured())
+                    if ((annotData.Annot as CPDFPolylineAnnotation).IsMeasured())
                     {
                         CRect rawRect = annotData.Annot.GetRect();
                         Rect rect = DataConversionForWPF.CRectConversionForRect(rawRect);
@@ -309,16 +318,16 @@ namespace ComPDFKit.Tool.DrawTool
             crossLine.Clear();
             rightLine.Clear();
             CPDFDistanceMeasure LineMeasure = Annot.GetDistanceMeasure();
-            double LeadLength = LineMeasure.GetLeadLength() / 72D * 96D;
-            double LeadOffset = LineMeasure.GetLeadOffset() / 72D * 96D;
-            double LeadExtension = LineMeasure.GetLeadExtension() / 72D * 96D;
+            double LeadLength = LineMeasure.GetLeadLength() / 72D * 96D * annotData.CurrentZoom;
+            double LeadOffset = LineMeasure.GetLeadOffset() / 72D * 96D * annotData.CurrentZoom;
+            double LeadExtension = LineMeasure.GetLeadExtension() / 72D * 96D * annotData.CurrentZoom;
 
             List<Point> orderPoints = activePoints.AsEnumerable().OrderBy(x => x.X).ToList();
-            Vector lineVector = (activePoints[1] - activePoints[0]) * annotData.CurrentZoom;
+            Vector lineVector = (activePoints[1] - activePoints[0]) ;
             lineVector.Normalize();
-            Vector leadEndVector = lineVector * (Math.Abs(LeadLength) + Math.Abs(LeadOffset) + Math.Abs(LeadExtension) * annotData.CurrentZoom);
-            Vector leadStartVector = lineVector * (Math.Abs(LeadOffset)) * annotData.CurrentZoom;
-            Vector leadCrossVector = lineVector * (Math.Abs(LeadLength)  * annotData.CurrentZoom + Math.Abs(LeadOffset));
+            Vector leadEndVector = lineVector * (Math.Abs(LeadLength) + Math.Abs(LeadOffset) + Math.Abs(LeadExtension));
+            Vector leadStartVector = lineVector * (Math.Abs(LeadOffset));
+            Vector leadCrossVector = lineVector * (Math.Abs(LeadLength) + Math.Abs(LeadOffset));
             Matrix rotateMatrix = new Matrix();
             double angle = LeadLength < 0 ? 90 : -90;
             rotateMatrix.Rotate(angle);
@@ -327,12 +336,12 @@ namespace ComPDFKit.Tool.DrawTool
             Point leftCrossPoint = rotateMatrix.Transform(leadCrossVector) + activePoints[0];
 
             leftLine.Add(leftStartPoint);
-            leftLine.Add(leftCrossPoint);
+            leftLine.Add(leftEndPoint);
             crossLine.Add(leftCrossPoint);
 
             lineVector = activePoints[1] - activePoints[0];
             rightLine.Add(leftStartPoint + lineVector);
-            rightLine.Add(leftCrossPoint + lineVector);
+            rightLine.Add(leftEndPoint + lineVector);
             crossLine.Add(leftCrossPoint + lineVector);
             activePoints.Insert(1, new Point(
                 (crossLine[0].X + crossLine[1].X) / 2,
@@ -348,6 +357,7 @@ namespace ComPDFKit.Tool.DrawTool
             hitIndex = -1;
             mouseDownPoint = downPoint;
             moveOffset = new Point(0, 0);
+            LineMeasureOffset=new Point(0, 0);
             HitTestResult hitResult = VisualTreeHelper.HitTest(this, downPoint);
             if (hitResult != null && hitResult.VisualHit is DrawingVisual)
             {
@@ -358,7 +368,7 @@ namespace ComPDFKit.Tool.DrawTool
         public virtual void OnMouseMove(Point mousePoint, out bool Tag)
         {
             Tag = false;
-            if (isMouseDown)
+            if (Mouse.LeftButton==MouseButtonState.Pressed)
             {
                 Tag = isMouseDown;
                 mouseEndDrawPoint = mousePoint;
@@ -369,6 +379,7 @@ namespace ComPDFKit.Tool.DrawTool
                     );
 
                 Point movePoint = CheckMoveOffSet(activePoints.ToList(), maxRect, newOffset);
+                LineMeasureOffset=newOffset;
                 if(movePoint.X==0)
                 {
                     newOffset.X=moveOffset.X;
@@ -389,7 +400,7 @@ namespace ComPDFKit.Tool.DrawTool
             Draw();
             if (annotData!=null&&annotData.AnnotType == C_ANNOTATION_TYPE.C_ANNOTATION_LINE)
             {
-                if ((annotData.Annot as CPDFLineAnnotation).IsMersured())
+                if ((annotData.Annot as CPDFLineAnnotation).IsMeasured())
                 {
                     activePoints.Clear();
 
@@ -443,7 +454,7 @@ namespace ComPDFKit.Tool.DrawTool
                 {
                     if (annotData.AnnotType == C_ANNOTATION_TYPE.C_ANNOTATION_LINE)
                     {
-                        if (!(annotData.Annot as CPDFLineAnnotation).IsMersured())
+                        if (!(annotData.Annot as CPDFLineAnnotation).IsMeasured())
                         {
                             currentPoint.X += moveOffset.X;
                             currentPoint.Y += moveOffset.Y;
@@ -486,7 +497,7 @@ namespace ComPDFKit.Tool.DrawTool
                 {
                     case C_ANNOTATION_TYPE.C_ANNOTATION_LINE:
                         {
-                            if ((annotData.Annot as CPDFLineAnnotation).IsMersured())
+                            if ((annotData.Annot as CPDFLineAnnotation).IsMeasured())
                             {
                                 DrawLineMeasure(drawDC);
                             }
@@ -625,23 +636,30 @@ namespace ComPDFKit.Tool.DrawTool
             }
         }
 
-        private void DrawLineMeasure(DrawingContext drawingContext)
+        private Point CalcRotateBound(Point rawPoint, Point moveOffset)
+        {
+            Point newPoint = rawPoint;
+            Rect checkRect = annotData.PaintOffset;
+            newPoint.X += moveOffset.X;
+            newPoint.Y += moveOffset.Y;
+            newPoint.X = Math.Max(checkRect.Left, newPoint.X);
+            newPoint.X = Math.Min(checkRect.Right, newPoint.X);
+            newPoint.Y = Math.Max(checkRect.Top, newPoint.Y);
+            newPoint.Y = Math.Min(checkRect.Bottom, newPoint.Y);
+
+            return newPoint;
+        }
+
+        private void DrawLineMeasure(DrawingContext drawDC)
         {
-            foreach (Point controlPoint in activePoints)
-            {
-                Point drawPoint = new Point(
-                    controlPoint.X,
-                    controlPoint.Y);
-                if (hitIndex == -1)
-                {
-                    drawPoint.X += moveOffset.X;
-                    drawPoint.Y += moveOffset.Y;
-                }
-                drawingContext?.DrawEllipse(drawParam.EditControlLineBrush, drawParam.EditControlLinePen, (drawPoint), pointSize, pointSize);
-            }
             Rect drawRect = activeRect;
             drawRect.X += moveOffset.X;
             drawRect.Y += moveOffset.Y;
+
+            Point[] drawLeftLine = leftLine.ToArray();
+            Point[] drawRightLine = rightLine.ToArray();
+            Point[] drawCrossLine = crossLine.ToArray();
+
             if (isMouseDown)
             {
                 PointCollection drawLeftPoints = new PointCollection();
@@ -650,44 +668,52 @@ namespace ComPDFKit.Tool.DrawTool
                 moveLeftLine = leftLine.ToArray();
                 moveRightLine = rightLine.ToArray();
                 moveCrossLine = crossLine.ToArray();
-                switch (hitIndex)
-                { 
-                    case 0://Left
-                        {
-                            moveLeftLine[0].X += moveOffset.X;
-                            moveLeftLine[0].Y += moveOffset.Y;
+                foreach(Point checkPoint in moveLeftLine)
+                {
+                    drawLeftPoints.Add(checkPoint);
+                }
 
-                            moveLeftLine[0].X = Math.Max(maxRect.Left, moveLeftLine[0].X);
-                            moveLeftLine[0].X = Math.Min(maxRect.Right, moveLeftLine[0].X);
-                            moveLeftLine[0].Y = Math.Max(maxRect.Top, moveLeftLine[0].Y);
-                            moveLeftLine[0].Y = Math.Min(maxRect.Bottom, moveLeftLine[0].Y);
+                foreach (Point checkPoint in moveRightLine)
+                {
+                    drawRightPoints.Add(checkPoint);
+                }
 
-                            Vector newVector = moveLeftLine[0] - rightLine[0];
-                            Vector leftVector = leftLine[1] - leftLine[0];
+                foreach (Point checkPoint in moveCrossLine)
+                {
+                    drawCrossPoints.Add(checkPoint);
+                }
 
-                            double angle = leftLine[0].Y < crossLine[0].Y ? -90 : 90;
+                switch (hitIndex)
+                {
+                    case 0:
+                        {
+                            moveLeftLine[0] = CalcRotateBound(drawLeftPoints[0], LineMeasureOffset);
+
+                            Vector newVector = moveLeftLine[0] - drawRightPoints[0];
+                            Vector leftVector = drawLeftPoints[1] - drawLeftPoints[0];
+                            double angle = drawLeftPoints[0].Y < drawCrossPoints[0].Y ? -90 : 90;
                             newVector.Normalize();
                             newVector = newVector * leftVector.Length;
                             Matrix rotateMatrix = new Matrix();
                             rotateMatrix.Rotate(angle);
+                            moveRightLine[0] = drawRightPoints[0];
                             moveLeftLine[1] = moveLeftLine[0] + newVector * rotateMatrix;
-                            moveRightLine[0] = rightLine[0];
                             moveRightLine[1] = moveRightLine[0] + newVector * rotateMatrix;
+
                             moveCrossLine[0] = moveLeftLine[1];
                             moveCrossLine[1] = moveRightLine[1];
+
+                            drawDC?.DrawLine(drawParam.EditLinePen, moveLeftLine[0], moveLeftLine[1]);
+                            drawDC?.DrawLine(drawParam.EditLinePen, moveRightLine[0], moveRightLine[1]);
+                            drawDC?.DrawLine(drawParam.EditLinePen, moveLeftLine[1], moveRightLine[1]);
                         }
                         break;
-                    case 1:// Center
+                    case 1:
                         {
-                            Point centerPoint = new Point(
-                            (crossLine[0].X + crossLine[1].X) / 2,
-                            (crossLine[0].Y + crossLine[1].Y) / 2
-                            );
-                            Point movePoint = new Point(centerPoint.X, centerPoint.Y);
-                            movePoint.X += moveOffset.X;
-                            movePoint.Y += moveOffset.Y;
-                            Vector ruleVector = crossLine[1] - crossLine[0];
+                            Point centerPoint = new Point((drawCrossPoints[0].X + drawCrossPoints[1].X) / 2,(drawCrossPoints[0].Y + drawCrossPoints[1].Y) / 2);
 
+                            Point movePoint = CalcRotateBound(centerPoint, LineMeasureOffset);
+                            Vector ruleVector = drawCrossPoints[1] - drawCrossPoints[0];
                             bool rateMove = true;
                             if (ruleVector.X == 0)
                             {
@@ -699,6 +725,7 @@ namespace ComPDFKit.Tool.DrawTool
                                 movePoint.X = centerPoint.X;
                                 rateMove = false;
                             }
+
                             if (rateMove)
                             {
                                 Vector moveVector = movePoint - centerPoint;
@@ -722,99 +749,151 @@ namespace ComPDFKit.Tool.DrawTool
                                 moveCrossLine[1] = SaveRight;
                                 moveLeftLine[1] = saveLeft;
                                 moveRightLine[1] = SaveRight;
-                                moveLeftLine[0] = leftLine[0];
-                                moveRightLine[0] = rightLine[0];
+                                moveLeftLine[0] = drawLeftPoints[0];
+                                moveRightLine[0] = drawRightPoints[0];
                             }
                             else
                             {
                                 Point moveOffset = new Point(
                                     movePoint.X - centerPoint.X,
                                     movePoint.Y - centerPoint.Y);
-                                moveCrossLine[0].X += moveOffset.X;
-                                moveCrossLine[0].Y += moveOffset.Y;
-                                moveCrossLine[1].X += moveOffset.X;
-                                moveCrossLine[1].Y += moveOffset.Y;
 
-                                moveLeftLine[1].X += moveOffset.X;
-                                moveLeftLine[1].Y += moveOffset.Y;
+                                moveCrossLine[0] = new Point(
+                                    drawCrossPoints[0].X + moveOffset.X,
+                                    drawCrossPoints[0].Y + moveOffset.Y);
+                                moveCrossLine[1] = new Point(
+                                    drawCrossPoints[1].X + moveOffset.X,
+                                    drawCrossPoints[1].Y + moveOffset.Y);
+
+                                moveLeftLine[0] = drawLeftPoints[0];
+                                moveRightLine[0] = drawRightPoints[0];
 
-                                moveRightLine[1].X += moveOffset.X;
-                                moveRightLine[1].Y += moveOffset.Y;
+                                moveLeftLine[1] = new Point(
+                                    drawLeftPoints[1].X + moveOffset.X,
+                                    drawLeftPoints[1].Y + moveOffset.Y);
+
+                                moveRightLine[1] = new Point(
+                                   drawRightPoints[1].X + moveOffset.X,
+                                   drawRightPoints[1].Y + moveOffset.Y);
                             }
 
+                            drawDC?.DrawLine(drawParam.EditLinePen, moveCrossLine[0], moveCrossLine[1]);
+                            drawDC?.DrawLine(drawParam.EditLinePen, moveCrossLine[0], moveLeftLine[0]);
+                            drawDC?.DrawLine(drawParam.EditLinePen, moveCrossLine[1], moveRightLine[0]);
                         }
                         break;
-                    case 2://Right
+                    case 2:
                         {
-                            moveRightLine[0].X += moveOffset.X;
-                            moveRightLine[0].Y += moveOffset.Y;
-
-                            Vector newVector = moveRightLine[0] - leftLine[0];
-                            Vector leftVector = rightLine[1] - rightLine[0];
-
-                            double angle = (rightLine[0].Y + leftLine[0].Y) / 2 > (crossLine[0].Y + crossLine[1].Y) / 2 ? -90 : 90;
+                            moveRightLine[0] = CalcRotateBound(drawRightPoints[0], LineMeasureOffset);
+                            Vector newVector = moveRightLine[0] - drawLeftPoints[0];
+                            Vector rightVector = drawRightPoints[1] - drawRightPoints[0];
+                            double angle = (drawRightPoints[0].Y + drawLeftPoints[0].Y) / 2 > (drawCrossPoints[0].Y + drawCrossPoints[1].Y) / 2 ? -90 : 90;
                             newVector.Normalize();
-                            newVector = newVector * leftVector.Length;
+                            newVector = newVector * rightVector.Length;
                             Matrix rotateMatrix = new Matrix();
                             rotateMatrix.Rotate(angle);
+                            moveLeftLine[0] = drawLeftPoints[0];
                             moveLeftLine[1] = moveLeftLine[0] + newVector * rotateMatrix;
-                            moveLeftLine[0] = leftLine[0];
                             moveRightLine[1] = moveRightLine[0] + newVector * rotateMatrix;
+
                             moveCrossLine[0] = moveLeftLine[1];
                             moveCrossLine[1] = moveRightLine[1];
+
+                            drawDC?.DrawLine(drawParam.EditLinePen, moveLeftLine[0], moveLeftLine[1]);
+                            drawDC?.DrawLine(drawParam.EditLinePen, moveRightLine[0], moveRightLine[1]);
+                            drawDC?.DrawLine(drawParam.EditLinePen, moveLeftLine[1], moveRightLine[1]);
                         }
                         break;
                     case -1:
-                        moveLeftLine[0].X += moveOffset.X;
-                        moveLeftLine[0].Y += moveOffset.Y;
-                        moveLeftLine[1].X += moveOffset.X;
-                        moveLeftLine[1].Y += moveOffset.Y;
-
-                        moveRightLine[0].X += moveOffset.X;
-                        moveRightLine[0].Y += moveOffset.Y;
-                        moveRightLine[1].X += moveOffset.X;
-                        moveRightLine[1].Y += moveOffset.Y;
-
-                        moveCrossLine[0] = moveLeftLine[1];
-                        moveCrossLine[1] = moveRightLine[1];
+                        {
+                            Rect moveRect = new Rect(moveLeftLine[0], moveRightLine[1]);
+                            moveRect.Union(moveLeftLine[1]);
+                            moveRect.Union(moveRightLine[0]);
+                            Point moveOffset = LineMeasureOffset;
+                            Rect pageBound = annotData.PaintOffset;
+                            if (moveRect.Left + LineMeasureOffset.X < pageBound.Left)
+                            {
+                                moveOffset.X = pageBound.Left - moveRect.Left;
+                            }
+                            if (moveRect.Right + moveOffset.X > pageBound.Right)
+                            {
+                                moveOffset.X = pageBound.Right - moveRect.Right;
+                            }
+                            if (moveRect.Top + moveOffset.Y < pageBound.Top)
+                            {
+                                moveOffset.Y = pageBound.Top - moveRect.Top;
+                            }
+                            if (moveRect.Bottom + moveOffset.Y > pageBound.Bottom)
+                            {
+                                moveOffset.Y = pageBound.Bottom - moveRect.Bottom;
+                            }
+
+                            moveLeftLine[0].X = moveLeftLine[0].X + moveOffset.X;
+                            moveLeftLine[0].Y = moveLeftLine[0].Y + moveOffset.Y;
+
+                            moveLeftLine[1].X = moveLeftLine[1].X + moveOffset.X;
+                            moveLeftLine[1].Y = moveLeftLine[1].Y + moveOffset.Y;
+
+                            moveRightLine[0].X = moveRightLine[0].X + moveOffset.X;
+                            moveRightLine[0].Y = moveRightLine[0].Y + moveOffset.Y;
+
+                            moveRightLine[1].X = moveRightLine[1].X + moveOffset.X;
+                            moveRightLine[1].Y = moveRightLine[1].Y + moveOffset.Y;
+
+                            moveCrossLine[0].X = moveCrossLine[0].X + moveOffset.X;
+                            moveCrossLine[0].Y = moveCrossLine[0].Y + moveOffset.Y;
+
+                            moveCrossLine[1].X = moveCrossLine[1].X + moveOffset.X;
+                            moveCrossLine[1].Y = moveCrossLine[1].Y + moveOffset.Y;
+
+                            drawDC?.DrawLine(drawParam.EditLinePen, moveLeftLine[0], moveLeftLine[1]);
+                            drawDC?.DrawLine(drawParam.EditLinePen, moveRightLine[0], moveRightLine[1]);
+                            drawDC?.DrawLine(drawParam.EditLinePen, moveCrossLine[0], moveCrossLine[1]);
+                        }
                         break;
                     default:
                         break;
                 }
-                //Left
-                drawLeftPoints.Add(new Point(
-                    moveLeftLine[0].X,
-                    moveLeftLine[0].Y));
-                drawLeftPoints.Add(new Point(
-                   moveLeftLine[1].X,
-                   moveLeftLine[1].Y));
-
-                //Right
-                drawRightPoints.Add(new Point(
-                    moveRightLine[0].X,
-                    moveRightLine[0].Y));
-                drawRightPoints.Add(new Point(
-                   moveRightLine[1].X,
-                   moveRightLine[1].Y));
-
-                //Middle
-                drawCrossPoints.Add(new Point(
-                    moveCrossLine[0].X,
-                    moveCrossLine[0].Y));
-
-                drawCrossPoints.Add(new Point(
-                    moveCrossLine[1].X,
-                    moveCrossLine[1].Y));
-
-
-                drawingContext?.DrawLine(drawParam.EditLinePen, drawLeftPoints[0], drawLeftPoints[1]);
-                drawingContext?.DrawLine(drawParam.EditLinePen, drawRightPoints[0], drawRightPoints[1]);
-                drawingContext?.DrawLine(drawParam.EditLinePen, drawCrossPoints[0], drawCrossPoints[1]);
+
+
+                if (moveLeftLine[0].X > moveRightLine[0].X)
+                {
+                    Point tmpPoint = moveRightLine[0];
+                    moveRightLine[0] = moveLeftLine[0];
+                    moveLeftLine[0] = tmpPoint;
+                }
+
+                if (moveLeftLine[1].X > moveRightLine[1].X)
+                {
+                    Point tmpPoint = moveRightLine[1];
+                    moveRightLine[1] = moveLeftLine[1];
+                    moveLeftLine[1] = tmpPoint;
+                }
+
+                if (moveCrossLine[0].X > moveCrossLine[1].X)
+                {
+                    Point tmpPoint = moveCrossLine[1];
+                    moveCrossLine[1] = moveCrossLine[0];
+                    moveCrossLine[0] = tmpPoint;
+                }
+
+                drawLeftLine=moveLeftLine;
+                drawRightLine=moveRightLine;
+                drawCrossLine=moveCrossLine;
             }
-            else
+
+            if(isMouseDown==false)
             {
-                drawingContext?.DrawRectangle(null, drawParam.EditLinePen, drawRect);
+                drawDC?.DrawRectangle(null, drawParam.EditControlLinePen, activeRect);
             }
+
+            Point moveCenterPoint = new Point(
+                (drawCrossLine[0].X + drawCrossLine[1].X) / 2,
+                (drawCrossLine[0].Y + drawCrossLine[1].Y) / 2
+                );
+            drawDC?.DrawEllipse(drawParam.EditControlLineBrush, drawParam.EditControlLinePen, drawLeftLine[0], pointSize, pointSize);
+            drawDC?.DrawEllipse(drawParam.EditControlLineBrush, drawParam.EditControlLinePen, drawRightLine[0], pointSize, pointSize);
+            drawDC?.DrawEllipse(drawParam.EditControlLineBrush, drawParam.EditControlLinePen, moveCenterPoint, pointSize, pointSize);
         }
 
         private void DrawPolyLineMeasure(DrawingContext drawingContext)

+ 210 - 0
Demo/Examples/ComPDFKit.Tool/DrawTool/AnnotSelector.cs

@@ -0,0 +1,210 @@
+using ComPDFKitViewer;
+using ComPDFKitViewer.Layer;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Media;
+
+namespace ComPDFKit.Tool.DrawTool
+{
+    internal class AnnotSelector:BaseLayer
+    {
+        public CPDFViewer PDFViewer { get; set; }
+        public List<AnnotData> SelectAnnots { get; set; } = new List<AnnotData>();
+        public Pen DrawPen { get; set; }
+        public Brush DrawBrush { get; set; }
+        private List<Point> ControlPoints { get; set; } = new List<Point>();
+        private double RectPadding = 4;
+        public AnnotSelector()
+        {
+            DrawPen = new Pen(new SolidColorBrush(Color.FromArgb(255, 71, 126, 222)), 2);
+            DrawBrush = new SolidColorBrush(Color.FromArgb(40, 119, 180, 227));
+        }
+        public override void Draw()
+        {
+            DrawingContext drawDC = Open();
+            DrawOutBound(drawDC);
+            DrawIndividual(drawDC);
+            DrawControlPoint(drawDC);
+            Present();
+        }
+
+        public int GetSelectCount()
+        {
+            if(SelectAnnots!=null)
+            {
+                return SelectAnnots.Count;
+            }
+            return 0;
+        }
+        public bool AddItem(AnnotData item)
+        {
+            if (item == null)
+            {
+                return false;
+            }
+            List<int> pageIndexList = SelectAnnots.Select(x => x.PageIndex).Distinct().ToList();
+            if(pageIndexList.Count > 1 )
+            {
+                SelectAnnots.Clear();
+            }
+
+            if( pageIndexList.Count==1 && pageIndexList[0]!=item.PageIndex)
+            {
+                SelectAnnots.Clear();
+            }
+
+            if (RemoveItem(item))
+            {
+                SelectAnnots.Add(item);
+                return true;
+            }
+            return false;
+        }
+        public bool HasItem(AnnotData item)
+        {
+            if (item == null)
+            {
+                return false;
+            }
+
+            if(SelectAnnots!=null && SelectAnnots.Count > 0)
+            {
+                return SelectAnnots.Where(x => x.AnnotIndex == item.AnnotIndex && x.PageIndex == item.PageIndex).Count() > 0;
+            }
+
+            return false;
+        }
+
+        public bool RemoveItem(AnnotData item)
+        {
+            if (item == null || item.PageIndex < 0 || item.AnnotIndex < 0)
+            {
+                return false;
+            }
+
+            List<AnnotData> checkList = SelectAnnots.Where(x => x.AnnotIndex == item.AnnotIndex && x.PageIndex == item.PageIndex).ToList();
+            if (checkList != null && checkList.Count > 0)
+            {
+                foreach (AnnotData removeItem in checkList)
+                {
+                    SelectAnnots.Remove(removeItem);
+                }
+            }
+            return true;
+        }
+
+        public void ClearItem()
+        { 
+            SelectAnnots?.Clear(); 
+        }
+        public Rect GetOutBoundRect()
+        {
+            if (SelectAnnots.Count > 0)
+            {
+                double left = 0;
+                double top = 0;
+                double right = 0;
+                double bottom = 0;
+
+                for (int i=0;i< SelectAnnots.Count;i++)
+                {
+                   AnnotData checkItem= SelectAnnots[i];
+                    if (i == 0) 
+                    {
+                        left=checkItem.PaintRect.Left;
+                        top=checkItem.PaintRect.Top;
+                        right=checkItem.PaintRect.Right;
+                        bottom=checkItem.PaintRect.Bottom;
+                        continue;
+                    }
+
+                    left = Math.Min(left, checkItem.PaintRect.Left);
+                    top = Math.Min(top, checkItem.PaintRect.Top);
+                    right = Math.Max(right, checkItem.PaintRect.Right);
+                    bottom = Math.Max(bottom, checkItem.PaintRect.Bottom);
+                }
+
+                if(right<left ||  bottom<top)
+                {
+                    return Rect.Empty;
+                }
+
+                return new Rect(left, top, right-left, bottom-top);
+            }
+           
+            return Rect.Empty;
+        }
+
+        public void DrawOutBound(DrawingContext drawDC) 
+        {
+            Rect boudRect = GetOutBoundRect();
+            if (boudRect.IsEmpty || boudRect.Width == 0 || boudRect.Height == 0)
+            { 
+                return;
+            }
+
+            drawDC.DrawRectangle(Brushes.Transparent, DrawPen, boudRect);
+        }
+
+        public void DrawIndividual(DrawingContext drawDC)
+        {
+            if(SelectAnnots==null || SelectAnnots.Count==0)
+            {
+                return;
+            }
+
+            foreach(AnnotData checkItem in SelectAnnots)
+            {
+                drawDC.DrawRectangle(null, DrawPen, checkItem.PaintRect);
+            }
+        }
+
+        public void DrawControlPoint(DrawingContext drawDC)
+        {
+            Rect boudRect = GetOutBoundRect();
+            ControlPoints.Clear();
+            double centerX = (boudRect.Left + boudRect.Right) / 2;
+            double centerY = (boudRect.Top + boudRect.Bottom) / 2;
+
+            ControlPoints.Add(new Point(boudRect.Left, boudRect.Top));
+            ControlPoints.Add(new Point(boudRect.Left, centerY));
+            ControlPoints.Add(new Point(boudRect.Left, boudRect.Bottom));
+            ControlPoints.Add(new Point(centerX, boudRect.Bottom));
+            ControlPoints.Add(new Point(boudRect.Right, boudRect.Bottom));
+            ControlPoints.Add(new Point(boudRect.Right, centerY));
+            ControlPoints.Add(new Point(boudRect.Right, boudRect.Top));
+            ControlPoints.Add(new Point(centerX, boudRect.Top));
+
+            foreach (Point point in ControlPoints)
+            {
+                drawDC.DrawRectangle(Brushes.White, DrawPen, new Rect(point.X- RectPadding,point.Y- RectPadding, RectPadding*2, RectPadding*2));
+            }
+        }
+
+        public PointControlType GetHitControlIndex(Point point)
+        {
+            for (int i = 0; i < ControlPoints.Count; i++)
+            {
+                Point checkPoint = ControlPoints[i];
+                Rect checkBound = new Rect(checkPoint.X - RectPadding, checkPoint.Y - RectPadding, RectPadding * 2, RectPadding * 2);
+                if (checkBound.Contains(point))
+                {
+                    return (PointControlType)i;
+                }
+            }
+
+            Rect outBound = GetOutBoundRect();
+            if (outBound.Contains(point))
+            {
+                return PointControlType.Body;
+            }
+
+            return PointControlType.None;
+        }
+    }
+}

+ 61 - 18
Demo/Examples/ComPDFKit.Tool/DrawTool/CreateAnnotTool.cs

@@ -28,6 +28,7 @@ using System.Windows.Input;
 using System.Windows.Media;
 using System.Windows.Media.Animation;
 using System.Windows.Media.Media3D;
+using System.Windows.Shapes;
 using static ComPDFKit.PDFAnnotation.CTextAttribute.CFontNameHelper;
 using static ComPDFKit.Tool.Help.ImportWin32;
 
@@ -87,6 +88,7 @@ namespace ComPDFKit.Tool.DrawTool
         /// The rectangle representing the original page range (calculated offset in continuous mode)
         /// </summary>
         protected Rect pageBound { get; set; }
+        protected int pageIndex { get; set; } = -1;
 
         /// <summary>
         /// The rectangle at standard DPI (without subtracting half of the pen thickness)
@@ -245,6 +247,7 @@ namespace ComPDFKit.Tool.DrawTool
         {
             RemoveTextBox();
             mouseStartPoint = downPoint;
+            mouseEndPoint = downPoint;
             isDrawAnnot = true;
             this.maxRect = maxRect;
             zoomFactor = zoom;
@@ -261,6 +264,7 @@ namespace ComPDFKit.Tool.DrawTool
                 drawPoints.Add(downPoint);
                 this.cropPoint = cropPoint;
                 this.pageBound = pageBound;
+                this.pageIndex = cPDFPage.PageIndex;
                 DPIRect = new Rect();
                 if (annotType != C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON)
                 {
@@ -308,6 +312,7 @@ namespace ComPDFKit.Tool.DrawTool
                 mouseEndPoint = new Point();
                 moveOffset = new Point();
                 pageBound = new Rect();
+                pageIndex = -1;
                 DPIRect = new Rect();
                 cPDFAnnotation = null;
                 inkDrawPoints.Clear();
@@ -338,7 +343,7 @@ namespace ComPDFKit.Tool.DrawTool
                         DrawText();
                         break;
                     case C_ANNOTATION_TYPE.C_ANNOTATION_LINE:
-                        if ((cPDFAnnotation as CPDFLineAnnotation).IsMersured())
+                        if ((cPDFAnnotation as CPDFLineAnnotation).IsMeasured())
                         {
                             DrawLineMeasure(drawDC);
                         }
@@ -680,6 +685,16 @@ namespace ComPDFKit.Tool.DrawTool
                 lineSegment.IsSmoothJoin = true;
                 pathFigure.Segments.Add(lineSegment);
             }
+            if(annotLine.Dash!=null && annotLine.Dash.Length>0)
+            {
+                DashStyle dash = new DashStyle();
+                foreach (var offset in annotLine.Dash)
+                {
+                    dash.Dashes.Add(offset);
+                }
+                DrawPen.DashStyle = dash;
+                DrawPen.DashCap = PenLineCap.Flat;
+            }
             Rect checkRect = pageBound;
             RectangleGeometry rectGeometry = new RectangleGeometry();
             drawRect = rectGeometry.Rect = checkRect;
@@ -859,7 +874,7 @@ namespace ComPDFKit.Tool.DrawTool
             Pen DrawPen = new Pen(new SolidColorBrush(color), polyLine.GetBorderWidth());
             SolidColorBrush TextBrush = Brushes.Red;
 
-            if (polyLine.IsMersured())
+            if (polyLine.IsMeasured())
             {
                 CPDFPerimeterMeasure measureInfo = polyLine.GetPerimeterMeasure();
                 if (measureInfo != null && measureInfo.TextAttribute != null && measureInfo.TextAttribute.FontColor != null && measureInfo.TextAttribute.FontColor.Length >= 3)
@@ -1042,7 +1057,7 @@ namespace ComPDFKit.Tool.DrawTool
             Pen EndDrawPen = new Pen(Brushes.Black, polyLine.GetBorderWidth());
             SolidColorBrush TextBrush = Brushes.Red;
 
-            if (polyLine.IsMersured())
+            if (polyLine.IsMeasured())
             {
                 CPDFAreaMeasure measureInfo = polyLine.GetAreaMeasure();
                 if (measureInfo != null && measureInfo.TextAttribute != null && measureInfo.TextAttribute.FontColor != null && measureInfo.TextAttribute.FontColor.Length >= 3)
@@ -1307,7 +1322,7 @@ namespace ComPDFKit.Tool.DrawTool
             Pen DrawPen = new Pen(new SolidColorBrush(color), polyLine.GetBorderWidth());
             SolidColorBrush TextBrush = Brushes.Red;
 
-            if (polyLine.IsMersured())
+            if (polyLine.IsMeasured())
             {
                 CPDFDistanceMeasure measureInfo = polyLine.GetDistanceMeasure();
                 if (measureInfo != null && measureInfo.TextAttribute != null && measureInfo.TextAttribute.FontColor != null && measureInfo.TextAttribute.FontColor.Length >= 3)
@@ -1432,9 +1447,12 @@ namespace ComPDFKit.Tool.DrawTool
         }
 
         #endregion
-        public void MultipleClick(Point downPoint)
+        public void MultipleClick(Point downPoint,int pageIndex)
         {
-            drawPoints.Add(downPoint);
+            if(pageIndex==this.pageIndex)
+            {
+                drawPoints.Add(downPoint);
+            }
         }
 
         public Rect GetMaxRect()
@@ -1451,8 +1469,7 @@ namespace ComPDFKit.Tool.DrawTool
                     CPDFFreeTextAnnotation annotFreeText = (cPDFAnnotation as CPDFFreeTextAnnotation);
 
                     TextBox textui = new TextBox();
-
-                    Border textBorder = new Border();
+                    DashedBorder textBorder = new DashedBorder();
                     textBorder.Child = textui;
                    
                     CTextAttribute textAttribute = annotFreeText.FreeTextDa;
@@ -1517,14 +1534,27 @@ namespace ComPDFKit.Tool.DrawTool
 
                     textBorder.Padding = new Thickness(0);
                     textBorder.BorderBrush = new SolidColorBrush(borderColor);
-                    textBorder.BorderThickness = new Thickness(DpiHelper.PDFNumToStandardNum(annotFreeText.GetBorderWidth() * zoomFactor));
+                    double rawWidth = annotFreeText.GetBorderWidth();
+                    double drawWidth = DpiHelper.PDFNumToStandardNum(rawWidth * zoomFactor);
+                    textBorder.BorderThickness = new Thickness(drawWidth);
+                    if (annotFreeText.BorderStyle != C_BORDER_STYLE.BS_SOLID && annotFreeText.Dash != null && annotFreeText.Dash.Length > 0)
+                    {
+                        //补充保存虚线样式
+                        DoubleCollection dashCollection = new DoubleCollection();
+                        foreach (float num in annotFreeText.Dash)
+                        {
+                            dashCollection.Add(num);
+                        }
+                        textBorder?.DrawDashBorder(true, drawWidth,rawWidth, dashCollection);
+                    }
+
                     textui.BorderThickness = new Thickness(0);
                     textui.Text = annotFreeText.Content;
 
-                    string fontName = string.Empty;
-                    string fontFamily = string.Empty;
-                    CPDFFont.GetFamilyStyleName(annotFreeText.FreeTextDa.FontName, ref fontFamily, ref fontName);
-                    textui.FontFamily = new FontFamily(fontFamily);
+                    //string fontName = string.Empty;
+                    //string fontFamily = string.Empty;
+                    //CPDFFont.GetFamilyStyleName(annotFreeText.FreeTextDa.FontName, ref fontFamily, ref fontName);
+                    textui.FontFamily = new FontFamily(annotFreeText.FreeTextDa.FontName + ",Microsoft YaHei");
 
                     textui.AcceptsReturn = true;
                     textui.TextWrapping = TextWrapping.Wrap;
@@ -1746,15 +1776,28 @@ namespace ComPDFKit.Tool.DrawTool
                     lastTextui.Background = new SolidColorBrush(backgroundColor);
                     lastTextBorder.Padding = new Thickness(0);
                     lastTextBorder.BorderBrush = new SolidColorBrush(borderColor);
-                    lastTextBorder.BorderThickness = new Thickness(DpiHelper.PDFNumToStandardNum(annotFreeText.GetBorderWidth() * zoomFactor));
+                    double rawWidth = annotFreeText.GetBorderWidth();
+                    double drawWidth = DpiHelper.PDFNumToStandardNum(rawWidth * zoomFactor);
+                    lastTextBorder.BorderThickness = new Thickness(drawWidth);
                     lastTextui.BorderThickness = new Thickness(0);
                     lastTextui.Text = annotFreeText.Content;
                     lastTextui.Opacity = annotFreeText.Transparency;
+                    if (annotFreeText.BorderStyle != C_BORDER_STYLE.BS_SOLID && annotFreeText.Dash != null && annotFreeText.Dash.Length > 0)
+                    {
+                        //补充保存虚线样式
+                        DashedBorder dashBorder = (DashedBorder)lastTextBorder;
+                        DoubleCollection dashCollection = new DoubleCollection();
+                        foreach (float num in annotFreeText.Dash)
+                        {
+                            dashCollection.Add(num);
+                        }
+                        dashBorder.DrawDashBorder(true, drawWidth,rawWidth, dashCollection);
+                    }
 
-                    string fontName = string.Empty;
-                    string fontFamily = string.Empty;
-                    CPDFFont.GetFamilyStyleName(annotFreeText.FreeTextDa.FontName, ref fontFamily, ref fontName);
-                    lastTextui.FontFamily = new FontFamily(fontFamily);
+                    //string fontName = string.Empty;
+                    //string fontFamily = string.Empty;
+                    //CPDFFont.GetFamilyStyleName(annotFreeText.FreeTextDa.FontName, ref fontFamily, ref fontName);
+                    lastTextui.FontFamily = new FontFamily(annotFreeText.FreeTextDa.FontName + ",Microsoft YaHei");
 
                     lastTextui.FontWeight = IsBold(textAttribute.FontName) ? FontWeights.Bold : FontWeights.Normal;
                     lastTextui.FontStyle = IsItalic(textAttribute.FontName) ? FontStyles.Italic : FontStyles.Normal;

+ 16 - 1
Demo/Examples/ComPDFKit.Tool/DrawTool/CreateCustomizeTool.cs

@@ -67,6 +67,7 @@ namespace ComPDFKit.Tool.DrawTool
         /// Standard DPI rectangle (without removing half of the pen thickness)
         /// </summary>
         protected Rect DPIRect { get; set; }
+        internal int ErasePageIndex {  get; set; }
         public SolidColorBrush FillBrush;
         public Pen DrawPen;
         public event EventHandler<List<AnnotParam>> DeleteChanged;
@@ -272,8 +273,18 @@ namespace ComPDFKit.Tool.DrawTool
             GroupHistory historyGroup=new GroupHistory();
             CPDFDocument pdfDoc = PDFViewer?.GetDocument();
             List<AnnotParam> paramList = new List<AnnotParam>();
+            List<AnnotParam> paramNewList = new List<AnnotParam>();
+
+            PDFViewer.GetPointPageInfo(mouseEndPoint, out int index, out Rect checkpaintRect, out Rect checkpageBound);
+         
             foreach (var item in annotControlList)
             {
+                AnnotData coreAnnotData = item.GetAnnotData();
+
+                if (coreAnnotData == null || coreAnnotData.PageIndex != ErasePageIndex)
+                {
+                    continue;
+                }
                 InkAnnot ink = item as InkAnnot;
                 int Tag = ErasePoint(ink, eraseRect);
                 if (Tag == 1)
@@ -281,9 +292,11 @@ namespace ComPDFKit.Tool.DrawTool
                     CPDFAnnotation delAnnot = item.GetAnnotData().Annot;
                     AnnotHistory annotHistory = ParamConverter.CreateHistory(delAnnot);
                     AnnotParam annotParam = null;
+                    AnnotParam annotNewParam = null; 
                     if (pdfDoc != null)
                     {
                         annotParam = ParamConverter.CPDFDataConverterToAnnotParam(pdfDoc, delAnnot.Page.PageIndex, delAnnot);
+                        annotNewParam= ParamConverter.CPDFDataConverterToAnnotParam(pdfDoc, delAnnot.Page.PageIndex, delAnnot);
                         annotHistory.CurrentParam = annotParam;
                         annotHistory.Action=HistoryAction.Remove;
                         annotHistory.PDFDoc=pdfDoc;
@@ -295,6 +308,8 @@ namespace ComPDFKit.Tool.DrawTool
                         if(annotParam != null)
                         {
                             paramList.Add(annotParam);
+                            
+                            paramNewList.Add(annotNewParam);
                         }
                         historyGroup.Histories.Add(annotHistory);
                     }
@@ -307,7 +322,7 @@ namespace ComPDFKit.Tool.DrawTool
             }
             if(paramList.Count > 0)
             {
-                DeleteChanged?.Invoke(this, paramList);
+                DeleteChanged?.Invoke(this, paramNewList);
             }
         }
     }

+ 47 - 0
Demo/Examples/ComPDFKit.Tool/DrawTool/DashBorder.cs

@@ -0,0 +1,47 @@
+using ComPDFKitViewer.Annot;
+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.Media;
+using System.Windows.Shapes;
+
+namespace ComPDFKit.Tool.DrawTool
+{
+    internal class DashedBorder : Border
+    {
+        private bool DrawDash {  get; set; }
+        private double DashThickness {  get; set; }
+        private double DashWidth { get; set; }
+        private DoubleCollection DashArray { get; set; }
+        protected override void OnRender(DrawingContext dc)
+        {
+            if (DrawDash)
+            {
+                Pen dashPen = new Pen(BorderBrush, DashThickness);
+                dashPen.DashCap = PenLineCap.Flat;
+                DashStyle dash = new DashStyle();
+                foreach (double offset in DashArray)
+                {
+                    dash.Dashes.Add(offset / DashWidth);
+                }
+                dashPen.DashStyle = dash;
+                dc.DrawRectangle(null, dashPen, new Rect(0, 0, ActualWidth, ActualHeight));
+                return;
+            }
+            base.OnRender(dc);
+        }
+        public void DrawDashBorder(bool isDash,double dashWidth,double rawWidth, DoubleCollection dashArray)
+        {
+            DrawDash = isDash;
+            DashArray = dashArray;
+            DashThickness=dashWidth;
+            DashWidth=rawWidth;
+            InvalidateVisual();
+        }
+    }
+}

+ 450 - 0
Demo/Examples/ComPDFKit.Tool/DrawTool/FrameSelectTool.cs

@@ -0,0 +1,450 @@
+using ComPDFKit.Import;
+using ComPDFKit.Measure;
+using ComPDFKit.PDFAnnotation;
+using ComPDFKit.PDFDocument;
+using ComPDFKit.PDFPage;
+using ComPDFKit.Tool.Help;
+using ComPDFKit.Tool.SettingParam;
+using ComPDFKit.Tool.UndoManger;
+using ComPDFKit.Viewer.Helper;
+using ComPDFKit.Viewer.Layer;
+using ComPDFKitViewer;
+using ComPDFKitViewer.Annot;
+using ComPDFKitViewer.BaseObject;
+using ComPDFKitViewer.Helper;
+using ComPDFKitViewer.Layer;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.Linq;
+using System.Net;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Annotations;
+using System.Windows.Controls;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Animation;
+using System.Windows.Media.Media3D;
+using static ComPDFKit.PDFAnnotation.CTextAttribute.CFontNameHelper;
+using static ComPDFKit.Tool.Help.ImportWin32;
+
+namespace ComPDFKit.Tool.DrawTool
+{
+    internal class FrameSelectTool : CustomizeLayer
+    {
+
+        #region Attributes
+
+        /// <summary>
+        /// Indicates whether proportional scaling is required
+        /// </summary>
+        protected bool isProportionalScaling { get; set; } = false;
+
+        /// <summary>
+        /// Mouse start point
+        /// </summary>
+        protected Point mouseStartPoint { get; set; }
+
+        /// <summary>
+        /// Mouse end point
+        /// </summary>
+        protected Point mouseEndPoint { get; set; }
+
+        /// <summary>
+        /// Crop point
+        /// </summary>
+        protected Point cropPoint { get; set; }
+
+        /// <summary>
+        ///Is drawing annotation
+        /// </summary>
+        protected bool isFrameSelect { get; set; }
+
+        /// <summary>   
+        /// Current zoom factor
+        /// </summary>
+        private double zoomFactor { get; set; } = 1;
+
+        /// <summary>
+        /// Draw rectangle
+        /// </summary>
+        protected Rect drawRect { get; set; } = new Rect();
+
+        /// <summary> 
+        /// The rectangle representing the maximum drawing area
+        /// </summary>
+        protected Rect maxRect { get; set; }
+
+        /// <summary> 
+        /// The rectangle representing the original page range (calculated offset in continuous mode)
+        /// </summary>
+        protected Rect pageBound { get; set; }
+
+        /// <summary>
+        /// The rectangle at standard DPI (without subtracting half of the pen thickness)
+        /// </summary>
+        protected Rect DPIRect { get; set; }
+
+        /// <summary>
+        /// The offset value during movement
+        /// </summary>
+        protected Point moveOffset { get; set; } = new Point(0, 0);
+
+        /// <summary>
+        /// The offset value during movement
+        /// </summary>
+        protected int pageIndex { get; set; } = -1;
+
+        protected DrawingContext drawDC { get; set; }
+
+        /// <summary>
+        /// The collection of points measured for annotation drawing
+        /// </summary>
+        protected PointCollection drawPoints { get; set; } = new PointCollection();
+
+        protected double textPadding { get; set; } = 10;
+
+        protected Border lastTextBorder;
+
+        #endregion
+
+        public FrameSelectTool()
+        {
+        }
+
+        public Point GetStartPoint()
+        {
+            return DpiHelper.StandardPointToPDFPoint(new Point((mouseStartPoint.X - pageBound.X + (cropPoint.X * zoomFactor)) / zoomFactor, (mouseStartPoint.Y - pageBound.Y + (cropPoint.Y * zoomFactor)) / zoomFactor));
+        }
+
+        public Point GetEndPoint()
+        {
+            if (moveOffset == new Point())
+            {
+                return new Point(-1, -1);
+            }
+            else
+            {
+                return DpiHelper.StandardPointToPDFPoint(new Point((mouseEndPoint.X - pageBound.X + (cropPoint.X * zoomFactor)) / zoomFactor, (mouseEndPoint.Y - pageBound.Y + (cropPoint.Y * zoomFactor)) / zoomFactor));
+            }
+        }
+
+        public double GetMoveLength()
+        {
+            if (mouseEndPoint == new Point())
+            {
+                return 0;
+            }
+            Point checkPoint = mouseEndPoint;
+            checkPoint.X = Math.Max(pageBound.Left, checkPoint.X);
+            checkPoint.X = Math.Min(pageBound.Right, checkPoint.X);
+            checkPoint.Y = Math.Max(pageBound.Top, checkPoint.Y);
+            checkPoint.Y = Math.Min(pageBound.Bottom, checkPoint.Y);
+
+            Vector moveOffset = checkPoint - mouseStartPoint;
+            return moveOffset.Length;
+        }
+
+        public void SetIsProportionalScaling(bool isOpen)
+        {
+            isProportionalScaling = isOpen;
+        }
+
+        #region Draw
+        public void StartDraw(Point downPoint, Rect maxRect, Rect pageBound, double zoom, int pageindex)
+        {
+            this.pageBound = pageBound;
+            pageIndex = pageindex;
+            isFrameSelect = true;
+            drawRect = new Rect();
+            DPIRect = new Rect();
+            mouseStartPoint = downPoint;
+            isFrameSelect = true;
+            this.maxRect = maxRect;
+            zoomFactor = zoom;
+            moveOffset = new Point();
+            DPIRect = new Rect();
+        }
+        bool noDraw=false;
+        public void MoveDraw(Point downPoint, double zoom)
+        {
+            if (isFrameSelect)
+            {
+                noDraw = true;
+                moveOffset = new Point(
+                    mouseEndPoint.X - downPoint.X,
+                    mouseEndPoint.Y - downPoint.Y
+                    );
+                mouseEndPoint = downPoint;
+                zoomFactor = zoom;
+                Draw();
+            }
+            noDraw = false;
+        }
+
+        public Rect EndDraw(ref int index)
+        {
+            if (noDraw && isFrameSelect)
+            {
+                new Rect();
+            }
+            if (!DPIRect.Equals(new Rect()))
+            {
+                Rect StandardRect = new Rect(
+                    (DPIRect.Left - pageBound.X + (cropPoint.X * zoomFactor)) / zoomFactor, (DPIRect.Top - pageBound.Y + (cropPoint.Y * zoomFactor)) / zoomFactor,
+                    DPIRect.Width / zoomFactor, DPIRect.Height / zoomFactor);
+                isFrameSelect = false;
+                noDraw = false;
+                mouseStartPoint = new Point();
+                mouseEndPoint = new Point();
+                moveOffset = new Point();
+                pageBound = new Rect();
+                DPIRect = new Rect();
+                drawPoints.Clear();
+                ClearDraw();
+                index = pageIndex;
+                return DpiHelper.StandardRectToPDFRect(StandardRect);
+            }
+            isFrameSelect = false;
+            noDraw = false;
+            return new Rect();
+        }
+
+        public override void Draw()
+        {
+            if (noDraw&& isFrameSelect)
+            {
+                Dispatcher.Invoke(() =>
+            {
+
+                drawDC = Open();
+                DrawSquare(drawDC);
+                Present();
+            });
+            }
+        }
+
+        public virtual void ClearDraw()
+        {
+            Open();
+            Present();
+        }
+
+        private void DrawSquare(DrawingContext drawingContext)
+        {
+            try
+            {
+                Pen DrawPen = new Pen(new SolidColorBrush(Color.FromRgb(71, 126, 222)), 2);
+
+                SolidColorBrush FillBrush = new SolidColorBrush(Colors.Transparent);
+                FillBrush = new SolidColorBrush(Color.FromArgb(0, 255, 255, 255));
+
+                if (isProportionalScaling)
+                {
+                    Point mouseOffset = (Point)(mouseStartPoint - mouseEndPoint);
+                    if (mouseOffset.X < 0)
+                    {
+                        if (mouseOffset.Y > 0)
+                        {
+                            mouseEndPoint = new Point(mouseEndPoint.X, mouseStartPoint.Y + mouseStartPoint.X - mouseEndPoint.X);
+                        }
+                        else
+                        {
+                            mouseEndPoint = new Point(mouseEndPoint.X, mouseStartPoint.Y + mouseEndPoint.X - mouseStartPoint.X);
+                        }
+                    }
+                    else
+                    {
+                        if (mouseOffset.Y > 0)
+                        {
+                            mouseEndPoint = new Point(mouseEndPoint.X, mouseStartPoint.Y + mouseEndPoint.X - mouseStartPoint.X);
+                        }
+                        else
+                        {
+                            mouseEndPoint = new Point(mouseEndPoint.X, mouseStartPoint.Y + mouseStartPoint.X - mouseEndPoint.X);
+                        }
+                    }
+                }
+
+                Rect rect = new Rect(mouseStartPoint, mouseEndPoint);
+
+                double mLeft = rect.Left;
+                double mRight = rect.Right;
+                double mUp = rect.Top;
+                double mDown = rect.Bottom;
+                if (rect.Left < maxRect.Left)
+                {
+                    mLeft = maxRect.Left;
+                }
+                if (rect.Right > maxRect.Right)
+                {
+                    mRight = maxRect.Right;
+                }
+                if (rect.Top < maxRect.Top)
+                {
+                    mUp = maxRect.Top;
+                }
+                if (rect.Bottom > maxRect.Bottom)
+                {
+                    mDown = maxRect.Bottom;
+                }
+                DPIRect = new Rect(mLeft, mUp, mRight - mLeft, mDown - mUp);
+                int halfPenWidth = (int)Math.Ceiling(DrawPen.Thickness / 2);
+                double drawWidth = DPIRect.Width - halfPenWidth * 2;
+                double drawHeight = DPIRect.Height - halfPenWidth * 2;
+                if (drawWidth > 0 && drawHeight > 0)
+                {
+                    drawRect = new Rect(
+                        (int)DPIRect.Left + halfPenWidth,
+                        (int)DPIRect.Top + halfPenWidth,
+                        (int)DPIRect.Width - halfPenWidth * 2,
+                        (int)DPIRect.Height - halfPenWidth * 2);
+                    drawingContext?.DrawRectangle(null, DrawPen, drawRect);
+                    halfPenWidth = (int)Math.Floor(DrawPen.Thickness / 2);
+                    if (drawRect.Width - halfPenWidth * 2 > 0 && drawRect.Height - halfPenWidth * 2 > 0)
+                    {
+                        Rect innerRect = new Rect(drawRect.Left + halfPenWidth, drawRect.Top + halfPenWidth, drawRect.Width - 2 * halfPenWidth, drawRect.Height - 2 * halfPenWidth);
+
+                        drawingContext?.DrawRectangle(FillBrush, null, innerRect);
+                    }
+                }
+                else
+                {
+                    drawRect = new Rect();
+                }
+            }
+            catch { }
+        }
+
+        public Rect GetMaxRect()
+        {
+            return maxRect;
+        }
+
+        /// <summary>
+        /// Use to calculate the point drawn at a fixed angle
+        /// </summary>
+        /// <param name="currentPoint">
+        /// Current point
+        /// </param>
+        /// <param name="startPoint">
+        /// Start point
+        /// </param>
+        /// <param name="pageBound">
+        /// Maximum drawing area
+        /// </param>
+        /// <returns>
+        /// Return the calculated point
+        /// </returns>
+        internal Point CalcAnglePoint(Point currentPoint, Point startPoint, Rect pageBound)
+        {
+            Vector angleVector = currentPoint - startPoint;
+            Point originPoint = new Point(startPoint.X, startPoint.Y - angleVector.Length);
+            Vector orignVector = originPoint - startPoint;
+            Rect checkRect = pageBound;
+            int angle = (int)Vector.AngleBetween(orignVector, angleVector);
+            if (angle < 0)
+            {
+                angle += 360;
+            }
+            int mod = angle % 45;
+            int quot = angle / 45;
+            Point anglePoint = currentPoint;
+
+            int rotateAngle = 0;
+            if (mod < 22)
+            {
+                Matrix rotateMatrix = new Matrix();
+                rotateAngle = quot * 45;
+                rotateMatrix.RotateAt(rotateAngle, startPoint.X, startPoint.Y);
+                anglePoint = rotateMatrix.Transform(originPoint);
+                anglePoint = new Point((int)anglePoint.X, (int)anglePoint.Y);
+            }
+            else
+            {
+                Matrix rotateMatrix = new Matrix();
+                rotateAngle = (quot + 1) * 45;
+                rotateMatrix.RotateAt(rotateAngle, startPoint.X, startPoint.Y);
+                anglePoint = rotateMatrix.Transform(originPoint);
+                anglePoint = new Point((int)anglePoint.X, (int)anglePoint.Y);
+            }
+
+
+            if (checkRect.Contains(anglePoint) == false)
+            {
+                switch (rotateAngle)
+                {
+                    case 0:
+                        {
+                            anglePoint.X = startPoint.X;
+                            anglePoint.Y = Math.Max(checkRect.Top, Math.Min(anglePoint.Y, startPoint.Y));
+                        }
+                        break;
+                    case 45:
+                        {
+                            double addValue = Math.Min(anglePoint.X - startPoint.X, checkRect.Right - startPoint.X);
+                            addValue = Math.Min(addValue, startPoint.Y - checkRect.Top);
+                            anglePoint.X = startPoint.X + addValue;
+                            anglePoint.Y = startPoint.Y - addValue;
+                        }
+                        break;
+                    case 90:
+                        {
+                            anglePoint.X = startPoint.X + Math.Min(anglePoint.X - startPoint.X, checkRect.Right - startPoint.X);
+                            anglePoint.Y = startPoint.Y;
+                        }
+                        break;
+                    case 135:
+                        {
+                            double addValue = Math.Min(anglePoint.X - startPoint.X, checkRect.Right - startPoint.X);
+                            addValue = Math.Min(addValue, checkRect.Bottom - startPoint.Y);
+                            anglePoint.X = startPoint.X + addValue;
+                            anglePoint.Y = startPoint.Y + addValue;
+                        }
+                        break;
+                    case 180:
+                        {
+                            anglePoint.X = startPoint.X;
+                            anglePoint.Y = Math.Min(anglePoint.Y, checkRect.Bottom);
+                        }
+                        break;
+                    case 225:
+                        {
+                            double addValue = Math.Min(startPoint.X - anglePoint.X, startPoint.X - checkRect.Left);
+                            addValue = Math.Min(addValue, checkRect.Bottom - startPoint.Y);
+                            anglePoint.X = startPoint.X - addValue;
+                            anglePoint.Y = startPoint.Y + addValue;
+                        }
+                        break;
+                    case 270:
+                        {
+                            anglePoint.X = startPoint.X - Math.Min(startPoint.X - anglePoint.X, startPoint.X - checkRect.Left);
+                            anglePoint.Y = startPoint.Y;
+                        }
+                        break;
+                    case 315:
+                        {
+                            double addValue = Math.Min(startPoint.X - anglePoint.X, startPoint.X - checkRect.Left);
+                            addValue = Math.Min(addValue, startPoint.Y - checkRect.Top);
+                            anglePoint.X = startPoint.X - addValue;
+                            anglePoint.Y = startPoint.Y - addValue;
+                        }
+                        break;
+                    case 360:
+                        {
+                            anglePoint.X = startPoint.X;
+                            anglePoint.Y = Math.Max(checkRect.Top, Math.Min(anglePoint.Y, startPoint.Y));
+                        }
+                        break;
+                    default:
+                        break;
+                }
+            }
+            return anglePoint;
+        }
+    }
+    #endregion
+}

+ 193 - 17
Demo/Examples/ComPDFKit.Tool/DrawTool/MultiSelectedRect.cs

@@ -179,6 +179,7 @@ namespace ComPDFKit.Tool.DrawTool
         /// Array passed from outside for multiple selection
         /// </summary>
         protected List<SelectedRect> selectedRects = new List<SelectedRect>();
+        protected Dictionary<SelectedRect,KeyValuePair<int,int>> RelationDict=new Dictionary<SelectedRect, KeyValuePair<int, int>>();
 
         protected bool isHover = false;
 
@@ -207,13 +208,53 @@ namespace ComPDFKit.Tool.DrawTool
         public MultiSelectedRect(DefaultDrawParam defaultDrawParam, SelectedType type) : base()
         {
             drawParam = defaultDrawParam;
-            currentDrawPointType = DrawPointType.Square;
+            currentDrawPointType = DrawPointType.Circle;
             selectedType = type;
         }
 
-        public void SetMulitSelectedRect(SelectedRect selectedobject)
+        public void SetMulitSelectedRect(SelectedRect selectedobject,int pageIndex,int editIndex)
         {
             selectedRects.Add(selectedobject);
+            RelationDict[selectedobject] = new KeyValuePair<int, int>(pageIndex, editIndex);
+        }
+
+        public bool GetRelationKey(SelectedRect selectedobject,out int pageIndex,out int editIndex)
+        {
+            pageIndex = -1;
+            editIndex = -1;
+            if(RelationDict!=null && RelationDict.ContainsKey(selectedobject))
+            {
+                KeyValuePair<int, int> relateData = RelationDict[selectedobject];
+                pageIndex = relateData.Key;
+                editIndex = relateData.Value;
+                return true;
+            }
+
+            return false;
+        }
+        /// <summary>
+        /// delete
+        /// </summary>
+        /// <param name="selectedobject"></param>
+        public void DelMulitSelectedRect(SelectedRect selectedobject)
+        {
+            selectedRects.Remove(selectedobject);
+            RelationDict.Remove(selectedobject);
+        }
+
+        /// <summary>
+        /// get selectedRects Index
+        /// </summary>
+        /// <param name="selectedobject"></param>
+        /// <returns></returns>
+        public int GetMulitSelectedRectIndex(SelectedRect selectedobject)
+        {
+          return selectedRects.IndexOf(selectedobject);
+        }
+
+        public List<SelectedRect> GetMulitSelectList()
+        {
+            return selectedRects==null ? new List<SelectedRect>() : selectedRects;
         }
 
         public SelectedType GetSelectedType()
@@ -226,6 +267,7 @@ namespace ComPDFKit.Tool.DrawTool
             if (selectedType != type)
             {
                 selectedRects.Clear();
+                RelationDict.Clear();
             }
             selectedType = type;
         }
@@ -233,6 +275,7 @@ namespace ComPDFKit.Tool.DrawTool
         public void CleanMulitSelectedRect()
         {
             selectedRects.Clear();
+            RelationDict.Clear();
         }
 
         public virtual void OnMouseLeftButtonDown(Point downPoint)
@@ -296,6 +339,25 @@ namespace ComPDFKit.Tool.DrawTool
             return (float)(drawRect.Height / drawDefaultRect.Height);
         }
 
+        /// <summary>
+        /// Multiple selection of movement distance
+        /// </summary>
+        /// <returns></returns>
+        public float GetChangeX()
+        {
+            return (float)(drawRect.Width - drawDefaultRect.Width);
+        }
+
+        /// <summary>
+        /// Multiple selection of movement distance
+        /// </summary>
+        /// <returns></returns>
+        public float GetChangeY()
+        {
+            return (float)(drawRect.Height - drawDefaultRect.Height);
+        }
+
+
         public void Draw()
         {
             switch (currentDrawType)
@@ -311,7 +373,7 @@ namespace ComPDFKit.Tool.DrawTool
                             SolidColorBrush solidColorBrush = drawParam.SPDFEditMultiRectFillBrush;
                             Pen pen = drawParam.SPDFEditMultiRectLinePen;
                             GetBrushAndPen(ref solidColorBrush, ref pen);
-                            if (selectedRects.Count > 1)
+                            if (selectedRects.Count >= 1)
                             {
                                 foreach (SelectedRect item in selectedRects)
                                 {
@@ -338,7 +400,14 @@ namespace ComPDFKit.Tool.DrawTool
                                         SolidColorBrush moveBrush = drawParam.PDFEditMultiMoveBrush;
                                         Pen movepen = drawParam.PDFEditMultiMovePen;
                                         GetMoveBrushAndPen(ref moveBrush, ref movepen);
-                                        DrawMoveBounds(drawDC, hitControlType, movepen, moveBrush, drawRect);
+                                        if (selectedType == SelectedType.PDFEdit)
+                                        {
+                                            DrawMoveBounds(drawDC, hitControlType, movepen, moveBrush, drawRect, drawParam.PDFEditMultiMoveRectPen);
+                                        }
+                                        else
+                                        {
+                                            DrawMoveBounds(drawDC, hitControlType, movepen, moveBrush, drawRect);
+                                        }
                                     }
                                     drawDC?.DrawRectangle(solidColorBrush, pen, drawDefaultRect);
                                     break;
@@ -349,7 +418,15 @@ namespace ComPDFKit.Tool.DrawTool
                             switch (currentDrawPointType)
                             {
                                 case DrawPointType.Circle:
-                                    DrawCirclePoint(drawDC, GetIgnorePoints(), pointSize, PointPen, PointBrush);
+                                    if (selectedType == SelectedType.PDFEdit)
+                                    {
+                                        //Edit Settings Frame
+                                        DrawCirclePoint(drawDC, GetIgnorePoints(), pointSize, PointPen, PointBrush);
+                                    }
+                                    else
+                                    {
+                                        DrawCirclePoint(drawDC, GetIgnorePoints(), pointSize, PointPen, PointBrush);
+                                    }
                                     break;
                                 case DrawPointType.Square:
                                     DrawSquarePoint(drawDC, GetIgnorePoints(), pointSize, PointPen, PointBrush);
@@ -579,7 +656,7 @@ namespace ComPDFKit.Tool.DrawTool
         /// <param name="moveRect">
         /// Move rectangle
         /// </param>
-        protected void DrawMoveBounds(DrawingContext drawDc, PointControlType controltype, Pen activePen, Brush moveBrush, Rect moveRect)
+        protected void DrawMoveBounds(DrawingContext drawDc, PointControlType controltype, Pen activePen, Brush moveBrush, Rect moveRect, Pen RectPen = null)
         {
             switch (controltype)
             {
@@ -615,15 +692,20 @@ namespace ComPDFKit.Tool.DrawTool
                     break;
                 case PointControlType.Body:
                 case PointControlType.Line:
-                    drawDc?.DrawLine(activePen, new Point(0, moveRect.Top), new Point(PDFViewerActualWidth, moveRect.Top));
-                    drawDc?.DrawLine(activePen, new Point(0, moveRect.Bottom), new Point(PDFViewerActualWidth, moveRect.Bottom));
-                    drawDc?.DrawLine(activePen, new Point(moveRect.Left, 0), new Point(moveRect.Left, PDFViewerActualHeight));
-                    drawDc?.DrawLine(activePen, new Point(moveRect.Right, 0), new Point(moveRect.Right, PDFViewerActualHeight));
+                    drawDc?.DrawLine(activePen, new Point(0, moveRect.Top), new Point(moveRect.Left, moveRect.Top));
+                    drawDc?.DrawLine(activePen, new Point(moveRect.Right, moveRect.Top), new Point(PDFViewerActualWidth, moveRect.Top));
+                    drawDc?.DrawLine(activePen, new Point(moveRect.Left, moveRect.Top), new Point(moveRect.Left, 0));
+                    drawDc?.DrawLine(activePen, new Point(moveRect.Right, moveRect.Top), new Point(moveRect.Right, 0));
+
+                    drawDc?.DrawLine(activePen, new Point(0, moveRect.Bottom), new Point(moveRect.Left, moveRect.Bottom));
+                    drawDc?.DrawLine(activePen, new Point(moveRect.Right, moveRect.Bottom), new Point(PDFViewerActualWidth, moveRect.Bottom));
+                    drawDc?.DrawLine(activePen, new Point(moveRect.Left, moveRect.Bottom), new Point(moveRect.Left, PDFViewerActualHeight));
+                    drawDc?.DrawLine(activePen, new Point(moveRect.Right, moveRect.Bottom), new Point(moveRect.Right, PDFViewerActualHeight));
                     break;
                 default:
                     break;
             }
-            drawDc?.DrawRectangle(moveBrush, null, moveRect);
+            drawDc?.DrawRectangle(moveBrush, RectPen, moveRect);
         }
 
         public virtual void ClearDraw()
@@ -1177,7 +1259,60 @@ namespace ComPDFKit.Tool.DrawTool
                     switch (currentDrawPointType)
                     {
                         case DrawPointType.Circle:
+                            if (IgnorePointsList.Contains(checkPoint))
+                            {
+                                continue;
+                            }
                             Vector checkVector = checkPoint - point;
+                            double wlen = drawRect.Width;
+                            if (wlen > 50)
+                            {
+                                wlen = 20;
+                            }
+                            else
+                            {
+                                wlen = wlen / 3;
+                            }
+                            double hlen = drawRect.Height;
+                            if (hlen > 50)
+                            {
+                                hlen = 20;
+                            }
+                            else
+                            {
+                                hlen = wlen / 3;
+                            }
+                            if ((PointControlType)i == PointControlType.RightMiddle)
+                            {
+
+                                if (Math.Abs(point.X - checkPoint.X) < wlen && checkVector.Length < drawRect.Height / 3)
+                                {
+                                    return (PointControlType)i;
+                                }
+                            }
+                            if ((PointControlType)i == PointControlType.LeftMiddle)
+                            {
+                                if (Math.Abs(point.X - checkPoint.X) < wlen && checkVector.Length < drawRect.Height / 3)
+                                {
+                                    return (PointControlType)i;
+                                }
+                            }
+
+                            if ((PointControlType)i == PointControlType.MiddleTop)
+                            {
+                                if (Math.Abs(point.Y - checkPoint.Y) < hlen && checkVector.Length < drawRect.Width / 3)
+                                {
+                                    return (PointControlType)i;
+                                }
+                            }
+
+                            if ((PointControlType)i == PointControlType.MiddlBottom)
+                            {
+                                if (Math.Abs(point.Y - checkPoint.Y) < hlen && checkVector.Length < drawRect.Width / 3)
+                                {
+                                    return (PointControlType)i;
+                                }
+                            }
                             if (checkVector.Length < pointSize)
                             {
                                 return (PointControlType)i;
@@ -1196,19 +1331,19 @@ namespace ComPDFKit.Tool.DrawTool
                     }
                 }
 
-                Rect defrect = drawDefaultRect;
+                Rect defrect = drawRect;
 
                 defrect.X -= rectPadding;
                 defrect.Y -= rectPadding;
                 defrect.Width += rectPadding;
                 defrect.Height += rectPadding;
-                if (drawDefaultRect.Contains(point))
+                if (drawRect.Contains(point))
                 {
                     Rect rect = new Rect(
-                        Math.Max(drawDefaultRect.X + rectPadding, 0),
-                        Math.Max(drawDefaultRect.Y + rectPadding, 0),
-                        drawDefaultRect.Width - 2 * rectPadding,
-                        drawDefaultRect.Height - 2 * rectPadding);
+                        Math.Max(drawRect.X + rectPadding, 0),
+                        Math.Max(drawRect.Y + rectPadding, 0),
+                        drawRect.Width - 2 * rectPadding,
+                        drawRect.Height - 2 * rectPadding);
                     if (rect.Contains(point))
                     {
                         if (!ignoreList.Contains(PointControlType.Body))
@@ -1224,5 +1359,46 @@ namespace ComPDFKit.Tool.DrawTool
             }
             return PointControlType.None;
         }
+
+        /// <summary>
+        /// Get the rectangle where the current point is located
+        /// </summary>
+        /// <param name="clickPoint">
+        /// Coordinate point
+        /// </param>
+        /// <returns>
+        /// Control point type
+        /// </returns>
+        public SelectedRect GetHitControlRect(Point point)
+        {
+            HitTestResult hitResult = VisualTreeHelper.HitTest(this, point);
+            if (hitResult != null && hitResult.VisualHit is DrawingVisual)
+            {
+                foreach (SelectedRect selectedRect in selectedRects) {
+                    Rect defrect = selectedRect.GetRect();
+                    defrect.X -= rectPadding;
+                    defrect.Y -= rectPadding;
+                    defrect.Width += rectPadding;
+                    defrect.Height += rectPadding;
+
+                    if (defrect.Contains(point))
+                    {
+                        Rect rect = new Rect(
+                            Math.Max(defrect.X + rectPadding, 0),
+                            Math.Max(defrect.Y + rectPadding, 0),
+                            defrect.Width - 2 * rectPadding,
+                            defrect.Height - 2 * rectPadding);
+                        if (rect.Contains(point))
+                        {
+                            return selectedRect;
+                        }
+                    }
+
+                }
+
+                
+            }
+            return null;
+        }
     }
 }

+ 301 - 19
Demo/Examples/ComPDFKit.Tool/DrawTool/SelectedRect.cs

@@ -17,6 +17,7 @@ using System.Windows.Input;
 using System.Windows.Media;
 using System.Windows.Media.Media3D;
 using System.Xml.Linq;
+using static ComPDFKit.Tool.Help.ImportWin32;
 using static System.Net.Mime.MediaTypeNames;
 
 namespace ComPDFKit.Tool.DrawTool
@@ -75,11 +76,42 @@ namespace ComPDFKit.Tool.DrawTool
 
         public AnnotData annotData { get; set; }
 
-        public double Angle {  get; set; }
+        public double Angle { get; set; }
     }
 
     public partial class SelectedRect : DrawingVisual
     {
+        /// <summary>
+        /// Re-layout child elements
+        /// </summary>
+        public void Arrange()
+        {
+            foreach (Visual child in Children)
+            {
+                if (!(child is UIElement))
+                {
+                    continue;
+                }
+                UIElement checkChild = child as UIElement;
+                try
+                {
+                    double left = Canvas.GetLeft(checkChild);
+                    double top = Canvas.GetTop(checkChild);
+                    double width = (double)checkChild.GetValue(FrameworkElement.WidthProperty);
+                    double height = (double)checkChild.GetValue(FrameworkElement.HeightProperty);
+                    checkChild.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
+                    checkChild.Arrange(new Rect(
+                        double.IsNaN(left) ? 0 : left,
+                        double.IsNaN(top) ? 0 : top,
+                        double.IsNaN(width) ? checkChild.DesiredSize.Width : width,
+                        double.IsNaN(height) ? checkChild.DesiredSize.Height : height));
+                }
+                catch (Exception ex)
+                {
+
+                }
+            }
+        }
         protected DefaultDrawParam DrawParam = new DefaultDrawParam();
 
         protected DrawingContext drawDC { get; set; }
@@ -99,9 +131,9 @@ namespace ComPDFKit.Tool.DrawTool
         protected bool isSelected = false;
 
         protected SelectedType selectedType = SelectedType.None;
-        public bool CanRotate {  get; set; }
+        public bool CanRotate { get; set; }
         private double angle = 0;
-        private Point rotateCenter= new Point(0,0);
+        private Point rotateCenter = new Point(0, 0);
         private int rotateline = 25;
         public SelectedType GetSelectedType()
         {
@@ -115,7 +147,7 @@ namespace ComPDFKit.Tool.DrawTool
 
         public bool GetIsHover()
         {
-           return isHover;
+            return isHover;
         }
 
         public void SetIsSelected(bool selected)
@@ -125,7 +157,7 @@ namespace ComPDFKit.Tool.DrawTool
 
         public bool GetIsSelected()
         {
-           return isSelected;
+            return isSelected;
         }
 
         public void SetCurrentDrawPointType(DrawPointType type)
@@ -147,7 +179,15 @@ namespace ComPDFKit.Tool.DrawTool
             HitTestResult hitResult = VisualTreeHelper.HitTest(this, downPoint);
             if (hitResult != null && hitResult.VisualHit is DrawingVisual)
             {
-                hitControlType = GetHitControlIndex(downPoint);
+                //Crop judgment point
+                if (currentDrawPointType == DrawPointType.Crop)
+                {
+                    hitControlType = GetHitCropControlIndex(downPoint);
+                }
+                else
+                {
+                    hitControlType = GetHitControlIndex(downPoint);
+                }
                 if (hitControlType != PointControlType.None)
                 {
                     cacheRect = drawRect;
@@ -235,7 +275,7 @@ namespace ComPDFKit.Tool.DrawTool
         private void DrawNormal(DrawingContext drawDC)
         {
             Rect currentRect = SetDrawRect;
-           
+
             switch (currentDrawMoveType)
             {
                 case DrawMoveType.kDefault:
@@ -285,12 +325,12 @@ namespace ComPDFKit.Tool.DrawTool
             {
                 RotateTransform transform = new RotateTransform();
                 transform.Angle = angle;
-               // if(hitControlType==PointControlType.Body || hitControlType==PointControlType.Line)
+                // if(hitControlType==PointControlType.Body || hitControlType==PointControlType.Line)
                 {
-                    rotateCenter.X  = drawRect.Left + drawRect.Width / 2;
+                    rotateCenter.X = drawRect.Left + drawRect.Width / 2;
                     rotateCenter.Y = drawRect.Top + drawRect.Height / 2;
                 }
-              
+
                 transform.CenterX = rotateCenter.X;
                 transform.CenterY = rotateCenter.Y;
 
@@ -302,7 +342,7 @@ namespace ComPDFKit.Tool.DrawTool
         {
             if (CanRotate)
             {
-               
+
                 drawDC.Pop();
             }
         }
@@ -417,7 +457,7 @@ namespace ComPDFKit.Tool.DrawTool
                     if (isHover)
                     {
                         colorBrush = DrawParam.PDFEditRectFillHoverBrush;
-                        pen = DrawParam.PDFEditRectLineHoverPen;
+                        pen = editHoverPen;//DrawParam.PDFEditRectLineHoverPen;
                     }
                     else
                     {
@@ -429,7 +469,16 @@ namespace ComPDFKit.Tool.DrawTool
                         else
                         {
                             colorBrush = DrawParam.PDFEditRectFillBrush;
-                            pen = DrawParam.PDFEditRectLinePen;
+                            //init Color
+                            if (showCreatTextRect)
+                            {
+                                pen = DrawParam.PDFEditRectLinePen;
+                            }
+                            else
+                            {
+                                pen = editPen;
+                            }
+                            // editPen; //editPen;//// DrawParam.PDFEditRectLinePen; 
                         }
                     }
                     break;
@@ -437,6 +486,31 @@ namespace ComPDFKit.Tool.DrawTool
                     break;
             }
         }
+        public void SetShowCreatTextRect(bool ShowCreatTextRect)
+        {
+            showCreatTextRect = ShowCreatTextRect;
+        }
+
+        public void SetEditPen(Pen editPen = null, Pen editHoverPen = null)
+        {
+            if (editPen == null)
+            {
+                this.editPen = DrawParam.PDFEditRectLinePen;
+            }
+            else
+            {
+                this.editPen = new Pen(editPen.Brush, editPen.Thickness);
+            }
+            if (editHoverPen == null)
+            {
+                this.editHoverPen = DrawParam.PDFEditRectLineHoverPen;
+            }
+            else
+            {
+                this.editHoverPen = editHoverPen;
+            }
+        }
+
         public virtual void ClearDraw()
         {
             SetDrawRect = drawRect = new Rect();
@@ -454,13 +528,13 @@ namespace ComPDFKit.Tool.DrawTool
             drawDC?.Close();
         }
 
-        public void SetRect(Rect newRect,double zoom)
+        public void SetRect(Rect newRect, double zoom)
         {
-            if(newRect == Rect.Empty || newRect == null)
+            if (newRect == Rect.Empty || newRect == null)
             {
                 return;
             }
-            newRect = new Rect((int)(newRect.X - rectPadding* zoom), (int)(newRect.Y - rectPadding* zoom),(int)( newRect.Width + 2 * rectPadding* zoom), (int)(newRect.Height + 2 * rectPadding* zoom));
+            newRect = new Rect((int)(newRect.X - rectPadding * zoom), (int)(newRect.Y - rectPadding * zoom), (int)(newRect.Width + 2 * rectPadding * zoom), (int)(newRect.Height + 2 * rectPadding * zoom));
             currentZoom = zoom;
             SetDrawRect = drawRect = newRect;
             drawCenterPoint = new Point(drawRect.Left + drawRect.Width / 2, drawRect.Top + drawRect.Height / 2);
@@ -493,6 +567,48 @@ namespace ComPDFKit.Tool.DrawTool
             return drawRect;
         }
 
+        /// <summary>
+        /// Obtain cropped and actual region margin
+        /// </summary>
+        /// <returns></returns>
+        public Thickness GetClipThickness()
+        {
+            return clipThickness;
+        }
+
+        /// <summary>
+        /// Get ClipRect
+        /// </summary>
+        /// <returns></returns>
+        public Rect GetClipRect()
+        {
+            Rect drawrect = new Rect(0, 0, 0, 0);
+            drawrect.X = SetDrawRect.X - clipThickness.Left * currentZoom;
+            drawrect.Y = SetDrawRect.Y - clipThickness.Top * currentZoom;
+            drawrect.Width = SetDrawRect.Width - clipThickness.Right * currentZoom + clipThickness.Left * currentZoom;
+            drawrect.Height = SetDrawRect.Height - clipThickness.Bottom * currentZoom + clipThickness.Top * currentZoom;
+            return drawrect;
+        }
+
+        /// <summary>
+        /// Set cropping and actual area margins
+        /// </summary>
+        /// <returns></returns>
+        public void SetClipThickness(Thickness rect)
+        {
+            try
+            {
+                Rect drawrect = new Rect(0, 0, 0, 0);
+                drawrect.X = SetDrawRect.X - rect.Left * currentZoom;
+                drawrect.Y = SetDrawRect.Y - rect.Top * currentZoom;
+                drawrect.Width = SetDrawRect.Width - rect.Right * currentZoom + rect.Left * currentZoom;
+                drawrect.Height = SetDrawRect.Height - rect.Bottom * currentZoom + rect.Top * currentZoom;
+                drawRect = drawrect;
+                clipThickness = rect;
+            }
+            catch { }
+        }
+
         public void SetMaxRect(Rect rect)
         {
             maxRect = rect;
@@ -502,6 +618,13 @@ namespace ComPDFKit.Tool.DrawTool
             return maxRect;
         }
 
+        public void UpdateAnnotData(AnnotData annotData)
+        {
+            if (selectedRectData != null)
+            {
+                selectedRectData.annotData = annotData;
+            }
+        }
         public void SetAnnotData(AnnotData annotData)
         {
             SetIgnorePoints(new List<PointControlType>());
@@ -580,6 +703,33 @@ namespace ComPDFKit.Tool.DrawTool
             }
         }
 
+        /// <summary>
+        /// Set Edit that need to be ignored
+        /// </summary>
+        /// <param name="types">
+        /// The collection of point types that need to be ignored
+        /// </param>
+        public void SetEditIgnorePoints(List<PointControlType> ignoreTextPoints, List<PointControlType> ignoreImagePoints, DrawPointType drawEditPointType, bool IsText = true)
+        {
+            SetCurrentDrawPointType(drawEditPointType);
+            if (IsText)
+            {
+                ignorePoints.Clear();
+                foreach (PointControlType type in ignoreTextPoints)
+                {
+                    ignorePoints.Add(type);
+                }
+            }
+            else
+            {
+                ignorePoints.Clear();
+                foreach (PointControlType type in ignoreImagePoints)
+                {
+                    ignorePoints.Add(type);
+                }
+            }
+        }
+
         /// <summary>
         /// Ignore all points
         /// </summary>
@@ -685,7 +835,7 @@ namespace ComPDFKit.Tool.DrawTool
         {
             if (CanRotate)
             {
-                return GetRotateHitIndex(point,isIgnore);
+                return GetRotateHitIndex(point, isIgnore);
             }
 
             return GetNormalHitIndex(point, isIgnore);
@@ -717,7 +867,60 @@ namespace ComPDFKit.Tool.DrawTool
                     switch (currentDrawPointType)
                     {
                         case DrawPointType.Circle:
+                            if (IgnorePointsList.Contains(checkPoint))
+                            {
+                                continue;
+                            }
                             Vector checkVector = checkPoint - point;
+                            double wlen = drawRect.Width;
+                            if (wlen > 50)
+                            {
+                                wlen = 20;
+                            }
+                            else
+                            {
+                                wlen = wlen / 3;
+                            }
+                            double hlen = drawRect.Height;
+                            if (hlen > 50)
+                            {
+                                hlen = 20;
+                            }
+                            else
+                            {
+                                hlen = wlen / 3;
+                            }
+                            if ((PointControlType)i == PointControlType.RightMiddle)
+                            {
+
+                                if (Math.Abs(point.X - checkPoint.X) < wlen && checkVector.Length < drawRect.Height / 3)
+                                {
+                                    return (PointControlType)i;
+                                }
+                            }
+                            if ((PointControlType)i == PointControlType.LeftMiddle)
+                            {
+                                if (Math.Abs(point.X - checkPoint.X) < wlen && checkVector.Length < drawRect.Height / 3)
+                                {
+                                    return (PointControlType)i;
+                                }
+                            }
+
+                            if ((PointControlType)i == PointControlType.MiddleTop)
+                            {
+                                if (Math.Abs(point.Y - checkPoint.Y) < hlen && checkVector.Length < drawRect.Width / 3)
+                                {
+                                    return (PointControlType)i;
+                                }
+                            }
+
+                            if ((PointControlType)i == PointControlType.MiddlBottom)
+                            {
+                                if (Math.Abs(point.Y - checkPoint.Y) < hlen && checkVector.Length < drawRect.Width / 3)
+                                {
+                                    return (PointControlType)i;
+                                }
+                            }
                             if (checkVector.Length < pointSize)
                             {
                                 return (PointControlType)i;
@@ -743,7 +946,6 @@ namespace ComPDFKit.Tool.DrawTool
                             break;
                     }
                 }
-
                 if (drawRect.Contains(point))
                 {
                     double rectWidth = (drawRect.Width - 2 * rectPadding > 0) ? drawRect.Width - 2 * rectPadding : 0;
@@ -763,6 +965,7 @@ namespace ComPDFKit.Tool.DrawTool
                 }
             }
             return PointControlType.None;
+
         }
 
         private PointControlType GetRotateHitIndex(Point point, bool isIgnore = true)
@@ -779,7 +982,7 @@ namespace ComPDFKit.Tool.DrawTool
                 Vector transVector = matrix.Transform(currentVector);
                 Point checkPos = new Point(centerPoint.X + transVector.X, centerPoint.Y + transVector.Y);
 
-                point= checkPos;
+                point = checkPos;
                 List<PointControlType> ignoreList = GetIgnorePoints();
 
                 List<Point> IgnorePointsList = new List<Point>();
@@ -867,5 +1070,84 @@ namespace ComPDFKit.Tool.DrawTool
                 Draw();
             }
         }
+        /// <summary>
+        /// The position of the points in the cropping box
+        /// </summary>
+        /// <param name="point"></param>
+        /// <param name="isIgnore"></param>
+        /// <returns></returns>
+        public PointControlType GetHitCropControlIndex(Point point, bool isIgnore = true)
+        {
+            List<Point> controlCurrentPoints = GetControlPoint(drawRect);
+            HitTestResult hitResult = VisualTreeHelper.HitTest(this, point);
+            if (hitResult != null && hitResult.VisualHit is DrawingVisual)
+            {
+                List<PointControlType> ignoreList = GetIgnorePoints();
+
+                List<Point> IgnorePointsList = new List<Point>();
+                foreach (PointControlType type in ignoreList)
+                {
+                    if ((int)type < controlCurrentPoints.Count)
+                    {
+                        IgnorePointsList.Add(controlCurrentPoints[(int)type]);
+                    }
+                }
+                for (int i = 0; i < controlCurrentPoints.Count; i++)
+                {
+                    Point checkPoint = controlCurrentPoints[i];
+
+                    if (isIgnore && IgnorePointsList.Contains(checkPoint))
+                    {
+                        continue;
+                    }
+                    switch (currentDrawPointType)
+                    {
+                        case DrawPointType.Circle:
+                            Vector checkVector = checkPoint - point;
+                            if (checkVector.Length < pointSize)
+                            {
+                                return (PointControlType)i;
+                            }
+                            break;
+                        case DrawPointType.Square:
+
+                            Rect checkRect = new Rect(Math.Max(checkPoint.X - pointSize, 0), Math.Max(checkPoint.Y - pointSize, 0), pointSize * 2, pointSize * 2);
+                            if (checkRect.Contains(point))
+                            {
+                                return (PointControlType)i;
+                            }
+                            break;
+
+                        case DrawPointType.Crop:
+                            Rect cropRect = new Rect(Math.Max(checkPoint.X - pointSize, 0), Math.Max(checkPoint.Y - pointSize, 0), pointSize * 2, pointSize * 2);
+                            if (cropRect.Contains(point))
+                            {
+                                return (PointControlType)i;
+                            }
+                            break;
+                        default:
+                            break;
+                    }
+                }
+                if (drawRect.Contains(point))
+                {
+                    double rectWidth = (drawRect.Width - 2 * rectPadding > 0) ? drawRect.Width - 2 * rectPadding : 0;
+                    double rectHeight = (drawRect.Height - 2 * rectPadding > 0) ? drawRect.Height - 2 * rectPadding : 0;
+                    Rect rect = new Rect(Math.Max(drawRect.X + rectPadding, 0), Math.Max(drawRect.Y + rectPadding, 0), rectWidth, rectHeight);
+                    if (rect.Contains(point))
+                    {
+                        if (!ignoreList.Contains(PointControlType.Body))
+                        {
+                            return PointControlType.Body;
+                        }
+                    }
+                    if (!ignoreList.Contains(PointControlType.Body))
+                    {
+                        return PointControlType.Line;
+                    }
+                }
+            }
+            return PointControlType.None;
+        }
     }
 }

+ 404 - 23
Demo/Examples/ComPDFKit.Tool/DrawTool/SelectedRect.protected.cs

@@ -15,7 +15,12 @@ namespace ComPDFKit.Tool.DrawTool
         /// <summary>
         /// Current control point drawing style.
         /// </summary>
-        protected DrawPointType currentDrawPointType { get; set; }
+        protected DrawPointType currentDrawPointType
+        {
+            get;
+            set;
+        }
+
 
         /// <summary>
         /// Current drag drawing style.
@@ -97,6 +102,19 @@ namespace ComPDFKit.Tool.DrawTool
         /// </summary>
         protected Point moveOffset { get; set; } = new Point(0, 0);
 
+        /// <summary>
+        /// Current drawing rectangle (calculated during operation).
+        /// </summary>
+        protected Thickness clipThickness = new Thickness(0, 0, 0, 0);
+
+        private Pen editPen { get; set; } = new Pen(new SolidColorBrush(Color.FromRgb(71, 126, 222)), 2) { DashStyle = DashStyles.Dash };
+
+        private Pen editHoverPen { get; set; } = new Pen(new SolidColorBrush(Color.FromRgb(71, 126, 222)), 2) { DashStyle = DashStyles.Dash };
+
+        private bool showCreatTextRect = false;
+
+        protected bool isOutSideScaling = false;
+
         /// <summary>
         /// Current actual display width and height of PDFVIewer.
         /// </summary>
@@ -140,6 +158,24 @@ namespace ComPDFKit.Tool.DrawTool
             controlPoints.Add(new Point(centerX, currentRect.Top));
         }
 
+        protected List<Point> GetControlPoint(Rect currentRect)
+        {
+            List<Point> controlCurrentPoints = new List<Point>();
+            controlCurrentPoints.Clear();
+            int centerX = (int)(currentRect.Left + currentRect.Right) / 2;
+            int centerY = (int)(currentRect.Top + currentRect.Bottom) / 2;
+
+            controlCurrentPoints.Add(new Point(currentRect.Left, currentRect.Top));
+            controlCurrentPoints.Add(new Point(currentRect.Left, centerY));
+            controlCurrentPoints.Add(new Point(currentRect.Left, currentRect.Bottom));
+            controlCurrentPoints.Add(new Point(centerX, currentRect.Bottom));
+            controlCurrentPoints.Add(new Point(currentRect.Right, currentRect.Bottom));
+            controlCurrentPoints.Add(new Point(currentRect.Right, centerY));
+            controlCurrentPoints.Add(new Point(currentRect.Right, currentRect.Top));
+            controlCurrentPoints.Add(new Point(centerX, currentRect.Top));
+            return controlCurrentPoints;
+        }
+
         /// <summary>
         /// Calcuate the offset of the current rectangle in the maximum rectangle range
         /// </summary>
@@ -203,9 +239,22 @@ namespace ComPDFKit.Tool.DrawTool
             {
                 return false;
             }
-            return NormalScaling(mousePoint);
+            if (!isOutSideScaling)
+            {
+                return NormalScaling(mousePoint);
+            }
+            else
+            {
+                return OutSideScaling(mousePoint);
+            }
         }
 
+        public void SetOutSideScaling(bool IsOutSideScaling)
+        {
+            isOutSideScaling = IsOutSideScaling;
+        }
+
+
         private Size GetProportionalScalingSize(double width, double height)
         {
             double minHeight = RectMinHeight + 2 * rectPadding * currentZoom;
@@ -852,6 +901,316 @@ namespace ComPDFKit.Tool.DrawTool
             }
             return false;
         }
+        /// <summary>
+        /// Provisional logic, to be further improved, not yet used: Draw the algorithm in the form of normal scaling (drag a point, only scale in one direction).
+        /// </summary>
+        /// <param name="mousePoint">Current mouse position.</param>
+        /// <returns></returns>
+        protected bool OutSideScaling(Point mousePoint)
+        {
+            try
+            {
+                double left = 0, right = 0, top = 0, bottom = 0;
+                double minHeight = RectMinHeight + 2 * rectPadding * currentZoom;
+                double minWidth = rectMinWidth + 2 * rectPadding * currentZoom;
+
+                Point centerPoint = new Point((cacheRect.Right + cacheRect.Left) / 2, (cacheRect.Bottom + cacheRect.Top) / 2);
+                Point moveVector = (Point)(mousePoint - centerPoint);
+                moveVector = ProportionalScalingOffsetPos(moveVector);
+
+                switch (hitControlType)
+                {
+                    case PointControlType.LeftTop:
+                        {
+                            left = centerPoint.X + moveVector.X;
+                            right = cacheRect.Right;
+                            top = centerPoint.Y + moveVector.Y;
+                            bottom = cacheRect.Bottom;
+                            if (isProportionalScaling)
+                            {
+                                Size size = GetProportionalScalingSize(right - left, bottom - top);
+                                left = right - size.Width;
+                                top = bottom - size.Height;
+                                if (left < maxRect.Left)
+                                {
+                                    double tmpWidth = right - left;
+                                    left = maxRect.Left;
+                                    double width = right - left;
+                                    double height = (bottom - top) * width / tmpWidth;
+                                    top = bottom - height;
+                                }
+
+                                if (top < maxRect.Top)
+                                {
+                                    double tmpHeight = bottom - top;
+                                    top = maxRect.Top;
+                                    double height = bottom - top;
+                                    double width = (right - left) * height / tmpHeight;
+                                    left = right - width;
+                                }
+                            }
+                            else
+                            {
+                                if (left + minWidth > right)
+                                {
+                                    left = right - minWidth;
+                                }
+
+                                if (top + minHeight > bottom)
+                                {
+                                    top = bottom - minHeight;
+                                }
+                            }
+                        }
+                        break;
+
+                    case PointControlType.LeftMiddle:
+                        {
+                            left = centerPoint.X + moveVector.X;
+                            right = cacheRect.Right;
+                            top = cacheRect.Top;
+                            bottom = cacheRect.Bottom;
+                            if (left + minWidth > right)
+                            {
+                                left = right - minWidth;
+                            }
+                        }
+                        break;
+
+                    case PointControlType.LeftBottom:
+                        {
+                            left = centerPoint.X + moveVector.X;
+                            right = cacheRect.Right;
+                            top = cacheRect.Top;
+                            bottom = centerPoint.Y + moveVector.Y;
+                            if (isProportionalScaling)
+                            {
+                                Size size = GetProportionalScalingSize(right - left, bottom - top);
+                                left = right - size.Width;
+                                bottom = top + size.Height;
+                                if (left < maxRect.Left)
+                                {
+                                    double tmpWidth = right - left;
+                                    left = maxRect.Left;
+                                    double width = right - left;
+                                    double height = (bottom - top) * width / tmpWidth;
+                                    bottom = top + height;
+                                }
+
+                                if (bottom > maxRect.Bottom)
+                                {
+                                    double tmpHeight = bottom - top;
+                                    bottom = maxRect.Bottom;
+                                    double height = bottom - top;
+                                    double width = (right - left) * height / tmpHeight;
+                                    left = right - width;
+                                }
+                            }
+                            else
+                            {
+                                if (left + minWidth > right)
+                                {
+                                    left = right - minWidth;
+                                }
+
+                                if (top + minHeight > bottom)
+                                {
+                                    bottom = top + minHeight;
+                                }
+                            }
+                        }
+                        break;
+
+                    case PointControlType.MiddlBottom:
+                        {
+                            left = cacheRect.Left;
+                            right = cacheRect.Right;
+                            top = cacheRect.Top;
+                            bottom = centerPoint.Y + moveVector.Y;
+                            if (top + minHeight > bottom)
+                            {
+                                bottom = top + minHeight;
+                            }
+                        }
+                        break;
+
+                    case PointControlType.RightBottom:
+                        {
+                            left = cacheRect.Left;
+                            right = centerPoint.X + moveVector.X;
+                            top = cacheRect.Top;
+                            bottom = centerPoint.Y + moveVector.Y;
+                            if (isProportionalScaling)
+                            {
+                                Size size = GetProportionalScalingSize(right - left, bottom - top);
+                                right = left + size.Width;
+                                bottom = top + size.Height;
+                                if (right > maxRect.Right)
+                                {
+                                    double tmpWidth = right - left;
+                                    right = maxRect.Right;
+                                    double width = right - left;
+                                    double height = (bottom - top) * width / tmpWidth;
+                                    bottom = top + height;
+                                }
+
+                                if (bottom > maxRect.Bottom)
+                                {
+                                    double tmpHeight = bottom - top;
+                                    bottom = maxRect.Bottom;
+                                    double height = bottom - top;
+                                    double width = (right - left) * height / tmpHeight;
+                                    right = left + width;
+                                }
+                            }
+                            else
+                            {
+                                if (left + minWidth > right)
+                                {
+                                    right = left + minWidth;
+                                }
+
+                                if (top + minHeight > bottom)
+                                {
+                                    bottom = top + minHeight;
+                                }
+                            }
+                        }
+                        break;
+
+                    case PointControlType.RightMiddle:
+                        {
+                            left = cacheRect.Left;
+                            right = centerPoint.X + moveVector.X;
+                            top = cacheRect.Top;
+                            bottom = cacheRect.Bottom;
+                            if (left + minWidth > right)
+                            {
+                                right = left + minWidth;
+                            }
+                        }
+                        break;
+
+                    case PointControlType.RightTop:
+                        {
+                            left = cacheRect.Left;
+                            right = centerPoint.X + moveVector.X;
+                            top = centerPoint.Y + moveVector.Y;
+                            bottom = cacheRect.Bottom;
+                            if (isProportionalScaling)
+                            {
+                                Size size = GetProportionalScalingSize(right - left, bottom - top);
+                                right = left + size.Width;
+                                top = bottom - size.Height;
+                                if (right > maxRect.Right)
+                                {
+                                    double tmpWidth = right - left;
+                                    right = maxRect.Right;
+                                    double width = right - left;
+                                    double height = (bottom - top) * width / tmpWidth;
+                                    top = bottom - height;
+                                }
+
+                                if (top < maxRect.Top)
+                                {
+                                    double tmpHeight = bottom - top;
+                                    top = maxRect.Top;
+                                    double height = bottom - top;
+                                    double width = (right - left) * height / tmpHeight;
+                                    right = left + width;
+                                }
+                            }
+                            else
+                            {
+                                if (left + minWidth > right)
+                                {
+                                    right = left + minWidth;
+                                }
+
+                                if (top + minHeight > bottom)
+                                {
+                                    top = bottom - minHeight;
+                                }
+                            }
+                        }
+                        break;
+
+                    case PointControlType.MiddleTop:
+                        {
+                            left = cacheRect.Left;
+                            right = cacheRect.Right;
+                            top = centerPoint.Y + moveVector.Y;
+                            bottom = cacheRect.Bottom;
+                            if (top + minHeight > bottom)
+                            {
+                                top = bottom - minHeight;
+                            }
+                        }
+                        break;
+
+                    case PointControlType.Body:
+                    case PointControlType.Line:
+                        {
+                            double newleft = maxRect.Left - SetDrawRect.Width + 10;
+                            double newright = maxRect.Right + SetDrawRect.Width - 10;
+                            double newtop = maxRect.Top - SetDrawRect.Height + 10;
+                            double newbottom = maxRect.Bottom + SetDrawRect.Height - 10;
+                            if (newleft < 0)
+                            {
+                                newleft = 0;
+                            }
+                            Rect newMaxRect = new Rect(newleft, newtop, newright - newleft, newbottom - newtop);
+
+                            Point OffsetPos = CalcMoveBound(cacheRect, ((Point)(mousePoint - mouseDownPoint)), newMaxRect);
+                            left = cacheRect.Left + OffsetPos.X;
+                            right = cacheRect.Right + OffsetPos.X;
+                            top = cacheRect.Top + OffsetPos.Y;
+                            bottom = cacheRect.Bottom + OffsetPos.Y;
+                        }
+                        break;
+
+                    default:
+                        break;
+                }
+
+                //if (left < maxRect.Left)
+                //{
+                //    left = maxRect.Left;
+                //}
+
+                //if (top < maxRect.Top)
+                //{
+                //    top = maxRect.Top;
+                //}
+
+                if (right > maxRect.Right + SetDrawRect.Width - 10)
+                {
+                    if (left > maxRect.Right - 10)
+                    {
+                        left = maxRect.Right - 10;
+                    }
+                    right = maxRect.Right + SetDrawRect.Width - 10;
+                }
+
+                if (bottom > maxRect.Bottom + SetDrawRect.Height - 10)
+                {
+                    if (top > maxRect.Bottom - 10)
+                    {
+                        top = maxRect.Bottom - 10;
+                    }
+                    bottom = maxRect.Bottom + SetDrawRect.Height - 10;
+                }
+
+                drawRect = new Rect(left, top, right - left, bottom - top);
+                moveOffset = new Point(drawRect.X - cacheRect.X, drawRect.Y - cacheRect.Y);
+                return true;
+            }
+            catch (Exception ex)
+            {
+            }
+            return false;
+        }
+
         /// <summary>
         /// Proportional scaling offset calibration
         /// </summary>
@@ -994,60 +1353,77 @@ namespace ComPDFKit.Tool.DrawTool
 
         protected void DrawCropPoint(DrawingContext drawingContext, List<PointControlType> ignoreList, int PointSize, Pen PointPen, SolidColorBrush BorderBrush)
         {
-            GeometryGroup controlGroup = new GeometryGroup();
-            controlGroup.FillRule = FillRule.Nonzero;
-
+            //GeometryGroup controlGroup = new GeometryGroup();
+            //controlGroup.FillRule = FillRule.Nonzero;
+            clipThickness.Left = (SetDrawRect.Left - drawRect.Left)/currentZoom;
+            clipThickness.Top = (SetDrawRect.Top - drawRect.Top) / currentZoom;
+            clipThickness.Right = (SetDrawRect.Right - drawRect.Right) / currentZoom;
+            clipThickness.Bottom = (SetDrawRect.Bottom - drawRect.Bottom) / currentZoom;
+            List<Point> controlCurrentPoints = GetControlPoint(drawRect);
+            CombinedGeometry controlGroup = new CombinedGeometry();
+            RectangleGeometry paintGeometry = new RectangleGeometry();
+            paintGeometry.Rect = SetDrawRect;
+            controlGroup.Geometry1 = paintGeometry;
+            RectangleGeometry moveGeometry = new RectangleGeometry();
+            Rect clippedBorder = drawRect;
+            if (clippedBorder.IsEmpty == false)
+            {
+                moveGeometry.Rect = drawRect;
+            }
+            controlGroup.Geometry2 = moveGeometry;
+            controlGroup.GeometryCombineMode = GeometryCombineMode.Exclude;
             //Left Top Corner
             if (!ignoreList.Contains(PointControlType.LeftTop))
             {
-                drawingContext?.DrawRectangle(BorderBrush, null, new Rect(controlPoints[0].X - PointSize, controlPoints[0].Y - PointSize, PointSize, PointSize * 4));
-                drawingContext?.DrawRectangle(BorderBrush, null, new Rect(controlPoints[0].X - PointSize, controlPoints[0].Y - PointSize, PointSize * 4, PointSize));
+                drawingContext?.DrawRectangle(BorderBrush, null, new Rect(controlCurrentPoints[0].X - PointSize, controlCurrentPoints[0].Y - PointSize, PointSize, PointSize * 4));
+                drawingContext?.DrawRectangle(BorderBrush, null, new Rect(controlCurrentPoints[0].X - PointSize, controlCurrentPoints[0].Y - PointSize, PointSize * 4, PointSize));
             }
 
             //Left Center
             if (!ignoreList.Contains(PointControlType.LeftMiddle))
             {
-                drawingContext?.DrawRectangle(BorderBrush, null, new Rect(controlPoints[1].X - PointSize, (controlPoints[1].Y + controlPoints[1].Y - PointSize * 5) / 2, PointSize, PointSize * 5));
+                drawingContext?.DrawRectangle(BorderBrush, null, new Rect(controlCurrentPoints[1].X - PointSize, (controlCurrentPoints[1].Y + controlCurrentPoints[1].Y - PointSize * 5) / 2, PointSize, PointSize * 5));
             }
 
             //Left Bottom Corner
             if (!ignoreList.Contains(PointControlType.LeftBottom))
             {
-                drawingContext?.DrawRectangle(BorderBrush, null, new Rect(controlPoints[2].X - PointSize, controlPoints[2].Y - PointSize * 3, PointSize, PointSize * 4));
-                drawingContext?.DrawRectangle(BorderBrush, null, new Rect(controlPoints[2].X - PointSize, controlPoints[2].Y, PointSize * 4, PointSize));
+                drawingContext?.DrawRectangle(BorderBrush, null, new Rect(controlCurrentPoints[2].X - PointSize, controlCurrentPoints[2].Y - PointSize * 3, PointSize, PointSize * 4));
+                drawingContext?.DrawRectangle(BorderBrush, null, new Rect(controlCurrentPoints[2].X - PointSize, controlCurrentPoints[2].Y, PointSize * 4, PointSize));
             }
 
             //Bottom Center
             if (!ignoreList.Contains(PointControlType.MiddlBottom))
             {
-                drawingContext?.DrawRectangle(BorderBrush, null, new Rect((controlPoints[3].X + controlPoints[3].X - PointSize * 5) / 2, controlPoints[3].Y, PointSize * 5, PointSize));
+                drawingContext?.DrawRectangle(BorderBrush, null, new Rect((controlCurrentPoints[3].X + controlCurrentPoints[3].X - PointSize * 5) / 2, controlCurrentPoints[3].Y, PointSize * 5, PointSize));
             }
 
             //Bottom Right Corner
             if (!ignoreList.Contains(PointControlType.RightBottom))
             {
-                drawingContext?.DrawRectangle(BorderBrush, null, new Rect(controlPoints[4].X, controlPoints[4].Y - PointSize * 3, PointSize, PointSize * 4));
-                drawingContext?.DrawRectangle(BorderBrush, null, new Rect(controlPoints[4].X - PointSize * 3, controlPoints[4].Y, PointSize * 4, PointSize));
+                drawingContext?.DrawRectangle(BorderBrush, null, new Rect(controlCurrentPoints[4].X, controlCurrentPoints[4].Y - PointSize * 3, PointSize, PointSize * 4));
+                drawingContext?.DrawRectangle(BorderBrush, null, new Rect(controlCurrentPoints[4].X - PointSize * 3, controlCurrentPoints[4].Y, PointSize * 4, PointSize));
             }
 
             //Right Center
             if (!ignoreList.Contains(PointControlType.RightMiddle))
             {
-                drawingContext?.DrawRectangle(BorderBrush, null, new Rect(controlPoints[5].X, (controlPoints[5].Y + controlPoints[5].Y - PointSize * 5) / 2, PointSize, PointSize * 5));
+                drawingContext?.DrawRectangle(BorderBrush, null, new Rect(controlCurrentPoints[5].X, (controlCurrentPoints[5].Y + controlCurrentPoints[5].Y - PointSize * 5) / 2, PointSize, PointSize * 5));
             }
 
             //Right Top Corner
             if (!ignoreList.Contains(PointControlType.RightTop))
             {
-                drawingContext?.DrawRectangle(BorderBrush, null, new Rect(controlPoints[6].X, controlPoints[6].Y - PointSize, PointSize, PointSize * 4));
-                drawingContext?.DrawRectangle(BorderBrush, null, new Rect(controlPoints[6].X - PointSize * 4, controlPoints[6].Y - PointSize, PointSize * 4, PointSize));
+                drawingContext?.DrawRectangle(BorderBrush, null, new Rect(controlCurrentPoints[6].X, controlCurrentPoints[6].Y - PointSize, PointSize, PointSize * 4));
+                drawingContext?.DrawRectangle(BorderBrush, null, new Rect(controlCurrentPoints[6].X - PointSize * 4, controlCurrentPoints[6].Y - PointSize, PointSize * 4, PointSize));
             }
 
             //Top Center
             if (!ignoreList.Contains(PointControlType.MiddleTop))
             {
-                drawingContext?.DrawRectangle(BorderBrush, null, new Rect((controlPoints[7].X + controlPoints[7].X - PointSize * 5) / 2, controlPoints[7].Y - PointSize, PointSize * 5, PointSize));
+                drawingContext?.DrawRectangle(BorderBrush, null, new Rect((controlCurrentPoints[7].X + controlCurrentPoints[7].X - PointSize * 5) / 2, controlCurrentPoints[7].Y - PointSize, PointSize * 5, PointSize));
             }
+            BorderBrush = new SolidColorBrush(Color.FromArgb(0x3F, 0x00, 0x00, 0x00));
             drawingContext?.DrawGeometry(BorderBrush, PointPen, controlGroup);
         }
 
@@ -1069,7 +1445,7 @@ namespace ComPDFKit.Tool.DrawTool
         /// <param name="moveRect">
         /// Current rectangle to draw
         /// </param>
-        protected void DrawMoveBounds(DrawingContext drawDc, PointControlType controltype, Pen activePen, Brush moveBrush, Rect moveRect)
+        protected void DrawMoveBounds(DrawingContext drawDc, PointControlType controltype, Pen activePen, Brush moveBrush, Rect moveRect, Pen RectPen = null)
         {
             switch (controltype)
             {
@@ -1105,15 +1481,20 @@ namespace ComPDFKit.Tool.DrawTool
                     break;
                 case PointControlType.Body:
                 case PointControlType.Line:
-                    drawDc?.DrawLine(activePen, new Point(0, moveRect.Top), new Point(PDFViewerActualWidth, moveRect.Top));
-                    drawDc?.DrawLine(activePen, new Point(0, moveRect.Bottom), new Point(PDFViewerActualWidth, moveRect.Bottom));
-                    drawDc?.DrawLine(activePen, new Point(moveRect.Left, 0), new Point(moveRect.Left, PDFViewerActualHeight));
-                    drawDc?.DrawLine(activePen, new Point(moveRect.Right, 0), new Point(moveRect.Right, PDFViewerActualHeight));
+                    drawDc?.DrawLine(activePen, new Point(0, moveRect.Top), new Point(moveRect.Left, moveRect.Top));
+                    drawDc?.DrawLine(activePen, new Point(moveRect.Right, moveRect.Top), new Point(PDFViewerActualWidth, moveRect.Top));
+                    drawDc?.DrawLine(activePen, new Point(moveRect.Left, moveRect.Top), new Point(moveRect.Left, 0));
+                    drawDc?.DrawLine(activePen, new Point(moveRect.Right, moveRect.Top), new Point(moveRect.Right, 0));
+
+                    drawDc?.DrawLine(activePen, new Point(0, moveRect.Bottom), new Point(moveRect.Left, moveRect.Bottom));
+                    drawDc?.DrawLine(activePen, new Point(moveRect.Right, moveRect.Bottom), new Point(PDFViewerActualWidth, moveRect.Bottom));
+                    drawDc?.DrawLine(activePen, new Point(moveRect.Left, moveRect.Bottom), new Point(moveRect.Left, PDFViewerActualHeight));
+                    drawDc?.DrawLine(activePen, new Point(moveRect.Right, moveRect.Bottom), new Point(moveRect.Right, PDFViewerActualHeight));
                     break;
                 default:
                     break;
             }
-            drawDc?.DrawRectangle(moveBrush, null, moveRect);
+            drawDc?.DrawRectangle(moveBrush, RectPen, moveRect);
         }
 
         /// <summary>

+ 83 - 0
Demo/Examples/ComPDFKit.Tool/Help/CommonHelper.cs

@@ -5,6 +5,12 @@ using System.Text;
 using System.Threading.Tasks;
 using System.Windows.Media;
 using System.Windows;
+using ComPDFKitViewer;
+using System.IO;
+using System.Runtime.Remoting.Messaging;
+using System.Windows.Media.Imaging;
+using System.ComponentModel;
+using ComPDFKit.PDFAnnotation;
 
 namespace ComPDFKit.Tool.Help
 {
@@ -103,6 +109,83 @@ namespace ComPDFKit.Tool.Help
             catch { return children; }
         }
 
+        public static PathGeometry GetPathIcon(string iconKey)
+        {
+            string pathIcon = "M18 3H2V15H5V18L10 15H18V3ZM5 6H11V7.5H5V6ZM5 9.5H15V11H5V9.5Z";
+            try
+            {
+                TypeConverter typeCovert = TypeDescriptor.GetConverter(typeof(Geometry));
+                if (CPDFViewer.StickyIconDict != null && CPDFViewer.StickyIconDict.ContainsKey(iconKey))
+                {
+                    pathIcon = CPDFViewer.StickyIconDict[iconKey];
+                }
+
+                return PathGeometry.CreateFromGeometry((Geometry)typeCovert.ConvertFrom(pathIcon));
+            }
+            catch (Exception ex)
+            {
+
+            }
+
+            return new PathGeometry();
+        }
+
+        private static bool GetIconData(string iconName, Brush fillBrush, out string tempImagePath)
+        {
+            tempImagePath = string.Empty;
+
+            try
+            {
+                if (CPDFViewer.StickyIconDict != null && CPDFViewer.StickyIconDict.ContainsKey(iconName))
+                {
+                    PathGeometry iconGeometry = GetPathIcon(iconName);
+                    DrawingVisual iconVisual = new DrawingVisual();
+                    DrawingContext iconContext = iconVisual.RenderOpen();
+                    iconContext.DrawGeometry(fillBrush, null, iconGeometry);
+                    iconContext.Close();
+                    RenderTargetBitmap renderBitmap = new RenderTargetBitmap(32, 32, 96, 96, PixelFormats.Pbgra32);
+                    renderBitmap.Render(iconVisual);
+                    string tempPath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), Guid.NewGuid().ToString());
+
+                    PngBitmapEncoder pngEncoder = new PngBitmapEncoder();
+                    using (FileStream fs = File.Create(tempPath))
+                    {
+                        pngEncoder.Frames.Add(BitmapFrame.Create(renderBitmap));
+                        pngEncoder.Save(fs);
+                    }
+                    tempImagePath = tempPath;
+                    return true;
+                }
+            }
+            catch (Exception ex)
+            {
+
+            }
+
+            return false;
+        }
+
+        public static void UpdateStickyAP(CPDFTextAnnotation textAnnotation)
+        {
+            if(textAnnotation==null || textAnnotation.IsValid()==false)
+            {
+                return;
+            }
+            try
+            {
+                string iconName = textAnnotation.GetIconName();
+                byte opacity = textAnnotation.GetTransparency();
+                SolidColorBrush fillBrush = new SolidColorBrush(Color.FromArgb(opacity, textAnnotation.Color[0], textAnnotation.Color[1], textAnnotation.Color[2]));
 
+                if (GetIconData(iconName, fillBrush, out string apPath) && File.Exists(apPath))
+                {
+                    textAnnotation.UpdateApWithImage(apPath, string.Empty, textAnnotation.GetRotation());
+                    File.Delete(apPath);
+                }
+            }
+            catch (Exception ex)
+            {
+            }
+        }
     }
 }

+ 20 - 1
Demo/Examples/ComPDFKit.Tool/Help/PDFHelp.cs

@@ -173,7 +173,26 @@ namespace ComPDFKit.Tool.Help
                     frame.CopyPixels(imageData, frame.PixelWidth * 4, 0);
                 }
 
-                imageWidth = frame.PixelWidth;
+                int stride = ((int)frame.PixelWidth) * 4;
+                for (int i = 0; i < (int)(frame.PixelHeight); i++)
+                {
+                    for (int j = 0; j < (int)(frame.PixelWidth); j++)
+                    {
+                        byte b = imageData[i * stride + j * 4];
+                        byte g = imageData[i * stride + j * 4 + 1];
+                        byte r = imageData[i * stride + j * 4 + 2];
+                        byte a = imageData[i * stride + j * 4 + 3];
+
+                        if (a == 0 && b == 0 && g == 0 && r == 0)
+                        {
+                            imageData[i * stride + j * 4] = 255;
+                            imageData[i * stride + j * 4 + 1] = 255;
+                            imageData[i * stride + j * 4 + 2] = 255;
+                            continue;
+                        }
+                    }
+                }
+                        imageWidth = frame.PixelWidth;
                 imageHeight = frame.PixelHeight;
             }
         }

+ 87 - 9
Demo/Examples/ComPDFKit.Tool/Help/ParamConverter.cs

@@ -9,6 +9,7 @@ using ComPDFKit.PDFPage.Edit;
 using ComPDFKit.Tool.SettingParam;
 using ComPDFKit.Tool.UndoManger;
 using ComPDFKit.Viewer.Helper;
+using ComPDFKitViewer.Annot;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
@@ -64,7 +65,7 @@ namespace ComPDFKit.Tool.Help
                     annotHistory = new FreeTextAnnotHistory();
                     break;
                 case C_ANNOTATION_TYPE.C_ANNOTATION_LINE:
-                    if ((cPDFAnnotation as CPDFLineAnnotation).IsMersured())
+                    if ((cPDFAnnotation as CPDFLineAnnotation).IsMeasured())
                     {
                         annotHistory = new LineMeasureAnnotHistory();
                     }
@@ -169,6 +170,68 @@ namespace ComPDFKit.Tool.Help
             return annotHistory;
         }
 
+        public static AnnotHistory CreateHistory(AnnotParam annotParam)
+        {
+            if (annotParam != null)
+            {
+                switch (annotParam.CurrentType)
+                {
+                    case C_ANNOTATION_TYPE.C_ANNOTATION_HIGHLIGHT:
+                        return new HighlightAnnotHistory();
+                    case C_ANNOTATION_TYPE.C_ANNOTATION_UNDERLINE:
+                        return new UnderlineAnnotHistory();
+                    case C_ANNOTATION_TYPE.C_ANNOTATION_STRIKEOUT:
+                        return new StrikeoutAnnotHistory();
+                    case C_ANNOTATION_TYPE.C_ANNOTATION_SQUIGGLY:
+                        return new SquigglyAnnotHistory();
+                    case C_ANNOTATION_TYPE.C_ANNOTATION_INK:
+                        return new InkAnnotHistory();
+                    case C_ANNOTATION_TYPE.C_ANNOTATION_FREETEXT:
+                        return new FreeTextAnnotHistory();
+                    case C_ANNOTATION_TYPE.C_ANNOTATION_TEXT:
+                        return new StickyNoteAnnotHistory();
+                    case C_ANNOTATION_TYPE.C_ANNOTATION_SQUARE:
+                        return new SquareAnnotHistory();
+                    case C_ANNOTATION_TYPE.C_ANNOTATION_CIRCLE:
+                        return new CircleAnnotHistory();
+                    case C_ANNOTATION_TYPE.C_ANNOTATION_LINE:
+                        return new LineAnnotHistory();
+                    case C_ANNOTATION_TYPE.C_ANNOTATION_LINK:
+                        return new LinkAnnotHistory();
+                    case C_ANNOTATION_TYPE.C_ANNOTATION_STAMP:
+                        return new StampAnnotHistory();
+                    case C_ANNOTATION_TYPE.C_ANNOTATION_WIDGET:
+                        {
+                            WidgetParm widgetParam = annotParam as WidgetParm;
+                            if (widgetParam != null)
+                            {
+                                switch (widgetParam.WidgetType)
+                                {
+                                    case C_WIDGET_TYPE.WIDGET_RADIOBUTTON:
+                                        return new RadioButtonHistory();
+                                    case C_WIDGET_TYPE.WIDGET_CHECKBOX:
+                                        return new CheckBoxHistory();
+                                    case C_WIDGET_TYPE.WIDGET_TEXTFIELD:
+                                        return new TextBoxHistory();
+                                    case C_WIDGET_TYPE.WIDGET_LISTBOX:
+                                        return new ListBoxHistory();
+                                    case C_WIDGET_TYPE.WIDGET_COMBOBOX:
+                                        return new ComboBoxHistory();
+                                    case C_WIDGET_TYPE.WIDGET_PUSHBUTTON:
+                                        return new PushButtonHistory();
+                                    default:
+                                        break;
+                                }
+                            }
+                        }
+                        break;
+                    default:
+                        break;
+                }
+            }
+            return new AnnotHistory();
+        }
+
         public static bool RemovePageAnnot(Dictionary<int, List<int>> removeAnnots, CPDFDocument cPDFDocument)
         {
             if (cPDFDocument == null || removeAnnots.Count <= 0)
@@ -347,7 +410,7 @@ namespace ComPDFKit.Tool.Help
             bool isBold = false;
             bool isItalic = false;
 
-            cPDFEditArea.GetTextStyle(ref fontName, ref fontSize, ref fontColor, ref transparency, ref isBold, ref isItalic);
+            cPDFEditArea.GetTextStyle(ref fontName,ref fontSize, ref fontColor, ref transparency, ref isBold, ref isItalic);
             textEditParam.FontName = fontName;
             textEditParam.FontSize = fontSize;
             textEditParam.FontColor = fontColor;
@@ -821,7 +884,7 @@ namespace ComPDFKit.Tool.Help
                         CPDFLineAnnotation lineAnnot = pdfAnnot as CPDFLineAnnotation;
                         if (lineAnnot != null)
                         {
-                            if(lineAnnot.IsMersured())
+                            if(lineAnnot.IsMeasured())
                             {
                                 return GetLineMeasureParam(lineAnnot);
                             }
@@ -932,7 +995,7 @@ namespace ComPDFKit.Tool.Help
                 case C_ANNOTATION_TYPE.C_ANNOTATION_POLYLINE:
                     {
                         CPDFPolylineAnnotation polylineAnnot= pdfAnnot as CPDFPolylineAnnotation;
-                        if (polylineAnnot!=null && polylineAnnot.IsMersured())
+                        if (polylineAnnot!=null && polylineAnnot.IsMeasured())
                         {
                             return GetPolyLineMeasureParam(polylineAnnot);
                         }
@@ -941,7 +1004,7 @@ namespace ComPDFKit.Tool.Help
                 case C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON:
                     {
                         CPDFPolygonAnnotation polygonAnnot= pdfAnnot as CPDFPolygonAnnotation;
-                        if(polygonAnnot!=null && polygonAnnot.IsMersured())
+                        if(polygonAnnot!=null && polygonAnnot.IsMeasured())
                         {
                             return GetPolygonMeasureParam(polygonAnnot);
                         }
@@ -1231,7 +1294,7 @@ namespace ComPDFKit.Tool.Help
 
         internal static LineMeasureParam GetLineMeasureParam(CPDFLineAnnotation lineAnnot)
         {
-            if (lineAnnot == null || lineAnnot.IsValid() == false || lineAnnot.IsMersured()==false)
+            if (lineAnnot == null || lineAnnot.IsValid() == false || lineAnnot.IsMeasured()==false)
             {
                 return null;
             }
@@ -1245,7 +1308,9 @@ namespace ComPDFKit.Tool.Help
             {
                 measureParam.LineColor = new byte[3] { lineAnnot.LineColor[0], lineAnnot.LineColor[1], lineAnnot.LineColor[2] };
             }
-
+            measureParam.LeadLength=distanceMeasure.GetLeadLength();
+            measureParam.LeadExtension=distanceMeasure.GetLeadExtension();
+            measureParam.LeadOffset=distanceMeasure.GetLeadOffset();
             measureParam.BorderStyle = lineAnnot.BorderStyle;
             measureParam.LineWidth = lineAnnot.LineWidth;
             measureParam.Transparency = lineAnnot.Transparency;
@@ -1316,6 +1381,12 @@ namespace ComPDFKit.Tool.Help
                 }
             }
 
+            if(inkAnnot.Dash!=null && inkAnnot.Dash.Length>0)
+            {
+                inkParam.Dash =new float[inkAnnot.Dash.Length];
+                inkAnnot.Dash.CopyTo(inkParam.Dash, 0);
+            }
+
             GetAnnotCommonParam(inkAnnot, inkParam);
             return inkParam;
         }
@@ -1380,6 +1451,12 @@ namespace ComPDFKit.Tool.Help
                 freetextParam.Alignment = freetextAnnot.Alignment;
             }
 
+            if (freetextAnnot.Dash != null && freetextAnnot.Dash.Length > 0)
+            {
+                freetextParam.Dash = new float[freetextAnnot.Dash.Length];
+                freetextAnnot.Dash.CopyTo(freetextParam.Dash, 0);
+            }
+
             GetAnnotCommonParam(freetextAnnot, freetextParam);
             return freetextParam;
         }
@@ -1539,6 +1616,7 @@ namespace ComPDFKit.Tool.Help
                 };
             }
 
+            stickyParam.IconName=stickyAnnot.GetIconName();
             GetAnnotCommonParam(stickyAnnot, stickyParam);
 
             return stickyParam;
@@ -1732,7 +1810,7 @@ namespace ComPDFKit.Tool.Help
 
         internal static PolyLineMeasureParam GetPolyLineMeasureParam(CPDFPolylineAnnotation polylineAnnot)
         {
-            if (polylineAnnot == null || polylineAnnot.IsValid() == false || polylineAnnot.IsMersured()==false)
+            if (polylineAnnot == null || polylineAnnot.IsValid() == false || polylineAnnot.IsMeasured()==false)
             {
                 return null;
             }
@@ -1766,7 +1844,7 @@ namespace ComPDFKit.Tool.Help
 
         internal static PolygonMeasureParam GetPolygonMeasureParam(CPDFPolygonAnnotation polygonAnnot)
         {
-            if (polygonAnnot == null || polygonAnnot.IsValid() == false || polygonAnnot.IsMersured() == false)
+            if (polygonAnnot == null || polygonAnnot.IsValid() == false || polygonAnnot.IsMeasured() == false)
             {
                 return null;
             }

+ 70 - 81
Demo/Examples/ComPDFKit.Tool/PDFTextSearch.cs

@@ -5,11 +5,8 @@ using ComPDFKit.PDFPage;
 using System;
 using System.Collections.Generic;
 using System.Diagnostics;
-using System.Linq;
-using System.Text;
 using System.Text.RegularExpressions;
 using System.Threading;
-using System.Threading.Tasks;
 using System.Windows.Media;
 using System.Windows;
 
@@ -150,104 +147,96 @@ namespace ComPDFKit.Tool
             searchResult.StartPage = startPage;
             searchResult.EndPage = endPage;
             double searchPercent = 100;
-            try
-            {
 
-                mSearchDocument = CPDFDocument.InitWithFilePath(TextSearchDocument.FilePath);
-                if (password != null && password != string.Empty)
-                {
-                    mSearchDocument.UnlockWithPassword(password);
-                }
-                password = string.Empty;
-            }
-            catch (Exception ex)
+            mSearchDocument = CPDFDocument.InitWithFilePath(TextSearchDocument.FilePath);
+            if (mSearchDocument.IsLocked && !string.IsNullOrEmpty(password))
             {
-
+                mSearchDocument.UnlockWithPassword(password);
             }
-            if (mSearchDocument != null)
+
+            if (mSearchDocument != null && !mSearchDocument.IsLocked)
             {
-                try
+                int pageMaxCount = 0;
+                int recordCount = 0;
+                searchPercent = 0;
+                for (int i = startPage; i <= endPage; i++)
                 {
-                    int pageMaxCount = 0;
-                    int recordCount = 0;
-                    searchPercent = 0;
-                    for (int i = startPage; i <= endPage; i++)
+                    CPDFTextSearcher mPDFTextSearcher = new CPDFTextSearcher();
+                    CPDFPage pageCore = mSearchDocument.PageAtIndex(i);
+                    if(pageCore == null)
                     {
-                        CPDFTextSearcher mPDFTextSearcher = new CPDFTextSearcher();
-                        CPDFPage pageCore = mSearchDocument.PageAtIndex(i);
-                        CPDFTextPage textPage = pageCore.GetTextPage();
-                        int startIndex = 0;
+                        continue;
+                    }   
 
-                        List<TextSearchItem> textSearchItems = new List<TextSearchItem>();
-                        if (mPDFTextSearcher.FindStart(textPage, searchKeywords, searchOption, startIndex))
+                    CPDFTextPage textPage = pageCore.GetTextPage();
+                    int startIndex = 0;
+                    List<TextSearchItem> textSearchItems = new List<TextSearchItem>();
+                    if (mPDFTextSearcher.FindStart(textPage, searchKeywords, searchOption, startIndex))
+                    {
+                        CRect textRect = new CRect();
+                        string textContent = "";
+                        while (mPDFTextSearcher.FindNext(pageCore, textPage, ref textRect, ref textContent, ref startIndex))
                         {
-                            CRect textRect = new CRect();
-                            string textContent = "";
-                            while (mPDFTextSearcher.FindNext(pageCore, textPage, ref textRect, ref textContent, ref startIndex))
+                            if (textContent == "")
                             {
-                                if (textContent == "")
-                                {
-                                    textContent = searchKeywords;
-                                }
-                                textSearchItems.Add(new TextSearchItem()
-                                {
-                                    PageIndex = i,
-                                    TextRect = new Rect(textRect.left, textRect.top, textRect.width(), textRect.height()),
-                                    TextContent = textContent,
-                                    PageRotate = pageCore.Rotation
-                                });
-                                var matchResult = Regex.Matches(textContent, searchKeywords, RegexOptions.IgnoreCase);
-                                if (matchResult != null)
-                                {
-                                    recordCount += matchResult.Count;
-                                }
+                                textContent = searchKeywords;
+                            }
+
+                            textSearchItems.Add(new TextSearchItem()
+                            {
+                                PageIndex = i,
+                                TextRect = new Rect(textRect.left, textRect.top, textRect.width(), textRect.height()),
+                                TextContent = textContent,
+                                PageRotate = pageCore.Rotation
+                            });
+
+                            var matchResult = Regex.Matches(textContent, searchKeywords, RegexOptions.IgnoreCase);
+                            if (matchResult != null)
+                            {
+                                recordCount += matchResult.Count;
                             }
-                        }
-                        mPDFTextSearcher.FindClose();
-                        if (textSearchItems.Count > 0)
-                        {
-                            searchResult.Items.Add(i, textSearchItems);
-                        }
-                        pageMaxCount = Math.Max(pageMaxCount, textSearchItems.Count);
-                        searchResult.TotalCount = recordCount;
-                        searchResult.PageMaxCount = pageMaxCount;
-                        if (SearchPercentHandler != null)
-                        {
-                            searchPercent = (int)((i + 1 - startPage) * 100 / (endPage + 1 - startPage));
-                            searchResult.Percent = searchPercent;
-                            searchResult.CurrentPage = i;
-                            SearchPercentHandler.Invoke(this, searchResult);
-                        }
-                        mSearchDocument.ReleasePages(i);
-                        if (isCancel)
-                        {
-                            break;
                         }
                     }
-                    searchPercent = 100;
-                }
-                catch (Exception ex)
-                {
 
+                    mPDFTextSearcher.FindClose();
+                    if (textSearchItems.Count > 0)
+                    {
+                        searchResult.Items.Add(i, textSearchItems);
+                    }
+
+                    pageMaxCount = Math.Max(pageMaxCount, textSearchItems.Count);
+                    searchResult.TotalCount = recordCount;
+                    searchResult.PageMaxCount = pageMaxCount;
+                    if (SearchPercentHandler != null)
+                    {
+                        searchPercent = (int)((i + 1 - startPage) * 100 / (endPage + 1 - startPage));
+                        searchResult.Percent = searchPercent;
+                        searchResult.CurrentPage = i;
+                        SearchPercentHandler.Invoke(this, searchResult);
+                    }
+
+                    mSearchDocument.ReleasePages(i);
+                    if (isCancel)
+                    {
+                        break;
+                    }
                 }
+
+                searchPercent = 100;
                 mSearchDocument.Release();
             }
-            try
+
+            if (SearchCompletedHandler != null && !isCancel)
             {
-                if (SearchCompletedHandler != null && !isCancel)
-                {
-                    searchResult.Percent = searchPercent;
-                    SearchCompletedHandler.Invoke(this, searchResult);
-                }
-                if (SearchCancelHandler != null && isCancel)
-                {
-                    SearchCancelHandler.Invoke(this, searchResult);
-                }
+                searchResult.Percent = searchPercent;
+                SearchCompletedHandler.Invoke(this, searchResult);
             }
-            catch (Exception ex)
-            {
 
+            if (SearchCancelHandler != null && isCancel)
+            {
+                SearchCancelHandler.Invoke(this, searchResult);
             }
+
             CanDoSearch = true;
             isCancel = false;
         }

+ 9 - 1
Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/FreeTextParam.cs

@@ -21,11 +21,11 @@ namespace ComPDFKit.Tool
         public string FontName { get; set; } = string.Empty;
         public double FontSize { get; set; }
         public C_TEXT_ALIGNMENT Alignment {  get; set; }
+        public float[] Dash { get; set; }
 
         public bool IsReadOnly { get; set; }
         public override bool CopyTo(AnnotParam transfer)
         {
-            
             FreeTextParam freetextTransfer = transfer as FreeTextParam;
             if (freetextTransfer == null)
             {
@@ -52,6 +52,14 @@ namespace ComPDFKit.Tool
                 freetextTransfer.FontColor = (byte[])FontColor.Clone();
             }
 
+            freetextTransfer.Dash = null;
+            if (Dash != null)
+            {
+                float[] DashCopy = new float[Dash.Length];
+                Dash.CopyTo(DashCopy, 0);
+                freetextTransfer.Dash = DashCopy;
+            }
+
             freetextTransfer.HasBgColor = HasBgColor;
             freetextTransfer.LineWidth = LineWidth;
             freetextTransfer.IsBold = IsBold;

+ 9 - 2
Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/InkParam.cs

@@ -15,7 +15,7 @@ namespace ComPDFKit.Tool
         public byte[] InkColor { get; set; }
         public double Thickness { get; set; }
         public List<List<CPoint>> InkPath { get; set; }
-
+        public float[] Dash { get; set; }
         public override bool CopyTo(AnnotParam transfer)
         {
             InkParam inkTransfer = transfer as InkParam;
@@ -51,7 +51,14 @@ namespace ComPDFKit.Tool
 
                 inkTransfer.InkPath = inkPoints;
             }
-
+            inkTransfer.Dash = null;
+            if (Dash != null)
+            {
+                float[] DashCopy=new float[Dash.Length];
+                Dash.CopyTo(DashCopy,0);
+                inkTransfer.Dash = DashCopy;
+            }
+            
             return true;
         }
     }

+ 23 - 18
Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/LineMeasureParam.cs

@@ -30,33 +30,35 @@ namespace ComPDFKit.Tool
         public bool IsItalic { get; set; }
         public C_BORDER_STYLE BorderStyle { get; set; }
         public CPDFMeasureInfo measureInfo { get; set; }
-
+        public double LeadLength {  get; set; }
+        public double LeadExtension {  get; set; }
+        public double LeadOffset {  get; set; }
         public override bool CopyTo(AnnotParam transfer)
         {
-            LineMeasureParam polygonTransfer = transfer as LineMeasureParam;
-            if (polygonTransfer == null)
+            LineMeasureParam lineTransfer = transfer as LineMeasureParam;
+            if (lineTransfer == null)
             {
                 return false;
             }
 
-            if (!base.CopyTo(polygonTransfer))
+            if (!base.CopyTo(lineTransfer))
             {
                 return false;
             }
 
             if (LineColor != null)
             {
-                polygonTransfer.LineColor = (byte[])LineColor.Clone();
+                lineTransfer.LineColor = (byte[])LineColor.Clone();
             }
 
             if (LineDash != null)
             {
-                polygonTransfer.LineDash = (float[])LineDash.Clone();
+                lineTransfer.LineDash = (float[])LineDash.Clone();
             }
 
             if (FontColor != null)
             {
-                polygonTransfer.FontColor = (byte[])FontColor.Clone();
+                lineTransfer.FontColor = (byte[])FontColor.Clone();
             }
 
             if (measureInfo != null)
@@ -78,19 +80,22 @@ namespace ComPDFKit.Tool
                     RulerTranslate= measureInfo.RulerTranslate,
                     CaptionType = measureInfo.CaptionType,
                 };
-                polygonTransfer.measureInfo = cPDFMeasureInfo;
+                lineTransfer.measureInfo = cPDFMeasureInfo;
             }
 
-            polygonTransfer.LineWidth = LineWidth;
-            polygonTransfer.HeadLineType = HeadLineType;
-            polygonTransfer.TailLineType = TailLineType;
-            polygonTransfer.FontName = FontName;
-            polygonTransfer.FontSize = FontSize;
-            polygonTransfer.IsBold = IsBold;
-            polygonTransfer.IsItalic = IsItalic;
-            polygonTransfer.HeadPoint = HeadPoint;
-            polygonTransfer.TailPoint = TailPoint;
-            polygonTransfer.BorderStyle = BorderStyle;
+            lineTransfer.LineWidth = LineWidth;
+            lineTransfer.HeadLineType = HeadLineType;
+            lineTransfer.TailLineType = TailLineType;
+            lineTransfer.FontName = FontName;
+            lineTransfer.FontSize = FontSize;
+            lineTransfer.IsBold = IsBold;
+            lineTransfer.IsItalic = IsItalic;
+            lineTransfer.HeadPoint = HeadPoint;
+            lineTransfer.TailPoint = TailPoint;
+            lineTransfer.BorderStyle = BorderStyle;
+            lineTransfer.LeadExtension=LeadExtension;
+            lineTransfer.LeadLength = LeadLength;
+            lineTransfer.LeadOffset = LeadOffset;
 
             return true;
         }

+ 5 - 1
Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/StampParam.cs

@@ -18,7 +18,10 @@ namespace ComPDFKit.Tool
 		public C_TEXTSTAMP_COLOR TextStampColor {  get; set; }
 		public MemoryStream ImageStream { get; set; }
 		public int Rotation { get; set; }	
-
+		//暂时做旋转用
+		//后续底层更新旋转角度支持后废除
+		//-1 逆时针 0 未动  1顺时针
+		public int Clockwise {  get; set; }
 
         public override bool CopyTo(AnnotParam transfer)
 		{
@@ -40,6 +43,7 @@ namespace ComPDFKit.Tool
 			stampTransfer.TextStampShape = TextStampShape;
 			stampTransfer.ImageStream = ImageStream;
 			stampTransfer.Rotation = Rotation;
+			stampTransfer.Clockwise = Clockwise;
 
 			return true;
 		}

+ 3 - 0
Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/StickyNoteParam.cs

@@ -11,6 +11,7 @@ namespace ComPDFKit.Tool
         }
 
         public byte[] StickyNoteColor { get; set; }
+        public string IconName { get; set; } = string.Empty;
 
         public override bool CopyTo(AnnotParam transfer)
         {
@@ -30,6 +31,8 @@ namespace ComPDFKit.Tool
                 stickynoteTransfer.StickyNoteColor = (byte[])StickyNoteColor.Clone();
             }
 
+            stickynoteTransfer.IconName = IconName;
+
             return true;
         }
     }

+ 18 - 0
Demo/Examples/ComPDFKit.Tool/SettingParam/DefaultSettingParam.cs

@@ -1112,6 +1112,14 @@ namespace ComPDFKit.Tool.SettingParam
             get { return pDFEditMovePen.Clone(); }
             set { pDFEditMovePen = value; }
         }
+        private Pen pDFEditMoveRectPen;
+
+        public Pen PDFEditMoveRectPen
+        {
+            get { return pDFEditMoveRectPen.Clone(); }
+            set { pDFEditMoveRectPen = value; }
+        }
+
 
         #region Not selected state
 
@@ -1331,6 +1339,14 @@ namespace ComPDFKit.Tool.SettingParam
             set { pDFEditMultiMovePen = value; }
         }
 
+        private Pen pDFEditMultiMoveRectPen;
+
+        public Pen PDFEditMultiMoveRectPen
+        {
+            get { return pDFEditMultiMoveRectPen.Clone(); }
+            set { pDFEditMultiMoveRectPen = value; }
+        }
+
         #region Not selected state
 
         private SolidColorBrush pDFEditMultiRectFillBrush;
@@ -1620,6 +1636,7 @@ namespace ComPDFKit.Tool.SettingParam
             CaretBrush = new SolidColorBrush(Color.FromArgb(0x46, 0x46, 0x82, 0xB4));
             CaretPen = new Pen(Brushes.Black, 1);
             PDFEditMovePen = new Pen(new SolidColorBrush(Color.FromRgb(0x00, 0xFF, 0x00)), 2);
+            PDFEditMoveRectPen = new Pen(new SolidColorBrush(Color.FromRgb(0x00, 0xFF, 0x00)), 2);
             PDFEditMoveBrush = new SolidColorBrush(Color.FromArgb(0x46, 0x46, 0x82, 0xB4));
 
 
@@ -1657,6 +1674,7 @@ namespace ComPDFKit.Tool.SettingParam
             ViewerImageBackgroundBrush = new SolidColorBrush(Color.FromArgb(0x46, 0x46, 0x82, 0xB4));
 
             //PDFEditMultiSelected
+            PDFEditMultiMoveRectPen = new Pen(new SolidColorBrush(Color.FromRgb(0x00, 0xFF, 0x00)), 2);
             PDFEditMultiMovePen = new Pen(new SolidColorBrush(Color.FromRgb(0x00, 0xFF, 0x00)), 2);
             PDFEditMultiMoveBrush = new SolidColorBrush(Color.FromArgb(0x46, 0x46, 0x82, 0xB4));
 

+ 2 - 2
Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory.cs

@@ -114,7 +114,7 @@ namespace ComPDFKit.Tool.UndoManger
             {
                 checkAnnotList.Add((AnnotHistory)checkItem);
             }
-            //而且 checkAnnotList 要从大到小排序
+
             List<AnnotHistory> loopList = new List<AnnotHistory>();
             if (checkAnnotList != null && checkAnnotList.Count > 0)
             {
@@ -169,7 +169,7 @@ namespace ComPDFKit.Tool.UndoManger
             if (GetPageIndex() == pageIndex)
             {
                 int oldIndex = GetAnnotIndex();
-                if (oldIndex == annotIndex && oldIndex>=0)
+                if (oldIndex == annotIndex && oldIndex >= 0)
                 {
                     SetAnnotIndex(-1);
                     HistoryIndex = -1;

+ 18 - 26
Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/FreeTextAnnotHistory.cs

@@ -1,6 +1,7 @@
 using ComPDFKit.PDFAnnotation;
 using ComPDFKit.PDFPage;
 using ComPDFKit.Tool.Help;
+using ComPDFKitViewer.Annot;
 using static ComPDFKit.PDFAnnotation.CTextAttribute.CFontNameHelper;
 
 namespace ComPDFKit.Tool.UndoManger
@@ -80,10 +81,7 @@ namespace ComPDFKit.Tool.UndoManger
                 }
                 textAttr.FontColor = fontColor;
                 textAttr.FontSize = (float)currentParam.FontSize;
-                textAttr.FontName = ObtainFontName(
-					GetFontType(currentParam.FontName),
-                    currentParam.IsBold,
-                    currentParam.IsItalic);
+                textAttr.FontName = currentParam.FontName;
 
                 textAnnot.SetFreetextDa(textAttr);
 
@@ -98,6 +96,12 @@ namespace ComPDFKit.Tool.UndoManger
                 {
                     textAnnot.SetContent(currentParam.Content);
                 }
+
+                if (currentParam.Dash != null && currentParam.Dash.Length > 0)
+                {
+                    textAnnot.SetBorderStyle(C_BORDER_STYLE.BS_DASHDED, currentParam.Dash);
+                }
+
                 textAnnot.SetIsLocked(currentParam.Locked);
                 textAnnot.SetCreationDate(PDFHelp.GetCurrentPdfTime());
                 textAnnot.UpdateAp();
@@ -176,10 +180,7 @@ namespace ComPDFKit.Tool.UndoManger
                 if(updateParam.FontName != checkParam.FontName)
                 {
                     CTextAttribute textAttr = textAnnot.FreeTextDa;
-                    bool isBold = IsBold(textAttr.FontName);
-                    bool isItalic = IsItalic(textAttr.FontName);
-                    FontType fontType = GetFontType(updateParam.FontName);
-                    textAttr.FontName = ObtainFontName(fontType, isBold, isItalic);
+                    textAttr.FontName = updateParam.FontName;
                     textAnnot.SetFreetextDa(textAttr);
                 }
 
@@ -199,24 +200,6 @@ namespace ComPDFKit.Tool.UndoManger
                         textAnnot.SetFreetextDa(textAttr);
                     }
                 }
-               
-                if(updateParam.IsBold != checkParam.IsBold)
-                {
-                    CTextAttribute textAttr = textAnnot.FreeTextDa;
-                    bool isItalic = IsItalic(textAttr.FontName);
-                    FontType fontType = GetFontType(textAttr.FontName);
-                    textAttr.FontName = ObtainFontName(fontType, updateParam.IsBold, isItalic);
-                    textAnnot.SetFreetextDa(textAttr);
-                }
-
-                if(updateParam.IsItalic != checkParam.IsItalic)
-                {
-                    CTextAttribute textAttr = textAnnot.FreeTextDa;
-                    bool isBold = IsBold(textAttr.FontName);
-                    FontType fontType = GetFontType(textAttr.FontName);
-                    textAttr.FontName = ObtainFontName(fontType, isBold, updateParam.IsItalic);
-                    textAnnot.SetFreetextDa(textAttr);
-                }
 
                 if (!updateParam.ClientRect.Equals(checkParam.ClientRect))
                 {
@@ -238,6 +221,15 @@ namespace ComPDFKit.Tool.UndoManger
                     textAnnot.SetIsLocked(updateParam.Locked);
                 }
 
+                if (updateParam.Dash != null && updateParam.Dash.Length > 0)
+                {
+                    textAnnot.SetBorderStyle(C_BORDER_STYLE.BS_DASHDED, updateParam.Dash);
+                }
+                else
+                {
+                    textAnnot.SetBorderStyle(C_BORDER_STYLE.BS_SOLID, new float[0]);
+                }
+
                 textAnnot.SetModifyDate(PDFHelp.GetCurrentPdfTime());
                 textAnnot.UpdateAp();
 

+ 15 - 0
Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/InkAnnotHistory.cs

@@ -69,6 +69,12 @@ namespace ComPDFKit.Tool.UndoManger
                 {
                     inkAnnot.SetContent(currentParam.Content);
                 }
+
+                if (currentParam.Dash != null && currentParam.Dash.Length > 0)
+                {
+                    inkAnnot.SetBorderStyle(C_BORDER_STYLE.BS_DASHDED,currentParam.Dash);
+                }
+
                 inkAnnot.SetIsLocked(currentParam.Locked);
                 inkAnnot.SetCreationDate(PDFHelp.GetCurrentPdfTime());
                 inkAnnot.UpdateAp();
@@ -124,6 +130,15 @@ namespace ComPDFKit.Tool.UndoManger
                     inkAnnot.SetInkPath(updateParam.InkPath);
                 }
 
+                if (updateParam.Dash!=null && updateParam.Dash.Length>0)
+                {
+                    inkAnnot.SetBorderStyle(C_BORDER_STYLE.BS_DASHDED,updateParam.Dash);
+                }
+                else
+                {
+                    inkAnnot.SetBorderStyle(C_BORDER_STYLE.BS_SOLID,new float[0]);
+                }
+
                 if (updateParam.Transparency != checkParam.Transparency)
                 {
                     inkAnnot.SetTransparency((byte)updateParam.Transparency);

+ 14 - 10
Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/LineMeasureAnnotHistory.cs

@@ -102,6 +102,9 @@ namespace ComPDFKit.Tool.UndoManger
                     CPDFDistanceMeasure polygonMeasure = polygonAnnot.GetDistanceMeasure();
                     if (polygonMeasure != null)
                     {
+                        polygonMeasure.SetLeadLength((float)currentParam.LeadLength);
+                        polygonMeasure.SetLeadExtension((float)currentParam.LeadExtension);
+                        polygonMeasure.SetLeadOffset((float)currentParam.LeadOffset);
                         polygonMeasure.SetMeasureInfo(currentParam.measureInfo);
                         polygonMeasure.SetMeasureScale(currentParam.measureInfo.RulerBase, currentParam.measureInfo.RulerBaseUnit,
                                                        currentParam.measureInfo.RulerTranslate, currentParam.measureInfo.RulerTranslateUnit);
@@ -143,7 +146,7 @@ namespace ComPDFKit.Tool.UndoManger
             if (MakeAnnotValid(CurrentParam))
             {
                 CPDFLineAnnotation polygonAnnot = Annot as CPDFLineAnnotation;
-                if (polygonAnnot == null || !polygonAnnot.IsValid() || !polygonAnnot.IsMersured())
+                if (polygonAnnot == null || !polygonAnnot.IsValid() || !polygonAnnot.IsMeasured())
                 {
                     return false;
                 }
@@ -209,16 +212,17 @@ namespace ComPDFKit.Tool.UndoManger
                 {
                     polygonAnnot.SetIsLocked(updateParam.Locked);
                 }
-                if (updateParam.measureInfo != checkParam.measureInfo)
+
+                CPDFDistanceMeasure polygonMeasure = polygonAnnot.GetDistanceMeasure();
+                if (polygonMeasure != null)
                 {
-                    CPDFDistanceMeasure polygonMeasure = polygonAnnot.GetDistanceMeasure();
-                    if (polygonMeasure != null)
-                    {
-                        polygonMeasure.SetMeasureInfo(updateParam.measureInfo);
-                        polygonMeasure.SetMeasureScale(updateParam.measureInfo.RulerBase, updateParam.measureInfo.RulerBaseUnit,
-                                                       updateParam.measureInfo.RulerTranslate, updateParam.measureInfo.RulerTranslateUnit);
-                        polygonMeasure.UpdateAnnotMeasure();
-                    }
+                    polygonMeasure.SetLeadLength((float)updateParam.LeadLength);
+                    polygonMeasure.SetLeadExtension((float)updateParam.LeadExtension);
+                    polygonMeasure.SetLeadOffset((float)updateParam.LeadOffset);
+                    polygonMeasure.SetMeasureInfo(updateParam.measureInfo);
+                    polygonMeasure.SetMeasureScale(updateParam.measureInfo.RulerBase, updateParam.measureInfo.RulerBaseUnit,
+                                                   updateParam.measureInfo.RulerTranslate, updateParam.measureInfo.RulerTranslateUnit);
+                    polygonMeasure.UpdateAnnotMeasure();
                 }
                 polygonAnnot.SetModifyDate(PDFHelp.GetCurrentPdfTime());
 

+ 1 - 1
Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/PolyLineMeasureAnnotHistory.cs

@@ -137,7 +137,7 @@ namespace ComPDFKit.Tool.UndoManger
             if (MakeAnnotValid(CurrentParam))
             {
                 CPDFPolylineAnnotation polygonAnnot = Annot as CPDFPolylineAnnotation;
-                if (polygonAnnot == null || !polygonAnnot.IsValid() || !polygonAnnot.IsMersured())
+                if (polygonAnnot == null || !polygonAnnot.IsValid() || !polygonAnnot.IsMeasured())
                 {
                     return false;
                 }

+ 1 - 1
Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/PolygonMeasureAnnotHistory.cs

@@ -146,7 +146,7 @@ namespace ComPDFKit.Tool.UndoManger
             if (MakeAnnotValid(CurrentParam))
             {
                 CPDFPolygonAnnotation polygonAnnot = Annot as CPDFPolygonAnnotation;
-                if (polygonAnnot == null || !polygonAnnot.IsValid() || !polygonAnnot.IsMersured())
+                if (polygonAnnot == null || !polygonAnnot.IsValid() || !polygonAnnot.IsMeasured())
                 {
                     return false;
                 }

+ 242 - 9
Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/StampAnnotHistory.cs

@@ -1,7 +1,11 @@
-using ComPDFKit.PDFAnnotation;
+using ComPDFKit.Import;
+using ComPDFKit.PDFAnnotation;
 using ComPDFKit.PDFPage;
 using ComPDFKit.Tool.Help;
+using System;
 using System.IO;
+using System.IO.Ports;
+using System.Windows;
 using System.Windows.Media;
 using System.Windows.Media.Imaging;
 
@@ -120,11 +124,16 @@ namespace ComPDFKit.Tool.UndoManger
 					default:
 						break;
 				}
+                //stampAnnot.UpdateAp();
+                stampAnnot.SetTransparency((byte)currentParam.Transparency);
+                //string imagePath = string.Empty;
+                //if (GetAnnotOpacityImage(stampAnnot, currentParam.Transparency / 255.0, 5, out imagePath) && File.Exists(imagePath))
+                //{
+                //    stampAnnot.SetImageStamp(imagePath, string.Empty);
+                //    File.Delete(imagePath);
+                //}
 
-				stampAnnot.SetTransparency((byte)currentParam.Transparency);
-				
-
-				if (!string.IsNullOrEmpty(currentParam.Author))
+                if (!string.IsNullOrEmpty(currentParam.Author))
 				{
 					stampAnnot.SetAuthor(currentParam.Author);
 				}
@@ -171,10 +180,38 @@ namespace ComPDFKit.Tool.UndoManger
 				StampParam updateParam = (isUndo ? PreviousParam : CurrentParam) as StampParam;
 				StampParam checkParam = (isUndo ? CurrentParam : PreviousParam) as StampParam;
 
-				if (updateParam.Transparency != checkParam.Transparency)
+                if (updateParam.Clockwise!=0)
+                {
+                    string imagePath = string.Empty;
+
+                    bool clockwise = updateParam.Clockwise== 1 ? true : false;
+                    if(isUndo)
+                    {
+                        clockwise=!clockwise;
+                    }
+
+                    if (GetAnnotRotateImage(stampAnnot, clockwise, 5, out imagePath) && File.Exists(imagePath))
+                    {
+                        CRect rawRect = stampAnnot.GetRect();
+                        Point centerPos = new Point(rawRect.left + rawRect.width() / 2, rawRect.top + rawRect.height() / 2);
+                        Rect saveRect = new Rect(centerPos.X - rawRect.height() / 2, centerPos.Y - rawRect.width() / 2, rawRect.height(), rawRect.width());
+
+                        stampAnnot.SetRect(new CRect((float)saveRect.Left, (float)saveRect.Bottom, (float)saveRect.Right, (float)saveRect.Top));
+                        stampAnnot.SetImageStamp(imagePath, string.Empty);
+                        File.Delete(imagePath);
+                    }
+                }
+
+                if (updateParam.Transparency != checkParam.Transparency)
 				{
-					stampAnnot.SetTransparency((byte)updateParam.Transparency);
-				}
+                    string imagePath = string.Empty;
+                    if (GetAnnotOpacityImage(stampAnnot, updateParam.Transparency/255.0, 5, out imagePath) && File.Exists(imagePath))
+                    {
+                        stampAnnot.SetImageStamp(imagePath, string.Empty);
+                        File.Delete(imagePath);
+                    }
+                    stampAnnot.SetTransparency((byte)updateParam.Transparency);
+                }
 
 				if (!updateParam.ClientRect.Equals(checkParam.ClientRect))
                 {
@@ -213,5 +250,201 @@ namespace ComPDFKit.Tool.UndoManger
 			}
 			return false;
 		}
-	}
+
+        private bool GetAnnotRotateImage(CPDFStampAnnotation annot, bool clockwise, double zoom, out string imagePath)
+        {
+            imagePath = string.Empty;
+
+            if (annot == null || annot.IsValid() == false)
+            {
+                return false;
+            }
+
+            try
+            {
+                double opacity = annot.GetTransparency() / 255.0;
+                CRect rawRect = annot.GetRect();
+                Rect drawRect = new Rect(0, 0, (int)(rawRect.width() * 96.0 / 72.0 * zoom), (int)(rawRect.height() * 96.0 / 72.0 * zoom));
+
+                byte[] imageData = new byte[(int)drawRect.Width * (int)drawRect.Height * 4];
+                annot.RenderAnnot((int)drawRect.Width, (int)drawRect.Height, imageData);
+
+                int stride = ((int)drawRect.Width) * 4;
+                for (int i = 0; i < (int)(drawRect.Height); i++)
+                {
+                    for (int j = 0; j < (int)(drawRect.Width); j++)
+                    {
+                        byte b = imageData[i * stride + j * 4];
+                        byte g = imageData[i * stride + j * 4 + 1];
+                        byte r = imageData[i * stride + j * 4 + 2];
+                        byte a = imageData[i * stride + j * 4 + 3];
+
+                        if (a == 0 && b == 255 && g == 255 && r == 255)
+                        {
+                            continue;
+                        }
+
+                        if (a == 0 && opacity > 0)
+                        {
+                            imageData[i * stride + j * 4] = 255;
+                            imageData[i * stride + j * 4 + 1] = 255;
+                            imageData[i * stride + j * 4 + 2] = 255;
+                            continue;
+                        }
+
+                        if (opacity == 0)
+                        {
+                            imageData[i * stride + j * 4 + 3] = 255;
+                            continue;
+                        }
+                        imageData[i * stride + j * 4 + 3] = (byte)(opacity * 255);
+                    }
+                }
+
+                WriteableBitmap writeImage = new WriteableBitmap((int)drawRect.Width, (int)drawRect.Height, 96, 96, PixelFormats.Bgra32, null);
+                writeImage.WritePixels(new Int32Rect(0, 0, (int)drawRect.Width, (int)drawRect.Height), imageData, ((int)drawRect.Width) * 4, 0);
+
+                RotateTransform rotateTransform = new RotateTransform();
+                rotateTransform.Angle = clockwise ? 90 : -90;
+                rotateTransform.CenterX = drawRect.Width / 2;
+                rotateTransform.CenterY = drawRect.Height / 2;
+                TranslateTransform translateTransform = new TranslateTransform();
+                if (clockwise == false)
+                {
+                    translateTransform.X = -(drawRect.Width - drawRect.Height) / 2;
+                    translateTransform.Y = -(drawRect.Width - drawRect.Height) / 2;
+                }
+                else
+                {
+                    translateTransform.X = (drawRect.Width - drawRect.Height) / 2;
+                    translateTransform.Y = (drawRect.Width - drawRect.Height) / 2;
+                }
+
+                DrawingVisual drawVisual = new DrawingVisual();
+
+                DrawingContext drawDC = drawVisual.RenderOpen();
+                drawDC.PushTransform(rotateTransform);
+                drawDC.PushTransform(translateTransform);
+                drawDC.DrawImage(writeImage, new Rect(0, 0, writeImage.Width, writeImage.Height));
+                drawDC.Pop();
+                drawDC.Pop();
+                drawDC.Close();
+
+                RenderTargetBitmap renderBitmap = new RenderTargetBitmap((int)drawRect.Height, (int)drawRect.Width, 96, 96, PixelFormats.Pbgra32);
+                renderBitmap.Render(drawVisual);
+                string tempPath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), Guid.NewGuid().ToString());
+                BitmapSource saveImageData = renderBitmap;
+                if (opacity == 0)
+                {
+                    stride = saveImageData.PixelWidth * 4;
+                    imageData = new byte[stride * saveImageData.PixelHeight];
+                    saveImageData.CopyPixels(imageData, stride, 0);
+                    for (int i = 0; i < saveImageData.PixelHeight; i++)
+                    {
+                        for (int j = 0; j < saveImageData.PixelWidth; j++)
+                        {
+                            byte b = imageData[i * stride + j * 4];
+                            byte g = imageData[i * stride + j * 4 + 1];
+                            byte r = imageData[i * stride + j * 4 + 2];
+                            byte a = imageData[i * stride + j * 4 + 3];
+
+                            if (a == 0 && b == 255 && g == 255 && r == 255)
+                            {
+                                continue;
+                            }
+
+                            if (a == 0 && b == 0 && g == 0 && r == 0)
+                            {
+                                imageData[i * stride + j * 4] = 255;
+                                imageData[i * stride + j * 4 + 1] = 255;
+                                imageData[i * stride + j * 4 + 2] = 255;
+                                continue;
+                            }
+
+                            imageData[i * stride + j * 4 + 3] = (byte)(opacity * 255);
+                        }
+                    }
+                    writeImage = new WriteableBitmap(saveImageData.PixelWidth, saveImageData.PixelHeight, 96, 96, PixelFormats.Bgra32, null);
+                    writeImage.WritePixels(new Int32Rect(0, 0, saveImageData.PixelWidth, saveImageData.PixelHeight), imageData, stride, 0);
+                    saveImageData = writeImage;
+                }
+                PngBitmapEncoder pngEncoder = new PngBitmapEncoder();
+                using (FileStream fs = File.Create(tempPath))
+                {
+                    pngEncoder.Frames.Add(BitmapFrame.Create(saveImageData));
+                    pngEncoder.Save(fs);
+                }
+                imagePath = tempPath;
+                return true;
+            }
+            catch (Exception ex)
+            {
+
+            }
+
+            return false;
+        }
+
+        private bool GetAnnotOpacityImage(CPDFStampAnnotation annot, double opacity, double zoom, out string imagePath)
+        {
+            imagePath = string.Empty;
+            if (annot == null || annot.IsValid() == false)
+            {
+                return false;
+            }
+
+            try
+            {
+                CRect rawRect = annot.GetRect();
+                Rect drawRect = new Rect(0, 0, (int)(rawRect.width() * 96.0 / 72.0 * zoom), (int)(rawRect.height() * 96.0 / 72.0 * zoom));
+
+                byte[] imageData = new byte[(int)drawRect.Width * (int)drawRect.Height * 4];
+                annot.RenderAnnot((int)drawRect.Width, (int)drawRect.Height, imageData);
+                byte annotOpacity = annot.GetTransparency();
+
+                int stride = ((int)drawRect.Width) * 4;
+                for (int i = 0; i < (int)(drawRect.Height); i++)
+                {
+                    for (int j = 0; j < (int)(drawRect.Width); j++)
+                    {
+                        byte b = imageData[i * stride + j * 4];
+                        byte g = imageData[i * stride + j * 4 + 1];
+                        byte r = imageData[i * stride + j * 4 + 2];
+                        byte a = imageData[i * stride + j * 4 + 3];
+
+                        if (a == 0 && b == 255 && g == 255 && r == 255)
+                        {
+                            continue;
+                        }
+                    
+                        if (a == 0 && annotOpacity > 0)
+                        {
+                            imageData[i * stride + j * 4] = 255;
+                            imageData[i * stride + j * 4 + 1] = 255;
+                            imageData[i * stride + j * 4 + 2] = 255;
+                            continue;
+                        }
+                        imageData[i * stride + j * 4 + 3] = (byte)(opacity * 255);
+                    }
+                }
+
+                WriteableBitmap writeImage = new WriteableBitmap((int)drawRect.Width, (int)drawRect.Height, 96, 96, PixelFormats.Bgra32, null);
+                writeImage.WritePixels(new Int32Rect(0, 0, (int)drawRect.Width, (int)drawRect.Height), imageData, stride, 0);
+                string tempPath = System.IO.Path.Combine(System.IO.Path.GetTempPath(), Guid.NewGuid().ToString());
+                PngBitmapEncoder pngEncoder = new PngBitmapEncoder();
+                using (FileStream fs = File.Create(tempPath))
+                {
+                    pngEncoder.Frames.Add(BitmapFrame.Create(writeImage));
+                    pngEncoder.Save(fs);
+                }
+                imagePath = tempPath;
+                return true;
+            }
+            catch (Exception ex)
+            {
+
+            }
+            return false;
+        }
+    }
 }

+ 13 - 2
Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/StickyNoteAnnotHistory.cs

@@ -68,9 +68,15 @@ namespace ComPDFKit.Tool.UndoManger
                 {
                     stickynoteAnnot.SetContent(currentParam.Content);
                 }
+
+                if (string.IsNullOrEmpty(currentParam.IconName) == false)
+                {
+                    stickynoteAnnot.SetIconName(currentParam.IconName);
+                }
+
                 stickynoteAnnot.SetIsLocked(currentParam.Locked);
                 stickynoteAnnot.SetCreationDate(PDFHelp.GetCurrentPdfTime());
-                stickynoteAnnot.UpdateAp();
+                CommonHelper.UpdateStickyAP(stickynoteAnnot);
                 stickynoteAnnot.ReleaseAnnot();
 
                 if (currentParam != null)
@@ -134,13 +140,18 @@ namespace ComPDFKit.Tool.UndoManger
                     stickynoteAnnot.SetContent(updateParam.Content);
                 }
 
+                if(updateParam.IconName!=checkParam.IconName && !string.IsNullOrEmpty(updateParam.IconName))
+                {
+                    stickynoteAnnot.SetIconName(updateParam.IconName);
+                }
+
                 if (updateParam.Locked != checkParam.Locked)
                 {
                     stickynoteAnnot.SetIsLocked(updateParam.Locked);
                 }
 
                 stickynoteAnnot.SetModifyDate(PDFHelp.GetCurrentPdfTime());
-                stickynoteAnnot.UpdateAp();
+                CommonHelper.UpdateStickyAP(stickynoteAnnot);
 
                 return true;
             }

+ 4 - 28
Demo/Examples/ComPDFKit.Tool/UndoManger/FormHistory/ComboBoxHistory.cs

@@ -84,12 +84,9 @@ namespace ComPDFKit.Tool.UndoManger
                 }
                 textAttr.FontColor = fontColor;
 				textAttr.FontSize = (float)currentParam.FontSize;
-				textAttr.FontName = ObtainFontName(
-					GetFontType(currentParam.FontName),
-					currentParam.IsBold,
-					currentParam.IsItalic);
+				textAttr.FontName = currentParam.FontName;
 
-				comboboxWidget.SetTextAttribute(textAttr);
+                comboboxWidget.SetTextAttribute(textAttr);
 
 				if(currentParam.OptionItems!=null && currentParam.OptionItems.Count > 0)
 				{
@@ -198,11 +195,8 @@ namespace ComPDFKit.Tool.UndoManger
 				if (updateParam.FontName != checkParam.FontName)
 				{
 					CTextAttribute textAttr = comboboxWidget.GetTextAttribute();
-					bool isBold = IsBold(textAttr.FontName);
-					bool isItalic = IsItalic(textAttr.FontName);
-					FontType fontType = GetFontType(updateParam.FontName);
-					textAttr.FontName = ObtainFontName(fontType, isBold, isItalic);
-					comboboxWidget.SetTextAttribute(textAttr);
+					textAttr.FontName = updateParam.FontName;
+                    comboboxWidget.SetTextAttribute(textAttr);
 				}
 
 				if (updateParam.FontSize != checkParam.FontSize)
@@ -222,24 +216,6 @@ namespace ComPDFKit.Tool.UndoManger
                     }
 				}
 
-				if (updateParam.IsBold != checkParam.IsBold)
-				{
-					CTextAttribute textAttr = comboboxWidget.GetTextAttribute();
-					bool isItalic = IsItalic(textAttr.FontName);
-					FontType fontType = GetFontType(textAttr.FontName);
-					textAttr.FontName = ObtainFontName(fontType, updateParam.IsBold, isItalic);
-					comboboxWidget.SetTextAttribute(textAttr);
-				}
-
-				if (updateParam.IsItalic != checkParam.IsItalic)
-				{
-					CTextAttribute textAttr = comboboxWidget.GetTextAttribute();
-					bool isBold = IsBold(textAttr.FontName);
-					FontType fontType = GetFontType(textAttr.FontName);
-					textAttr.FontName = ObtainFontName(fontType, isBold, updateParam.IsItalic);
-					comboboxWidget.SetTextAttribute(textAttr);
-				}
-
 				if (updateParam.OptionItems != null)
 				{
 					int optionsCount = comboboxWidget.GetItemsCount();

+ 4 - 29
Demo/Examples/ComPDFKit.Tool/UndoManger/FormHistory/ListBoxHistory.cs

@@ -84,12 +84,9 @@ namespace ComPDFKit.Tool.UndoManger
                 }
                 textAttr.FontColor = fontColor;
 				textAttr.FontSize = (float)currentParam.FontSize;
-				textAttr.FontName = ObtainFontName(
-					GetFontType(currentParam.FontName),
-					currentParam.IsBold,
-					currentParam.IsItalic);
+				textAttr.FontName = currentParam.FontName;
 
-				listboxWidget.SetTextAttribute(textAttr);
+                listboxWidget.SetTextAttribute(textAttr);
 
 				if (currentParam.OptionItems != null && currentParam.OptionItems.Count > 0)
 				{
@@ -198,11 +195,8 @@ namespace ComPDFKit.Tool.UndoManger
 				if (updateParam.FontName != checkParam.FontName)
 				{
 					CTextAttribute textAttr = listboxWidget.GetTextAttribute();
-					bool isBold = IsBold(textAttr.FontName);
-					bool isItalic = IsItalic(textAttr.FontName);
-					FontType fontType = GetFontType(updateParam.FontName);
-					textAttr.FontName = ObtainFontName(fontType, isBold, isItalic);
-					listboxWidget.SetTextAttribute(textAttr);
+					textAttr.FontName = updateParam.FontName;
+                    listboxWidget.SetTextAttribute(textAttr);
 				}
 
 				if (updateParam.FontSize != checkParam.FontSize)
@@ -222,25 +216,6 @@ namespace ComPDFKit.Tool.UndoManger
                     }
                 }
 
-
-                if (updateParam.IsBold != checkParam.IsBold)
-				{
-					CTextAttribute textAttr = listboxWidget.GetTextAttribute();
-					bool isItalic = IsItalic(textAttr.FontName);
-					FontType fontType = GetFontType(textAttr.FontName);
-					textAttr.FontName = ObtainFontName(fontType, updateParam.IsBold, isItalic);
-					listboxWidget.SetTextAttribute(textAttr);
-				}
-
-				if (updateParam.IsItalic != checkParam.IsItalic)
-				{
-					CTextAttribute textAttr = listboxWidget.GetTextAttribute();
-					bool isBold = IsBold(textAttr.FontName);
-					FontType fontType = GetFontType(textAttr.FontName);
-					textAttr.FontName = ObtainFontName(fontType, isBold, updateParam.IsItalic);
-					listboxWidget.SetTextAttribute(textAttr);
-				}
-
 				if (updateParam.OptionItems != null)
 				{
 					int optionsCount = listboxWidget.GetItemsCount();

+ 4 - 28
Demo/Examples/ComPDFKit.Tool/UndoManger/FormHistory/PushButtonHistory.cs

@@ -92,12 +92,9 @@ namespace ComPDFKit.Tool.UndoManger
                 }
 				textAttr.FontColor = fontColor;
 				textAttr.FontSize = (float)currentParam.FontSize;
-				textAttr.FontName = ObtainFontName(
-					GetFontType(currentParam.FontName),
-					currentParam.IsBold,
-					currentParam.IsItalic);
+				textAttr.FontName = currentParam.FontName;
 
-				pushbuttonWidget.SetTextAttribute(textAttr);
+                pushbuttonWidget.SetTextAttribute(textAttr);
 
 				switch (currentParam.Action)
 				{
@@ -215,11 +212,8 @@ namespace ComPDFKit.Tool.UndoManger
 				if (updateParam.FontName != checkParam.FontName)
 				{
 					CTextAttribute textAttr = pushbutton.GetTextAttribute();
-					bool isBold = IsBold(textAttr.FontName);
-					bool isItalic = IsItalic(textAttr.FontName);
-					FontType fontType = GetFontType(updateParam.FontName);
-					textAttr.FontName = ObtainFontName(fontType, isBold, isItalic);
-					pushbutton.SetTextAttribute(textAttr);
+					textAttr.FontName = updateParam.FontName;
+                    pushbutton.SetTextAttribute(textAttr);
 				}
 
 				if (updateParam.FontSize != checkParam.FontSize)
@@ -239,24 +233,6 @@ namespace ComPDFKit.Tool.UndoManger
                     }
                 }
 
-                if (updateParam.IsBold != checkParam.IsBold)
-				{
-					CTextAttribute textAttr = pushbutton.GetTextAttribute();
-					bool isItalic = IsItalic(textAttr.FontName);
-					FontType fontType = GetFontType(textAttr.FontName);
-					textAttr.FontName = ObtainFontName(fontType, updateParam.IsBold, isItalic);
-					pushbutton.SetTextAttribute(textAttr);
-				}
-
-				if (updateParam.IsItalic != checkParam.IsItalic)
-				{
-					CTextAttribute textAttr = pushbutton.GetTextAttribute();
-					bool isBold = IsBold(textAttr.FontName);
-					FontType fontType = GetFontType(textAttr.FontName);
-					textAttr.FontName = ObtainFontName(fontType, isBold, updateParam.IsItalic);
-					pushbutton.SetTextAttribute(textAttr);
-				}
-
 				switch (updateParam.Action)
 				{
 					case C_ACTION_TYPE.ACTION_TYPE_GOTO:

+ 4 - 28
Demo/Examples/ComPDFKit.Tool/UndoManger/FormHistory/TextBoxHistory.cs

@@ -86,12 +86,9 @@ namespace ComPDFKit.Tool.UndoManger
                 }
 				textAttr.FontColor = fontColor;
 				textAttr.FontSize = (float)currentParam.FontSize;
-				textAttr.FontName = ObtainFontName(
-					GetFontType(currentParam.FontName),
-					currentParam.IsBold,
-					currentParam.IsItalic);
+				textAttr.FontName = currentParam.FontName;
 
-				textWidget.SetTextAttribute(textAttr);
+                textWidget.SetTextAttribute(textAttr);
                 textWidget.SetJustification(currentParam.Alignment);
 
 				textWidget.SetBorderWidth((float)currentParam.LineWidth);
@@ -185,11 +182,8 @@ namespace ComPDFKit.Tool.UndoManger
 				if (updateParam.FontName != checkParam.FontName)
 				{
 					CTextAttribute textAttr = textWidget.GetTextAttribute();
-					bool isBold = IsBold(textAttr.FontName);
-					bool isItalic = IsItalic(textAttr.FontName);
-					FontType fontType = GetFontType(updateParam.FontName);
-					textAttr.FontName = ObtainFontName(fontType, isBold, isItalic);
-					textWidget.SetTextAttribute(textAttr);
+					textAttr.FontName = updateParam.FontName;
+                    textWidget.SetTextAttribute(textAttr);
 				}
 
 				if (updateParam.FontSize != checkParam.FontSize)
@@ -209,24 +203,6 @@ namespace ComPDFKit.Tool.UndoManger
                     }
 				}
 
-				if (updateParam.IsBold != checkParam.IsBold)
-				{
-					CTextAttribute textAttr = textWidget.GetTextAttribute();
-					bool isItalic = IsItalic(textAttr.FontName);
-					FontType fontType = GetFontType(textAttr.FontName);
-					textAttr.FontName = ObtainFontName(fontType, updateParam.IsBold, isItalic);
-					textWidget.SetTextAttribute(textAttr);
-				}
-
-				if (updateParam.IsItalic != checkParam.IsItalic)
-				{
-					CTextAttribute textAttr = textWidget.GetTextAttribute();
-					bool isBold = IsBold(textAttr.FontName);
-					FontType fontType = GetFontType(textAttr.FontName);
-					textAttr.FontName = ObtainFontName(fontType, isBold, updateParam.IsItalic);
-					textWidget.SetTextAttribute(textAttr);
-				}
-
 				if (updateParam.Alignment != checkParam.Alignment)
 				{
                     textWidget.SetJustification(updateParam.Alignment);

+ 8 - 7
Demo/Examples/ComPDFKit.Tool/UndoManger/GroupHistory.cs

@@ -15,7 +15,6 @@ namespace ComPDFKit.Tool.UndoManger
             if (Histories != null && Histories.Count > 0)
             {
                 bool success = true;
-                //需要排序
 
                 List<AnnotHistory> checkAnnotList = new List<AnnotHistory>();
                 List<IHistory> OtherList = new List<IHistory>();
@@ -31,7 +30,6 @@ namespace ComPDFKit.Tool.UndoManger
                     OtherList.Add(history);
                 }
 
-                //而且 checkAnnotList 要从大到小排序
                 List<AnnotHistory> loopList = new List<AnnotHistory>();
                 if (checkAnnotList != null && checkAnnotList.Count > 0)
                 {
@@ -66,7 +64,6 @@ namespace ComPDFKit.Tool.UndoManger
             if (Histories != null && Histories.Count > 0)
             {
                 bool success = true;
-                //需要排序
 
                 List<AnnotHistory> checkAnnotList = new List<AnnotHistory>();
                 List<IHistory> OtherList = new List<IHistory>();
@@ -82,7 +79,6 @@ namespace ComPDFKit.Tool.UndoManger
                     OtherList.Add(history);
                 }
 
-                //而且 checkAnnotList 要从大到小排序
                 List<AnnotHistory> loopList = new List<AnnotHistory>();
                 if (checkAnnotList != null && checkAnnotList.Count > 0)
                 {
@@ -103,6 +99,11 @@ namespace ComPDFKit.Tool.UndoManger
                     success &= history.Undo();
                 }
 
+                foreach (IHistory history in OtherList)
+                {
+                    success &= history.Undo();
+                }
+
                 foreach (IHistory history in OtherList)
                 {
                     success &= history.Undo();
@@ -131,7 +132,7 @@ namespace ComPDFKit.Tool.UndoManger
             if (checkItem is GroupHistory)
             {
                 GroupHistory groupHistory = (GroupHistory)checkItem;
-                foreach (IHistory checkHistory in groupHistory.Histories)
+                foreach(IHistory checkHistory in groupHistory.Histories)
                 {
                     AnnotHistory checkAnnot = checkHistory as AnnotHistory;
                     if (checkAnnot == null || checkAnnotList.Contains(checkAnnot))
@@ -146,7 +147,7 @@ namespace ComPDFKit.Tool.UndoManger
             {
                 checkAnnotList.Add((AnnotHistory)checkItem);
             }
-            //而且 checkAnnotList 要从大到小排序
+
             List<AnnotHistory> loopList = new List<AnnotHistory>();
             if (checkAnnotList != null && checkAnnotList.Count > 0)
             {
@@ -227,7 +228,7 @@ namespace ComPDFKit.Tool.UndoManger
                 if (annotHistory.GetPageIndex() == pageIndex && annotHistory.HistoryIndex == prevIndex)
                 {
                     annotHistory.SetAnnotIndex(annotIndex);
-                    annotHistory.HistoryIndex =annotIndex;
+                    annotHistory.HistoryIndex = annotIndex;
                 }
             }
         }

+ 1 - 1
Demo/Examples/ComPDFKit.Tool/UndoManger/MultiAnnotHistory.cs

@@ -69,7 +69,7 @@ namespace ComPDFKit.Tool.UndoManger
             {
                 checkAnnotList.Add((AnnotHistory)checkItem);
             }
-            //而且 checkAnnotList 要从大到小排序
+
             List<AnnotHistory> loopList = new List<AnnotHistory>();
             if (checkAnnotList != null && checkAnnotList.Count > 0)
             {

+ 28 - 21
Demo/Examples/ComPDFKit.Tool/UndoManger/PDFEditHistory/PDFEditHistory.cs

@@ -3,36 +3,43 @@ using ComPDFKitViewer.Helper;
 
 namespace ComPDFKit.Tool.UndoManger
 {
-	public class PDFEditHistory : IHistory
-	{
-		public CPDFEditPage EditPage { get; set; }
-		public int PageIndex {  get; set; }
-		public bool Redo()
-		{
+    public class PDFEditHistory : IHistory
+    {
+        public CPDFEditPage EditPage { get; set; }
+        public int PageIndex { get; set; }
+        public bool Redo()
+        {
             if (EditPage != null && EditPage.IsValid())
             {
                 bool result = EditPage.Redo();
-                EditPage.EndEdit();
+                if (result)
+                {
+                    EditPage.EndEdit();
+                }
                 return result;
+
             }
 
             return false;
-		}
+        }
 
-		public bool Undo()
-		{
-			if(EditPage!=null && EditPage.IsValid())
-			{
-				bool result= EditPage.Undo();
-				EditPage.EndEdit();
-				return result;
-			}
-			return false;
-		}
+        public bool Undo()
+        {
+            if (EditPage != null && EditPage.IsValid())
+            {
+                bool result = EditPage.Undo();
+                if (result)
+                {
+                    EditPage.EndEdit();
+                }
+                return result;
+            }
+            return false;
+        }
 
-		public void Check(IHistory changeItem, bool undo, bool redo, bool add)
+        public void Check(IHistory changeItem, bool undo, bool redo, bool add)
         {
 
-		}
-	}
+        }
+    }
 }

+ 1 - 1
Demo/Examples/Compdfkit.Controls/Annotation/CPDFAnnotationPreviewerControl.xaml.cs

@@ -175,7 +175,7 @@ namespace ComPDFKit.Controls.PDFControl
             string fontFamily = string.Empty;
             string fontStyle = string.Empty;
 
-            CPDFFont.GetFamlyStyleName(freeTextData.FontFamily, ref fontFamily, ref fontStyle);
+            CPDFFont.GetFamilyStyleName(freeTextData.FontFamily, ref fontFamily, ref fontStyle);
             FreeText.FontFamily = new FontFamily(fontFamily); 
             FreeText.FontSize = freeTextData.FontSize / 1.2;
             FreeText.Foreground = new SolidColorBrush(freeTextData.BorderColor);

+ 6 - 1
Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationData/CPDFAnnotationData.cs

@@ -25,7 +25,12 @@ namespace ComPDFKit.Controls.Data
         Signature,
         Link,
         Audio,
-        Image
+        Image,
+        PolyLine,
+        Polygon,
+        LineMeasure,
+        PolyLineMeasure,
+        PolygonMeasure
     }
 
     public enum SignatureType

Diff do ficheiro suprimidas por serem muito extensas
+ 65 - 1
Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListControl/CPDFAnnotationListControl.xaml


+ 203 - 18
Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListControl/CPDFAnnotationListControl.xaml.cs

@@ -6,19 +6,19 @@ using ComPDFKit.Tool.Help;
 using ComPDFKitViewer;
 using ComPDFKitViewer.BaseObject;
 using System.Collections.Generic;
-using System.Linq;
 using System.IO;
 using System.Windows;
-using System.Windows.Annotations;
 using System.Windows.Controls;
-using ComPDFKit.Controls.Helper;
-using static ComPDFKit.Controls.PDFControlUI.CPDFAnnoationListUI;
+using static ComPDFKit.Controls.PDFControlUI.CPDFAnnotationListUI;
+using ComPDFKit.Controls.PDFControlUI;
+using System.Windows.Input;
+using System;
 
 namespace ComPDFKit.Controls.PDFControl
 {
     public partial class CPDFAnnotationListControl : UserControl
     {
-        private List<C_ANNOTATION_TYPE> OmitList = new List<C_ANNOTATION_TYPE> 
+        private List<C_ANNOTATION_TYPE> OmitList = new List<C_ANNOTATION_TYPE>
         {
             C_ANNOTATION_TYPE.C_ANNOTATION_UNKOWN,
             C_ANNOTATION_TYPE.C_ANNOTATION_LINK,
@@ -43,6 +43,52 @@ namespace ComPDFKit.Controls.PDFControl
         {
             AnnotationList.DeleteItemHandler -= AnnotationList_DeleteItemHandler;
             AnnotationList.DeleteItemHandler += AnnotationList_DeleteItemHandler;
+            AnnotationList.ReplyStatusChanged -= AnnotationList_ReplyStatusChanged;
+            AnnotationList.ReplyStatusChanged += AnnotationList_ReplyStatusChanged;
+            AnnotationReplyListControl.ReplyListChanged -= AnnotationReplyListControl_ReplyListChanged;
+            AnnotationReplyListControl.ReplyListChanged += AnnotationReplyListControl_ReplyListChanged;
+        }
+
+        private void AnnotationList_ReplyStatusChanged(object sender, CPDFAnnotationState e)
+        {
+            if (sender is ReplyStatusControl replyStatusControl)
+            {
+                if (replyStatusControl.DataContext is AnnotationBindData data)
+                {
+                    if (pdfViewer != null)
+                    {
+                        CPDFAnnotation annot = data.BindProperty.Annotation;
+                        if (annot != null)
+                        {
+                            annot.SetState(e);
+                            pdfViewer.PDFViewTool.GetCPDFViewer().UpdateAnnotFrame();
+                            pdfViewer.PDFViewTool.IsDocumentModified = true;
+                        }
+                    }
+                }
+            }
+            else if (sender is CheckBox checkBox)
+            {
+                if (checkBox.DataContext is AnnotationBindData data)
+                {
+                    if (pdfViewer != null)
+                    {
+                        CPDFAnnotation annot = data.BindProperty.Annotation;
+                        if (annot != null)
+                        {
+                            annot.SetMarkedAnnotState(checkBox.IsChecked == true ? CPDFAnnotationState.C_ANNOTATION_MARKED : CPDFAnnotationState.C_ANNOTATION_UNMARKED, "");
+                            pdfViewer.PDFViewTool.GetCPDFViewer().UpdateAnnotFrame();
+                            pdfViewer.PDFViewTool.IsDocumentModified = true;
+                        }
+                    }
+                }
+            }
+        }
+
+        private void AnnotationReplyListControl_ReplyListChanged(object sender, System.EventArgs e)
+        {
+            pdfViewer.PDFViewTool.IsDocumentModified = true;
+            pdfViewer.PDFViewTool.GetCPDFViewer().UpdateAnnotFrame();
         }
 
         private void AnnotationList_DeleteItemHandler(object sender, Dictionary<int, List<int>> e)
@@ -71,9 +117,9 @@ namespace ComPDFKit.Controls.PDFControl
             }
             else
             {
-                BaseAnnot baseAnnot= pdfViewer.PDFToolManager.GetCacheHitTestAnnot();
+                BaseAnnot baseAnnot = pdfViewer.PDFToolManager.GetCacheHitTestAnnot();
                 AnnotData annotData = baseAnnot?.GetAnnotData();
-                if(annotData != null)
+                if (annotData != null)
                 {
                     AnnotationList.SelectAnnotationChanged(annotData.PageIndex, annotData.AnnotIndex);
                 }
@@ -95,21 +141,49 @@ namespace ComPDFKit.Controls.PDFControl
 
             List<BindAnnotationResult> bindAnnotationResults = new List<BindAnnotationResult>();
 
+            pdfViewer.UpdateAnnotFrame();
             for (int i = 0; i < pageCount; i++)
             {
-
                 List<AnnotParam> annotList = GetAnnotCommentList(i, pdfViewer.PDFViewTool.GetCPDFViewer().GetDocument());
-                if (annotList != null&& annotList.Count>0)
+                List<CPDFAnnotation> annotCoreList = pdfViewer?.GetCPDFViewer()?.GetDocument()?.PageAtIndex(i, false)?.GetAnnotations();
+                if (annotList != null && annotList.Count > 0)
                 {
                     Dispatcher.Invoke(() =>
                     {
                         foreach (AnnotParam annot in annotList)
                         {
-                            bindAnnotationResults.Add(new BindAnnotationResult
+                            CPDFAnnotation annotCore = annotCoreList[annot.AnnotIndex];
+                            if (annotCore == null || annotCore.IsReplyAnnot() || annotCore.Type == C_ANNOTATION_TYPE.C_ANNOTATION_LINK)
+                            {
+                                continue;
+                            }
+
+                            var bindResult = new BindAnnotationResult
                             {
                                 PageIndex = i,
-                                annotationData = annot
-                            });
+                                annotationData = annot,
+                                pdfViewer = pdfViewer,
+                                ReplyState = annotCore.GetState(),
+                                IsMarkState = annotCore.IsMarkedStateAnnot()
+                            };
+
+                            List<CPDFTextAnnotation> replyAnnotations = annotCore?.GetReplies();
+                            if (replyAnnotations != null && replyAnnotations.Count > 0)
+                            {
+                                foreach (CPDFTextAnnotation replyAnnot in replyAnnotations)
+                                {
+                                    if (replyAnnot == null)
+                                    {
+                                        continue;
+                                    }
+
+                                    bindResult.ReplyList.Add(new ReplyData
+                                    {
+                                        ReplyAnnotation = replyAnnot,
+                                    });
+                                }
+                            }
+                            bindAnnotationResults.Add(bindResult);
                         }
                     });
                 }
@@ -135,12 +209,12 @@ namespace ComPDFKit.Controls.PDFControl
             {
                 foreach (CPDFAnnotation annotation in docAnnots)
                 {
-                    if (annotation==null|| OmitList.Contains(annotation.Type))
+                    if (annotation == null || OmitList.Contains(annotation.Type))
                     {
                         continue;
                     }
-                    AnnotParam annotParam= ParamConverter.CPDFDataConverterToAnnotParam(currentDoc,pageIndex,annotation);
-                    if (annotParam!=null)
+                    AnnotParam annotParam = ParamConverter.CPDFDataConverterToAnnotParam(currentDoc, pageIndex, annotation);
+                    if (annotParam != null)
                     {
                         annotList.Add(annotParam);
                     }
@@ -177,8 +251,8 @@ namespace ComPDFKit.Controls.PDFControl
             {
                 Directory.CreateDirectory(tempPath);
             }
-            pdfViewer.PDFToolManager.GetDocument().ImportAnnotationFromXFDFPath(selectedPath,tempPath);
-                
+            pdfViewer.PDFToolManager.GetDocument().ImportAnnotationFromXFDFPath(selectedPath, tempPath);
+
             LoadAnnotationList();
             pdfViewer.PDFViewTool.GetCPDFViewer().UpdateVirtualNodes();
             pdfViewer.PDFViewTool.GetCPDFViewer().UpdateRenderFrame();
@@ -194,11 +268,122 @@ namespace ComPDFKit.Controls.PDFControl
             {
                 Directory.CreateDirectory(tempPath);
             }
-
             if (pdfViewer.PDFToolManager.GetDocument().ExportAnnotationToXFDFPath(selectedPath, tempPath))
             {
                 System.Diagnostics.Process.Start("explorer.exe", "/select," + selectedPath);
             }
         }
     }
+
+    public class ExpandAllReplyCommand : ICommand
+    {
+        public event EventHandler CanExecuteChanged;
+
+        public bool CanExecute(object parameter)
+        {
+            return true;
+        }
+
+        public void Execute(object parameter)
+        {
+            if (parameter is CPDFAnnotationListControl annotationListControl)
+            {
+                annotationListControl.AnnotationList.ExpandAllReply(true);
+            }
+        }
+    }
+
+    public class FoldAllReplyCommand : ICommand
+    {
+        public event EventHandler CanExecuteChanged;
+
+        public bool CanExecute(object parameter)
+        {
+            return true;
+        }
+
+        public void Execute(object parameter)
+        {
+            if (parameter is CPDFAnnotationListControl annotationListControl)
+            {
+                annotationListControl.AnnotationList.ExpandAllReply(false);
+            }
+        }
+    }
+
+    public class DeleteAllAnnotCommand : ICommand
+    {
+        public event EventHandler CanExecuteChanged;
+
+        public bool CanExecute(object parameter)
+        {
+            return true;
+        }
+
+        public void Execute(object parameter)
+        {
+            if (parameter is CPDFAnnotationListControl annotationListControl)
+            {
+                annotationListControl.AnnotationList.DeleteAllReply();
+                annotationListControl.LoadAnnotationList();
+                annotationListControl.AnnotationList.DeleteAllAnnot();
+            }
+        }
+    }
+
+    public class DeleteAllReplyCommand : ICommand
+    {
+        public event EventHandler CanExecuteChanged;
+
+        public bool CanExecute(object parameter)
+        {
+            return true;
+        }
+
+        public void Execute(object parameter)
+        {
+            if (parameter is CPDFAnnotationListControl annotationListControl)
+            {
+                annotationListControl.AnnotationList.DeleteAllReply();
+                annotationListControl.LoadAnnotationList();
+            }
+        }
+    }
+
+    public class ExpandAnnotListCommand : ICommand
+    {
+        public event EventHandler CanExecuteChanged;
+
+        public bool CanExecute(object parameter)
+        {
+            return true;
+        }
+
+        public void Execute(object parameter)
+        {
+            if (parameter is CPDFAnnotationListControl annotationListControl)
+            {
+                annotationListControl.AnnotationList.ExpandAnnotList(true);
+            }
+        }
+    }
+
+    public class FoldAnnotListCommand : ICommand
+    {
+        public event EventHandler CanExecuteChanged;
+
+        public bool CanExecute(object parameter)
+        {
+            return true;
+        }
+
+        public void Execute(object parameter)
+        {
+            if (parameter is CPDFAnnotationListControl annotationListControl)
+            {
+                annotationListControl.AnnotationList.ExpandAnnotList(false);
+            }
+        }
+    }
+
 }

+ 134 - 0
Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListUI/AnnotationReplyListControl.xaml

@@ -0,0 +1,134 @@
+<UserControl x:Class="ComPDFKit.Controls.PDFControlUI.AnnotationReplyListControl"
+             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:common="clr-namespace:ComPDFKit.Controls.Common"
+             xmlns:local="clr-namespace:ComPDFKit.Controls.PDFControlUI"
+             mc:Ignorable="d" 
+             Loaded= "UserControl_Loaded"
+             d:DesignHeight="450" d:DesignWidth="800">
+    <UserControl.Resources>
+        <ResourceDictionary>
+            <ResourceDictionary.MergedDictionaries>
+                <ResourceDictionary Source="../../../Asset/Styles/MenuItemStyle.xaml"></ResourceDictionary>
+            </ResourceDictionary.MergedDictionaries>
+            <common:TextLengthToVisibilityConverter x:Key="TextLengthToVisibilityConverter"></common:TextLengthToVisibilityConverter>
+            <common:SubtractionConverter x:Key="SubtractionConverter"></common:SubtractionConverter>
+            <common:AntiVisibilityConverter x:Key="AntiVisibilityConverter"></common:AntiVisibilityConverter>
+            <common:BoolToVisibleConverter x:Key="BoolToVisibleConverter"></common:BoolToVisibleConverter>
+            <common:BotaResourceConverter x:Key="BotaResourceConverter"></common:BotaResourceConverter>
+        </ResourceDictionary>
+    </UserControl.Resources>
+    <Grid x:Name="ReplyGrid" Margin="0">
+        <Grid.RowDefinitions>
+            <RowDefinition Height="0"></RowDefinition>
+            <RowDefinition Height="0"></RowDefinition>
+            <RowDefinition Height="0"></RowDefinition>
+        </Grid.RowDefinitions>
+
+        <Grid Grid.Row="0">
+            <TextBox x:Name="InputTxb" Height="30" VerticalContentAlignment="Center"></TextBox>
+            <TextBlock Text="{Binding Converter={StaticResource BotaResourceConverter},ConverterParameter=Holder_Reply}" VerticalAlignment="Center" Margin="10,0,0,0" Foreground="#A0A0A0" IsHitTestVisible="False"
+                      Visibility="{Binding ElementName=InputTxb, Path=Text, Converter={StaticResource TextLengthToVisibilityConverter}}"></TextBlock>
+        </Grid>
+
+        <StackPanel Grid.Row="1" Orientation="Horizontal" HorizontalAlignment="Right">
+            <Button Content="{Binding Converter={StaticResource BotaResourceConverter},ConverterParameter=Button_Cancel}" Background="Transparent" BorderThickness="0" Margin="0,0,5,0" Width="56" Height="30" Click="ButtonCancel_Click"></Button>
+            <Button Content="{Binding Converter={StaticResource BotaResourceConverter},ConverterParameter=Button_Reply}" Width="56" Height="30" Foreground="White" Background="#1460F3" BorderThickness="0" Click="ReplyButton_Click"></Button>
+        </StackPanel>
+
+        <ListView Grid.Row="2" x:Name="ReplyList" Margin="0,0,0,0" VirtualizingPanel.IsVirtualizingWhenGrouping="True" 
+                 ScrollViewer.HorizontalScrollBarVisibility="Hidden" BorderThickness="0" SelectionMode="Single" 
+                   Visibility="{Binding ElementName=ReplyList, Path=HasItems, Converter={StaticResource BoolToVisibleConverter}}">
+            <ListView.ItemsPanel>
+                <ItemsPanelTemplate>
+                    <VirtualizingStackPanel Background="#FAFCFF" HorizontalAlignment="Stretch" MaxHeight="200"
+                                           Width="{Binding ActualWidth, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListView}, Converter={StaticResource SubtractionConverter}, ConverterParameter=5}"></VirtualizingStackPanel>
+                </ItemsPanelTemplate>
+            </ListView.ItemsPanel>
+            <ListView.ItemContainerStyle>
+                <Style TargetType="ListViewItem">
+                    <Setter Property="Template">
+                        <Setter.Value>
+                            <ControlTemplate TargetType="ListViewItem">
+                                <ContentPresenter />
+                            </ControlTemplate>
+                        </Setter.Value>
+                    </Setter>
+                    <Setter Property="MinHeight" Value="0" />
+                    <Setter Property="Height" Value="Auto" /> 
+                </Style>
+            </ListView.ItemContainerStyle>
+            <ListView.ItemTemplate>
+                <ItemContainerTemplate> 
+                    <Grid>
+                        <Grid.Style>
+                            <Style TargetType="Grid"> 
+                                <Style.Triggers>
+                                    <Trigger Property="IsMouseOver" Value="True">
+                                        <Setter Property="Background" Value="#D0D9E1"/> 
+                                    </Trigger>
+                                    <DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType=ListViewItem}}" Value="True">
+                                        <Setter Property="Background" Value="#D0D9E1"/> 
+                                    </DataTrigger>
+                                </Style.Triggers>
+                            </Style>
+                        </Grid.Style>
+                        <Grid.RowDefinitions>
+                            <RowDefinition Height="Auto"/>
+                            <RowDefinition Height="Auto"/>
+                        </Grid.RowDefinitions>
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="*"/>
+                            <ColumnDefinition Width="Auto"/>
+                        </Grid.ColumnDefinitions>
+
+                        <DockPanel Grid.Column="0">
+                            <StackPanel VerticalAlignment="Center">
+                                <TextBlock Text="{Binding Author}" FontSize="14" Foreground="#43474D" VerticalAlignment="Center"/>
+                                <TextBlock Text="{Binding Date}" FontSize="11" Foreground="#999999" VerticalAlignment="Center"/>
+                            </StackPanel>
+                        </DockPanel>
+
+                        <Menu Background="Transparent" BorderThickness="0" Grid.Column="1">
+                            <MenuItem  BorderThickness="0" Width="30" Height="30" Padding="4,3,0,0">
+                                <MenuItem.Header>
+                                    <Canvas Width="30" Height="30"  VerticalAlignment="Stretch" HorizontalAlignment="Stretch">
+                                        <Path Data="M10 5.5C10.8284 5.5 11.5 4.82843 11.5 4C11.5 3.17157 10.8284 2.5 10 2.5C9.17157 2.5 8.5 3.17157 8.5 4C8.5 4.82843 9.17157 5.5 10 5.5ZM11.5 10C11.5 10.8284 10.8284 11.5 10 11.5C9.17157 11.5 8.5 10.8284 8.5 10C8.5 9.17157 9.17157 8.5 10 8.5C10.8284 8.5 11.5 9.17157 11.5 10ZM11.5 16C11.5 16.8284 10.8284 17.5 10 17.5C9.17157 17.5 8.5 16.8284 8.5 16C8.5 15.1716 9.17157 14.5 10 14.5C10.8284 14.5 11.5 15.1716 11.5 16Z" 
+                                             Fill="#43474D"/>
+                                    </Canvas>
+                                </MenuItem.Header>
+                                <MenuItem Header="{Binding Converter={StaticResource BotaResourceConverter},ConverterParameter=Menu_Edit}" Style="{StaticResource Sub_MenuItem}">
+                                    <MenuItem.Command>
+                                        <local:ShowContentBoxCommand/>
+                                    </MenuItem.Command>
+                                    <MenuItem.CommandParameter>
+                                        <Binding ElementName="ContentBox"/>
+                                    </MenuItem.CommandParameter>
+                                </MenuItem>
+
+                                <MenuItem Header="{Binding Converter={StaticResource BotaResourceConverter},ConverterParameter=Menu_Delete}" Style="{StaticResource Sub_MenuItem}">
+                                    <MenuItem.Command>
+                                        <local:DeleteReplyCommand/>
+                                    </MenuItem.Command>
+                                    <MenuItem.CommandParameter>
+                                        <Binding Path="."></Binding>
+                                    </MenuItem.CommandParameter>
+                                </MenuItem>
+                            </MenuItem>
+                        </Menu>
+                        <Grid Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2">
+                            <TextBox x:Name="ContentBox" Text="{Binding Content}" FontSize="14" Foreground="#666666" Margin="5,5,0,0"
+                                    Visibility="Collapsed" VerticalAlignment="Center" LostFocus="ContentBox_LostFocus"></TextBox>
+
+                            <TextBlock Text="{Binding Content}" x:Name="ContentTxb" FontSize="14" Foreground="#666666" Margin="5,5,0,0" VerticalAlignment="Center"
+                                      Visibility="{Binding ElementName=ContentBox,Path=Visibility,Converter={StaticResource AntiVisibilityConverter}}"></TextBlock>
+                        </Grid>
+
+                    </Grid>
+                </ItemContainerTemplate>
+            </ListView.ItemTemplate>
+        </ListView>
+    </Grid>
+</UserControl>

+ 215 - 0
Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListUI/AnnotationReplyListControl.xaml.cs

@@ -0,0 +1,215 @@
+using System;
+using System.Collections.ObjectModel;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+
+namespace ComPDFKit.Controls.PDFControlUI
+{
+    /// <summary>
+    /// Interaction logic for AnnotationReplyListControl.xaml
+    /// </summary>
+    public partial class AnnotationReplyListControl : UserControl
+    {
+        public ObservableCollection<CPDFAnnotationListUI.ReplyData> ReplyListSource
+        {
+            get => (ObservableCollection<CPDFAnnotationListUI.ReplyData>)GetValue(ReplyListProperty);
+            set => SetValue(ReplyListProperty, value);
+        }
+
+        /// <summary>
+        /// The source of the reply list.
+        /// </summary>
+        public static readonly DependencyProperty ReplyListProperty = DependencyProperty.Register(
+            nameof(ReplyListSource),
+            typeof(ObservableCollection<CPDFAnnotationListUI.ReplyData>),
+            typeof(AnnotationReplyListControl),
+            new PropertyMetadata(null, OnReplyListSourceChanged));
+
+        private static void OnReplyListSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+        {
+            var newReplyListSource = e.NewValue as ObservableCollection<CPDFAnnotationListUI.ReplyData>;
+            if (d is AnnotationReplyListControl control)
+            {
+                control.ReplyList.ItemsSource = newReplyListSource;
+            }
+        }
+
+        public bool IsShowInput
+        {
+            get => (bool)GetValue(IsShowInputProperty);
+            set => SetValue(IsShowInputProperty, value);
+        }
+
+        /// <summary>
+        /// The visibility of the reply input.
+        /// </summary>
+        public static readonly DependencyProperty IsShowInputProperty = DependencyProperty.Register(
+            nameof(IsShowInput),
+            typeof(bool),
+            typeof(AnnotationReplyListControl),
+            new PropertyMetadata(false, OnIsShowInputChanged));
+
+        public static event EventHandler ReplyListChanged;
+        public static event EventHandler<CPDFAnnotationListUI.ReplyData> ReplyDeleted;
+
+
+        private static void OnIsShowInputChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+        {
+            if (d is AnnotationReplyListControl control)
+            {
+                control.SetReplyInputVisibility((bool)e.NewValue);
+            }
+        }
+
+        public bool IsShowList
+        {
+            get => (bool)GetValue(IsShowListProperty);
+            set => SetValue(IsShowListProperty, value);
+        }
+
+        /// <summary>
+        /// The visibility of the reply list.
+        /// </summary>
+        public static readonly DependencyProperty IsShowListProperty = DependencyProperty.Register(
+            nameof(IsShowList),
+            typeof(bool),
+            typeof(AnnotationReplyListControl),
+            new PropertyMetadata(false, OnIsShowListChanged));
+
+        public void SetReplyInputVisibility(bool isVisible)
+        {
+            if (isVisible)
+            {
+                ReplyGrid.RowDefinitions[0].Height = new GridLength(1, GridUnitType.Auto);
+                ReplyGrid.RowDefinitions[1].Height = new GridLength(1, GridUnitType.Auto);
+            }
+            else
+            {
+                ReplyGrid.RowDefinitions[0].Height = new GridLength(0);
+                ReplyGrid.RowDefinitions[1].Height = new GridLength(0);
+            }
+        }
+
+        private static void OnIsShowListChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+        {
+            if (d is AnnotationReplyListControl control)
+            {
+                control.SetReplyListVisibility((bool)e.NewValue);
+            }
+        }
+
+        public void SetReplyListVisibility(bool isVisible)
+        {
+            ReplyGrid.RowDefinitions[2].Height = isVisible ? new GridLength(1, GridUnitType.Auto) : new GridLength(0);
+        }
+
+        public static void InvokeReplyListChanged()
+        {
+            ReplyListChanged?.Invoke(null, EventArgs.Empty);
+        }
+
+        public static void InvokeReplyDeleted(CPDFAnnotationListUI.ReplyData replyData)
+        {
+            ReplyDeleted?.Invoke(null, replyData);
+        }
+
+        public AnnotationReplyListControl()
+        {
+            InitializeComponent();
+        }
+
+
+        private void ReplyButton_Click(object sender, RoutedEventArgs e)
+        {
+            if (sender is Button button)
+            {
+                if (button.DataContext is AnnotationBindData annotBindData)
+                {
+                    if (!string.IsNullOrEmpty(InputTxb.Text))
+                    {
+                        var replyAnnot = annotBindData.BindProperty.Annotation.CreateReplyAnnotation();
+                        replyAnnot.SetContent(InputTxb.Text);
+                        replyAnnot.SetAuthor(Data.CPDFAnnotationData.Author);
+                        annotBindData.BindProperty.ReplyList.Add(new CPDFAnnotationListUI.ReplyData
+                        {
+                            ReplyAnnotation = replyAnnot
+                        });
+                        InputTxb.Text = string.Empty;
+                        InvokeReplyListChanged();
+                    }
+                }
+            }
+        }
+
+        private void ButtonCancel_Click(object sender, RoutedEventArgs e)
+        {
+            IsShowInput = false;
+        }
+
+        private void ContentBox_LostFocus(object sender, RoutedEventArgs e)
+        {
+            if (sender is TextBox textBox)
+            {
+                textBox.Visibility = Visibility.Collapsed;
+                if (textBox.DataContext is CPDFAnnotationListUI.ReplyData replyData)
+                {
+                    replyData.ReplyAnnotation.SetContent(textBox.Text);
+                    InvokeReplyListChanged();
+                }
+            }
+        }
+
+        private void UserControl_Loaded(object sender, RoutedEventArgs e)
+        {
+            ReplyDeleted -= AnnotationReplyListControl_ReplyDeleted;
+            ReplyDeleted += AnnotationReplyListControl_ReplyDeleted;
+        }
+
+        private void AnnotationReplyListControl_ReplyDeleted(object sender, CPDFAnnotationListUI.ReplyData e)
+        {
+            ReplyListSource.Remove(e);
+        }
+    }
+
+    public class ShowContentBoxCommand : ICommand
+    {
+        public event EventHandler CanExecuteChanged;
+
+        public bool CanExecute(object parameter)
+        {
+            return true;
+        }
+
+        public void Execute(object parameter)
+        {
+            if (parameter is TextBox textBox)
+            {
+                textBox.Visibility = Visibility.Visible;
+                textBox.Focus();
+                textBox.SelectAll();
+            }
+        }
+    }
+
+    public class DeleteReplyCommand : ICommand
+    {
+        public event EventHandler CanExecuteChanged;
+
+        public bool CanExecute(object parameter)
+        {
+            return true;
+        }
+
+        public void Execute(object parameter)
+        {
+            if (parameter is CPDFAnnotationListUI.ReplyData replyData)
+            {
+                replyData.ReplyAnnotation.RemoveAnnot();
+                AnnotationReplyListControl.InvokeReplyDeleted(replyData);
+                AnnotationReplyListControl.InvokeReplyListChanged();
+            }
+        }
+    }
+
+}

+ 0 - 239
Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListUI/CPDFAnnoationListUI.xaml.cs

@@ -1,239 +0,0 @@
-using ComPDFKit.PDFAnnotation;
-using ComPDFKit.Tool;
-using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.ComponentModel;
-using System.Text.RegularExpressions;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Data;
-using System.Windows.Input;
-using ComPDFKit.Controls.Helper;
-
-namespace ComPDFKit.Controls.PDFControlUI
-{
-    public partial class CPDFAnnoationListUI : UserControl
-    {
-        public class BindAnnotationResult : INotifyPropertyChanged
-        {
-            public int PageIndex { get; set; }
-
-            public int AnnotIndex { get => annotationData.AnnotIndex; }
-
-            public string CreateDate
-            {
-                get
-                {
-                    if (Regex.IsMatch(annotationData.CreateTime, "(?<=D\\:)[0-9]+(?=[\\+\\-])"))
-                    {
-                        string dateStr = Regex.Match(annotationData.CreateTime, "(?<=D\\:)[0-9]+(?=[\\+\\-])").Value;
-                        return (dateStr.Substring(0, 4) + "-" + dateStr.Substring(4, 2) + "-" + dateStr.Substring(6, 2) + ", " + dateStr.Substring(8, 2) + ":" +
-                            dateStr.Substring(10, 2));
-                    }
-                    else
-                    {
-                        return String.Empty;
-                    }
-                }
-            }
-
-            public string Note
-            {
-                get => annotationData.Content;
-            }
-
-            public C_ANNOTATION_TYPE CurrentAnnotationType
-            {
-                get => annotationData.CurrentType;
-            }
-
-            public AnnotParam annotationData { get; set; }
-
-            public event PropertyChangedEventHandler PropertyChanged;
-            protected void OnPropertyChanged(string propertyName)
-            {
-                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
-            }
-        }
-
-        internal class AnnotationBindData
-        {
-            public BindAnnotationResult BindProperty { get; set; }
-            public AnnotationBindData()
-            {
-                BindProperty = new BindAnnotationResult();
-            }
-            public int ShowPageIndex { get { return BindProperty.PageIndex + 1; } set { BindProperty.PageIndex = value; } }
-        }
-
-        private ObservableCollection<AnnotationBindData> annotationList = new ObservableCollection<AnnotationBindData>();
-
-        public event EventHandler<object> AnnotationSelectionChanged;
-
-        public event EventHandler<Dictionary<int, List<int>>> DeleteItemHandler;
-
-        private ContextMenu popContextMenu;
-        private bool enableSelectEvent = true;
-
-        public CPDFAnnoationListUI()
-        {
-            InitializeComponent();
-            ICollectionView groupView = CollectionViewSource.GetDefaultView(annotationList);
-            groupView.GroupDescriptions.Add(new PropertyGroupDescription(nameof(AnnotationBindData.ShowPageIndex)));
-            popContextMenu = new ContextMenu();
-            MenuItem deleteMenu = new MenuItem();
-            deleteMenu.Header = LanguageHelper.BotaManager.GetString("Menu_Delete");
-            deleteMenu.Click -= DeleteMenu_Click;
-            deleteMenu.Click += DeleteMenu_Click;
-            popContextMenu.Items.Add(deleteMenu);
-            MenuItem deleteAllMenu = new MenuItem();
-            deleteAllMenu.Header = LanguageHelper.BotaManager.GetString("Menu_DeleteAll");
-            deleteAllMenu.Click -= DeleteAllMenu_Click;
-            deleteAllMenu.Click += DeleteAllMenu_Click;
-            popContextMenu.Items.Add(deleteAllMenu);
-        }
-
-        private void DeleteAllMenu_Click(object sender, RoutedEventArgs e)
-        {
-            try
-            {
-                Dictionary<int, List<int>> delDict = new Dictionary<int, List<int>>();
-
-                foreach (AnnotationBindData bindData in annotationList)
-                {
-                    if (delDict.ContainsKey(bindData.BindProperty.PageIndex) == false)
-                    {
-                        delDict[bindData.BindProperty.PageIndex] = new List<int>();
-                    }
-                    delDict[bindData.BindProperty.PageIndex].Add(bindData.BindProperty.AnnotIndex);
-                }
-
-                if (delDict.Count > 0)
-                {
-                    DeleteItemHandler?.Invoke(this, delDict);
-                }
-            }
-            catch (Exception ex)
-            {
-
-            }
-        }
-
-        private void DeleteMenu_Click(object sender, RoutedEventArgs e)
-        {
-            try
-            {
-                if (AnnotationList != null && AnnotationList.SelectedIndex >= 0)
-                {
-                    AnnotationBindData bindData = annotationList[AnnotationList.SelectedIndex];
-
-                    Dictionary<int, List<int>> delDict = new Dictionary<int, List<int>>();
-                    delDict[bindData.BindProperty.PageIndex] = new List<int>()
-                    {
-                        bindData.BindProperty.AnnotIndex
-                    };
-                    DeleteItemHandler?.Invoke(this, delDict);
-                }
-            }
-            catch (Exception ex)
-            {
-
-            }
-        }
-
-        public void SetAnnotationList(List<BindAnnotationResult> results)
-        {
-            annotationList.Clear();
-            AnnotationList.ContextMenu = null;
-            if (results == null || results.Count == 0)
-            {
-                AnnotationList.ItemsSource = null;
-                NoContentText.Visibility = Visibility.Visible;
-                return;
-            }
-
-            foreach (BindAnnotationResult item in results)
-            {
-                annotationList.Add(new AnnotationBindData()
-                {
-                    BindProperty = item
-                });
-            }
-            AnnotationList.ItemsSource = annotationList;
-            if (annotationList.Count > 0)
-            {
-                AnnotationList.ContextMenu = popContextMenu;
-            }
-            AnnotationList.Visibility = Visibility.Visible;
-            NoContentText.Visibility = Visibility.Collapsed;
-        }
-
-        private void AnnotationListControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
-        {
-            if (enableSelectEvent)
-            {
-                try
-                {
-                    AnnotationSelectionChanged?.Invoke(this, (e.AddedItems[0] as AnnotationBindData).BindProperty);
-                }
-                catch { }
-            }
-        }
-         
-        public void CancelSelected()
-        {
-            AnnotationList.SelectedIndex = -1;
-        }
-
-        public void SelectAnnotationChanged(int annotationIndex = -1)
-        {
-
-            AnnotationList.SelectedIndex = annotationIndex;
-        }
-
-        public void SelectAnnotationChanged(int pageIIndex, int annotIndex)
-        {
-            if (annotationList != null && annotationList.Count > 0)
-            {
-                for (int i = 0; i < annotationList.Count; i++)
-                {
-                    AnnotationBindData data = annotationList[i];
-                    if (data.BindProperty.PageIndex == pageIIndex && data.BindProperty.AnnotIndex == annotIndex)
-                    {
-                        enableSelectEvent = false;
-                        AnnotationList.SelectedIndex = i;
-                        enableSelectEvent = true;
-                        break;
-                    }
-                }
-            }
-        }
-
-        private void AnnotationList_ContextMenuOpening(object sender, ContextMenuEventArgs e)
-        {
-            try
-            {
-                MenuItem checkMenu = popContextMenu.Items[0] as MenuItem;
-                if (checkMenu != null)
-                {
-                    checkMenu.IsEnabled = true;
-                }
-                if (AnnotationList != null && AnnotationList.SelectedIndex == -1)
-                {
-                    checkMenu.IsEnabled = false;
-                }
-
-            }
-            catch (Exception ex)
-            {
-
-            }
-        }
-
-        private void AnnotationList_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
-        {
-            CancelSelected();
-        }
-    }
-}

Diff do ficheiro suprimidas por serem muito extensas
+ 121 - 24
Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListUI/CPDFAnnoationListUI.xaml


+ 690 - 0
Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListUI/CPDFAnnotationListUI.xaml.cs

@@ -0,0 +1,690 @@
+using ComPDFKit.PDFAnnotation;
+using ComPDFKit.Tool;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Text.RegularExpressions;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Input;
+using ComPDFKit.Controls.Helper;
+using System.Collections.Specialized;
+using ComPDFKit.Controls.PDFControl;
+using static ComPDFKit.Controls.PDFControlUI.CPDFAnnotationListUI;
+using ComPDFKit.Controls.Data;
+
+namespace ComPDFKit.Controls.PDFControlUI
+{
+    public class ShowReplyListCommand : ICommand
+    {
+        public event EventHandler CanExecuteChanged;
+
+        public bool CanExecute(object parameter)
+        {
+            return true;
+        }
+
+        public void Execute(object parameter)
+        {
+            if (parameter is AnnotationBindData data)
+            {
+                data.IsReplyListVisible = !data.IsReplyListVisible;
+            }
+        }
+    }
+
+    public class ShowReplyInputCommand : ICommand
+    {
+        public event EventHandler CanExecuteChanged;
+
+        public bool CanExecute(object parameter)
+        {
+            return true;
+        }
+
+        public void Execute(object parameter)
+        {
+            if (parameter is AnnotationBindData data)
+            {
+                data.IsReplyInputVisible = !data.IsReplyInputVisible;
+                if(data.IsReplyInputVisible)
+                {
+                    data.IsReplyListVisible = true;
+                }
+            }
+        }
+    }
+
+    internal class AnnotationBindData : INotifyPropertyChanged
+    {
+        public PDFViewControl pdfViewer { get; set; }
+
+        public AnnotParam annotationData { get; set; }
+
+        public string ReplyCount
+        {
+            get => ReplyList.Count.ToString();
+        }
+
+        private bool _isReplyListVisible = true;
+        public bool IsReplyListVisible
+        {
+            get { return _isReplyListVisible; }
+            set
+            {
+                _isReplyListVisible = value;
+                OnPropertyChanged(nameof(IsReplyListVisible));
+            }
+        }
+
+        private bool _isReplyInputVisible;
+        public bool IsReplyInputVisible
+        {
+            get { return _isReplyInputVisible; }
+            set
+            {
+                _isReplyInputVisible = value;
+                OnPropertyChanged(nameof(IsReplyInputVisible));
+            }
+        }
+
+        public int PageIndex { get; set; }
+
+        public int AnnotIndex { get => annotationData.AnnotIndex; }
+
+        public string Author
+        {
+            get => annotationData.Author;
+        }
+
+        public string Note
+        {
+            get => annotationData.Content;
+        }
+
+
+        private CPDFAnnotation _annotation;
+        public CPDFAnnotation Annotation
+        {
+            get
+            {
+                List<CPDFAnnotation> annotCoreList = pdfViewer?.GetCPDFViewer()?.GetDocument()?.PageAtIndex(annotationData.PageIndex, false)?.GetAnnotations();
+                return annotCoreList[annotationData.AnnotIndex];
+            }
+        }
+
+        private ObservableCollection<ReplyData> _replyList = new ObservableCollection<ReplyData>();
+
+        public ObservableCollection<ReplyData> ReplyList
+        {
+            get => _replyList;
+            set
+            {
+                if (_replyList != value)
+                {
+                    if (_replyList != null)
+                    {
+                        // Unsubscribe from the previous collection
+                        _replyList.CollectionChanged -= ReplyList_CollectionChanged;
+                    }
+
+                    _replyList = value;
+
+                    if (_replyList != null)
+                    {
+                        // Subscribe to the new collection
+                        _replyList.CollectionChanged += ReplyList_CollectionChanged;
+                    }
+
+                    OnPropertyChanged(nameof(ReplyList));
+                }
+            }
+        }
+
+        private ObservableCollection<AnnotationBindData> annotationList = new ObservableCollection<AnnotationBindData>();
+
+        private void ReplyList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+        {
+            // Notify that the ReplyCount has changed when the collection changes
+            OnPropertyChanged(nameof(ReplyCount));
+        }
+
+        public BindAnnotationResult BindProperty { get; set; }
+        public AnnotationBindData()
+        {
+            BindProperty = new BindAnnotationResult();
+        }
+        public int ShowPageIndex { get { return BindProperty.PageIndex + 1; } set { BindProperty.PageIndex = value; } }
+
+        public event PropertyChangedEventHandler PropertyChanged;
+        protected void OnPropertyChanged(string propertyName)
+        {
+            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+        }
+    }
+
+    public partial class CPDFAnnotationListUI : UserControl
+    {
+        public event EventHandler<CPDFAnnotationState> ReplyStatusChanged;
+
+        public class ReplyData
+        {
+            public CPDFAnnotation ReplyAnnotation { get; set; }
+
+            public string Author
+            {
+                get => ReplyAnnotation.GetAuthor();
+                set => ReplyAnnotation.SetAuthor(value);
+            }
+
+            public string Date
+            {
+                get
+                {
+                    try
+                    {
+                        if (Regex.IsMatch(ReplyAnnotation.GetCreationDate(), "(?<=D\\:)[0-9]+(?=[\\+\\-])"))
+                        {
+                            string dateStr = Regex.Match(ReplyAnnotation.GetCreationDate(), "(?<=D\\:)[0-9]+(?=[\\+\\-])").Value;
+                            return (dateStr.Substring(0, 4) + "-" + dateStr.Substring(4, 2) + "-" + dateStr.Substring(6, 2) + ", " + dateStr.Substring(8, 2) + ":" +
+                                    dateStr.Substring(10, 2));
+                        }
+                        else
+                        {
+                            return string.Empty;
+                        }
+                    }
+                    catch (Exception)
+                    {
+                        return string.Empty;
+                    }
+
+                }
+                set => ReplyAnnotation.SetCreationDate(value);
+            }
+
+            public string Content
+            {
+                get => ReplyAnnotation.GetContent();
+                set => ReplyAnnotation.SetContent(value);
+            }
+        }
+         
+        public class BindAnnotationResult : INotifyPropertyChanged
+        {
+            private ObservableCollection<ReplyData> _replyList = new ObservableCollection<ReplyData>();
+
+            public ObservableCollection<ReplyData> ReplyList
+            {
+                get => _replyList;
+                set
+                {
+                    if (_replyList != value)
+                    {
+                        if (_replyList != null)
+                        {
+                            // Unsubscribe from the previous collection
+                            _replyList.CollectionChanged -= ReplyList_CollectionChanged;
+                        }
+
+                        _replyList = value;
+
+                        if (_replyList != null)
+                        {
+                            // Subscribe to the new collection
+                            _replyList.CollectionChanged += ReplyList_CollectionChanged; ;
+                        }
+
+                        OnPropertyChanged(nameof(ReplyList));
+                    }
+                }
+            }
+
+            private void ReplyList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
+            {         
+                OnPropertyChanged(nameof(ReplyCount));
+            }
+
+            private Visibility _isAnnotListVisible = Visibility.Visible;
+            public Visibility IsAnnotListVisible
+            {
+                get { return _isAnnotListVisible; }
+                set
+                {
+                    _isAnnotListVisible = value;
+                    OnPropertyChanged(nameof(IsAnnotListVisible));
+                }
+            }
+
+            public int PageIndex { get; set; }
+
+            public int AnnotIndex { get => annotationData.AnnotIndex; }
+
+            public string Author
+            {
+                get => annotationData.Author;
+            }
+
+            public string ReplyCount
+            {
+                get => ReplyList.Count.ToString();
+            }
+
+            public string CreateDate
+            {
+                get
+                {
+                    if (Regex.IsMatch(annotationData.CreateTime, "(?<=D\\:)[0-9]+(?=[\\+\\-])"))
+                    {
+                        string dateStr = Regex.Match(annotationData.CreateTime, "(?<=D\\:)[0-9]+(?=[\\+\\-])").Value;
+                        return (dateStr.Substring(0, 4) + "-" + dateStr.Substring(4, 2) + "-" + dateStr.Substring(6, 2) + ", " + dateStr.Substring(8, 2) + ":" +
+                            dateStr.Substring(10, 2));
+                    }
+                    else
+                    {
+                        return string.Empty;
+                    }
+                }
+            }
+
+            public string Note
+            {
+                get => annotationData.Content;
+            }
+
+            public CPDFAnnotationType CurrentAnnotationType
+            {
+                get
+                {
+                    switch(Annotation.Type)
+                    {
+                        case C_ANNOTATION_TYPE.C_ANNOTATION_CIRCLE:
+                            return CPDFAnnotationType.Circle;
+
+                        case C_ANNOTATION_TYPE.C_ANNOTATION_SQUARE:
+                            return CPDFAnnotationType.Square;
+
+                        case C_ANNOTATION_TYPE.C_ANNOTATION_LINE:
+                            {
+                                if(Annotation.IsMeasured())
+                                    return CPDFAnnotationType.LineMeasure;
+                                else
+                                    return CPDFAnnotationType.Line;
+                            }
+
+                        case C_ANNOTATION_TYPE.C_ANNOTATION_FREETEXT:
+                             return CPDFAnnotationType.FreeText;
+
+                        case C_ANNOTATION_TYPE.C_ANNOTATION_HIGHLIGHT:
+                             return CPDFAnnotationType.Highlight;
+
+                        case C_ANNOTATION_TYPE.C_ANNOTATION_SQUIGGLY:
+                            return CPDFAnnotationType.Squiggly;
+
+                        case C_ANNOTATION_TYPE.C_ANNOTATION_STRIKEOUT:
+                            return CPDFAnnotationType.Strikeout;
+
+                        case C_ANNOTATION_TYPE.C_ANNOTATION_UNDERLINE:
+                            return CPDFAnnotationType.Underline;
+
+                        case C_ANNOTATION_TYPE.C_ANNOTATION_INK:
+                            return CPDFAnnotationType.Freehand;
+
+                        case C_ANNOTATION_TYPE.C_ANNOTATION_TEXT:
+                            return CPDFAnnotationType.Note;
+
+                        case C_ANNOTATION_TYPE.C_ANNOTATION_STAMP:
+                            return CPDFAnnotationType.Stamp;
+
+                        case C_ANNOTATION_TYPE.C_ANNOTATION_POLYLINE:
+                            {
+                                if (Annotation.IsMeasured())
+                                    return CPDFAnnotationType.PolyLineMeasure;
+                                else
+                                    return CPDFAnnotationType.PolyLine;
+                            }
+
+                        case C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON:
+                            {
+                                if (Annotation.IsMeasured())
+                                    return CPDFAnnotationType.PolygonMeasure;
+                                else
+                                    return CPDFAnnotationType.Polygon;
+                            }
+
+                        default:
+                            return CPDFAnnotationType.Note;
+
+                    }
+
+                }
+
+            }
+
+            public AnnotParam annotationData { get; set; }
+
+            private CPDFAnnotation _annotation;
+            public CPDFAnnotation Annotation
+            {
+                get
+                {
+                    List<CPDFAnnotation> annotCoreList = pdfViewer?.GetCPDFViewer()?.GetDocument()?.PageAtIndex(annotationData.PageIndex, false)?.GetAnnotations();
+                    return annotCoreList[annotationData.AnnotIndex];
+                }
+            }
+
+            public PDFViewControl pdfViewer { get; set; }
+
+            public CPDFAnnotationState ReplyState { get; set; }
+
+            public bool IsMarkState { get; set; }
+            public BindAnnotationResult()
+            {
+                ReplyList.CollectionChanged += ReplyList_CollectionChanged;
+            }
+             
+            public event PropertyChangedEventHandler PropertyChanged;
+            protected void OnPropertyChanged(string propertyName)
+            {
+                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+            } 
+        }
+
+        private ObservableCollection<AnnotationBindData> annotationList = new ObservableCollection<AnnotationBindData>();
+
+        public event EventHandler<object> AnnotationSelectionChanged;
+
+        public event EventHandler<Dictionary<int, List<int>>> DeleteItemHandler;
+
+        private ContextMenu popContextMenu;
+        private bool enableSelectEvent = true;
+
+        public CPDFAnnotationListUI()
+        {
+            InitializeComponent();
+            ICollectionView groupView = CollectionViewSource.GetDefaultView(annotationList);
+            groupView.GroupDescriptions.Add(new PropertyGroupDescription(nameof(AnnotationBindData.ShowPageIndex)));
+            AnnotationList.PreviewMouseRightButtonUp += ((sender, args) => { SetContextMenu(); });
+        }
+
+        private void SetContextMenu()
+        {
+            if (AnnotationList.SelectedIndex == -1)
+            {
+                return;
+            }
+            popContextMenu = new ContextMenu();
+            AnnotationBindData data = annotationList[AnnotationList.SelectedIndex];
+
+            MenuItem deleteMenu = new MenuItem();
+            deleteMenu.Header = LanguageHelper.BotaManager.GetString("Menu_Delete");
+            deleteMenu.Click -= DeleteMenu_Click;
+            deleteMenu.Click += DeleteMenu_Click;
+            popContextMenu.Items.Add(deleteMenu);
+
+            MenuItem deleteAllMenu = new MenuItem();
+            deleteAllMenu.Header = LanguageHelper.BotaManager.GetString("Menu_DeleteAll");
+            deleteAllMenu.Click -= DeleteAllMenu_Click;
+            deleteAllMenu.Click += DeleteAllMenu_Click;
+            popContextMenu.Items.Add(deleteAllMenu);
+
+            MenuItem replyMenu = new MenuItem();
+            replyMenu.Header = LanguageHelper.BotaManager.GetString("Menu_AddReply");
+            replyMenu.Click += (sender, e) =>
+            {
+                if (AnnotationList != null && AnnotationList.SelectedIndex >= 0)
+                {
+                    data.IsReplyInputVisible = true;
+                }
+            };
+            popContextMenu.Items.Add(replyMenu);
+
+            MenuItem showReplyMenu = new MenuItem();
+
+            if (data.IsReplyListVisible)
+            {
+                showReplyMenu.Header = LanguageHelper.BotaManager.GetString("Menu_FoldReply");
+            }
+            else
+            {
+                showReplyMenu.Header = LanguageHelper.BotaManager.GetString("Menu_ExpandReply");
+            }
+            showReplyMenu.Click += (sender, e) =>
+            {
+                if (AnnotationList != null && AnnotationList.SelectedIndex >= 0)
+                {
+                    data.IsReplyListVisible = !data.IsReplyListVisible;
+                }
+            };
+            popContextMenu.Items.Add(showReplyMenu);
+
+            AnnotationList.ContextMenu = popContextMenu;
+        }
+
+        public void DeleteAllAnnot()
+        {
+            try
+            {
+                Dictionary<int, List<int>> delDict = new Dictionary<int, List<int>>();
+
+                foreach (AnnotationBindData bindData in annotationList)
+                {
+                    if (delDict.ContainsKey(bindData.BindProperty.PageIndex) == false)
+                    {
+                        delDict[bindData.BindProperty.PageIndex] = new List<int>();
+                    }
+                    delDict[bindData.BindProperty.PageIndex].Add(bindData.BindProperty.AnnotIndex);
+                }
+
+                if (delDict.Count > 0)
+                {
+                    DeleteItemHandler?.Invoke(this, delDict);
+                }
+            }
+            catch (Exception ex)
+            {
+                return;
+            }
+        }
+
+        public void DeleteAllReply()
+        {
+            try
+            {
+                foreach (var data in annotationList)
+                {
+                    foreach (var replyData in data.BindProperty.ReplyList)
+                    {
+                        replyData.ReplyAnnotation.RemoveAnnot();
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+                return;
+            }
+        }
+
+        public void ExpandAllReply(bool isExpand)
+        {
+            foreach (AnnotationBindData data in annotationList)
+            {
+                data.IsReplyListVisible = isExpand;
+            }
+        }
+
+        public void ExpandAnnotList(bool isExpand)
+        {
+            foreach (AnnotationBindData data in annotationList)
+            {
+                if (isExpand)
+                    data.BindProperty.IsAnnotListVisible = Visibility.Visible;
+                else
+                    data.BindProperty.IsAnnotListVisible = Visibility.Collapsed;
+            }
+        }
+
+        private void DeleteAllMenu_Click(object sender, RoutedEventArgs e)
+        {
+            try
+            {
+                Dictionary<int, List<int>> delDict = new Dictionary<int, List<int>>();
+
+                foreach (AnnotationBindData bindData in annotationList)
+                {
+                    if (delDict.ContainsKey(bindData.BindProperty.PageIndex) == false)
+                    {
+                        delDict[bindData.BindProperty.PageIndex] = new List<int>();
+                    }
+                    delDict[bindData.BindProperty.PageIndex].Add(bindData.BindProperty.AnnotIndex);
+                }
+
+                if (delDict.Count > 0)
+                {
+                    DeleteItemHandler?.Invoke(this, delDict);
+                }
+            }
+            catch (Exception ex)
+            {
+
+            }
+        }
+
+        private void DeleteMenu_Click(object sender, RoutedEventArgs e)
+        {
+            try
+            {
+                if (AnnotationList != null && AnnotationList.SelectedIndex >= 0)
+                {
+                    AnnotationBindData bindData = annotationList[AnnotationList.SelectedIndex];
+
+                    Dictionary<int, List<int>> delDict = new Dictionary<int, List<int>>();
+                    delDict[bindData.BindProperty.PageIndex] = new List<int>()
+                    {
+                        bindData.BindProperty.AnnotIndex
+                    };
+                    DeleteItemHandler?.Invoke(this, delDict);
+                }
+            }
+            catch (Exception ex)
+            {
+
+            }
+        }
+
+        public void SetAnnotationList(List<BindAnnotationResult> results)
+        {
+            annotationList.Clear();
+            AnnotationList.ContextMenu = null;
+            if (results == null || results.Count == 0)
+            {
+                AnnotationList.ItemsSource = null;
+                NoContentText.Visibility = Visibility.Visible;
+                return;
+            }
+
+            foreach (BindAnnotationResult item in results)
+            {
+                annotationList.Add(new AnnotationBindData()
+                {
+                    BindProperty = item
+                });
+            }
+            AnnotationList.ItemsSource = annotationList;
+            if (annotationList.Count > 0)
+            {
+                AnnotationList.ContextMenu = popContextMenu;
+            }
+            AnnotationList.Visibility = Visibility.Visible;
+            NoContentText.Visibility = Visibility.Collapsed;
+        }
+
+        private void AnnotationListControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
+        {
+            if (enableSelectEvent)
+            {
+                try
+                {
+                    if (e.AddedItems[0] is AnnotationBindData annotationBindData)
+                    {
+                        AnnotationSelectionChanged?.Invoke(this, (annotationBindData).BindProperty);
+                    }
+                }
+                catch { }
+            }
+        }
+
+        public void CancelSelected()
+        {
+            AnnotationList.SelectedIndex = -1;
+        }
+
+        public void SelectAnnotationChanged(int annotationIndex = -1)
+        {
+
+            AnnotationList.SelectedIndex = annotationIndex;
+        }
+
+        public void SelectAnnotationChanged(int pageIIndex, int annotIndex)
+        {
+            if (annotationList != null && annotationList.Count > 0)
+            {
+                for (int i = 0; i < annotationList.Count; i++)
+                {
+                    AnnotationBindData data = annotationList[i];
+                    if (data.BindProperty.PageIndex == pageIIndex && data.BindProperty.AnnotIndex == annotIndex)
+                    {
+                        enableSelectEvent = false;
+                        AnnotationList.SelectedIndex = i;
+                        enableSelectEvent = true;
+                        break;
+                    }
+                }
+            }
+        }
+
+        private void AnnotationList_ContextMenuOpening(object sender, ContextMenuEventArgs e)
+        {
+            try
+            {
+                if (popContextMenu.Items[0] is MenuItem checkMenu)
+                {
+                    if (checkMenu != null)
+                    {
+                        checkMenu.IsEnabled = true;
+                    }
+                    if (AnnotationList != null && AnnotationList.SelectedIndex == -1)
+                    {
+                        checkMenu.IsEnabled = false;
+                    }
+                }  
+            }
+            catch (Exception ex)
+            {
+
+            }
+        }
+
+        private void AnnotationList_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
+        {
+            CancelSelected();
+        }
+
+        private void ToggleButton_Checked(object sender, RoutedEventArgs e)
+        {
+            ReplyStatusChanged?.Invoke(sender, CPDFAnnotationState.C_ANNOTATION_MARKED);
+        }
+
+        private void ToggleButton_Unchecked(object sender, RoutedEventArgs e)
+        {
+            ReplyStatusChanged?.Invoke(sender, CPDFAnnotationState.C_ANNOTATION_UNMARKED);
+        }
+
+        private void StatusControl_ReplyStatusChanged(object sender, CPDFAnnotationState e)
+        {
+            ReplyStatusChanged?.Invoke(sender, e);
+        }
+    }
+}

+ 71 - 0
Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListUI/ReplyStatusControl.xaml

@@ -0,0 +1,71 @@
+<UserControl x:Class="ComPDFKit.Controls.PDFControlUI.ReplyStatusControl"
+             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.Controls.PDFControlUI"
+             mc:Ignorable="d"  
+             d:DesignHeight="450" d:DesignWidth="800">
+    <UserControl.Resources>
+        <Style x:Key="MenuItemStyle" TargetType="local:PathMenuItem">
+            <Setter Property="Template">
+                <Setter.Value>
+                    <ControlTemplate TargetType="{x:Type local:PathMenuItem}">
+                        <Border x:Name="border"
+                            Background="#FFFFFF"
+                            BorderThickness="0"
+                            Height="40">
+                            <Grid Margin="20,0,20,0">
+                                <Grid.ColumnDefinitions>
+                                    <ColumnDefinition Width="Auto"></ColumnDefinition>
+                                    <ColumnDefinition Width="Auto"></ColumnDefinition>
+                                </Grid.ColumnDefinitions>
+                                <ContentPresenter x:Name="IconPresenter"
+                                              ContentSource="IconPath"
+                                              Grid.Column="0">
+                                </ContentPresenter>
+                                <ContentPresenter x:Name="contentPresenter"
+                                              Grid.Column="1"
+                                              ContentSource="Header"
+                                              TextBlock.Foreground="#000000"
+                                              TextBlock.FontFamily="SegoeUI"
+                                              TextBlock.FontSize="15"
+                                              Margin="10,0,0,0"
+                                              HorizontalAlignment="Left"
+                                              VerticalAlignment="Center">
+                                </ContentPresenter>
+                            </Grid>
+                        </Border>
+                        <ControlTemplate.Triggers>
+                            <Trigger Property="IsEnabled" Value="False">
+                                <Setter Property="TextBlock.Foreground" TargetName="contentPresenter" Value="#6A6A6A"></Setter>
+                                <Setter TargetName="border" Property="Background" Value="#EFEFEF"></Setter>
+                            </Trigger>
+                            <Trigger Property="IsHighlighted" Value="True">
+                                <Setter Property="Background" TargetName="border" Value="#2894FF"></Setter>
+                                <Setter Property="BorderBrush" TargetName="border" Value="#2894FF"></Setter>
+                                <Setter Property="TextBlock.Foreground" TargetName="contentPresenter" Value="#FFFFFF"></Setter>
+                            </Trigger>
+                        </ControlTemplate.Triggers>
+                    </ControlTemplate>
+                </Setter.Value>
+            </Setter>
+        </Style>
+    </UserControl.Resources>
+    <Grid Height="auto">
+        <Grid Height="30" Width="30">
+            <Menu Background="Transparent">
+                <local:PathMenuItem x:Name="IconMenu" Height="30" Width="30" Margin="0" Padding="0">
+                    <local:PathMenuItem.Header>
+                        <Grid x:Name="ButtonIcon" Height="30" Width="30">
+                            <Canvas Height="20" Width="20"> 
+                                <Rectangle Stroke="#5A000000" StrokeThickness="2" Width="16" Height="16"/>
+                                <Line X1="1" Y1="1" X2="15" Y2="15" Stroke="#5A000000" StrokeThickness="2"/>
+                            </Canvas>
+                        </Grid>
+                    </local:PathMenuItem.Header>
+                </local:PathMenuItem>
+            </Menu>
+        </Grid>
+    </Grid>
+</UserControl>

Diff do ficheiro suprimidas por serem muito extensas
+ 175 - 0
Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListUI/ReplyStatusControl.xaml.cs


+ 8 - 4
Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationPanel/PDFAnnotationControl/CPDFAnnotationControl.xaml.cs

@@ -12,7 +12,6 @@ using ComPDFKit.Controls.Annotation.PDFAnnotationUI;
 using Microsoft.Win32;
 using System.Windows.Media;
 using ComPDFKit.Controls.Properties;
-using static ComPDFKit.Tool.CPDFToolManager;
 using ComPDFKit.PDFAnnotation;
 using ComPDFKit.Tool;
 using ComPDFKit.Tool.Help;
@@ -101,7 +100,6 @@ namespace ComPDFKit.Controls.PDFControl
         {
             if (e.IsCreate)
             {
-                pdfViewerControl.UpdateAnnotFrame();
                 if (currentAnnotationType == CPDFAnnotationType.Image || currentAnnotationType == CPDFAnnotationType.Stamp || currentAnnotationType == CPDFAnnotationType.Signature)
                 {
                     pdfViewerControl.SetToolType(ToolType.Pan);
@@ -409,6 +407,7 @@ namespace ComPDFKit.Controls.PDFControl
                         PDFHelp.ImageStreamToByte(stampParam.ImageStream, ref imageData, ref imageWidth, ref imageHeight);
                         if (imageData != null && imageWidth > 0 && imageHeight > 0)
                         {
+                            pdfViewerControl.PDFViewTool.GetCPDFViewer().SetMouseImageMaxSize(200, 300);
                             pdfViewerControl.SetStampMouseImage(imageData, imageWidth, imageHeight);
                         }
 
@@ -434,6 +433,7 @@ namespace ComPDFKit.Controls.PDFControl
                                     PDFHelp.ImageStreamToByte(stampParam.ImageStream, ref imageData, ref imageWidth, ref imageHeight);
                                     if (imageData != null && imageWidth > 0 && imageHeight > 0)
                                     {
+                                        pdfViewerControl.PDFViewTool.GetCPDFViewer().SetMouseImageMaxSize(200, 300);
                                         pdfViewerControl.SetStampMouseImage(imageData, imageWidth, imageHeight);
                                         pdfViewerControl.SetIsVisibleCustomMouse(true);
                                         pdfViewerControl.SetIsShowStampMouse(true);
@@ -446,6 +446,7 @@ namespace ComPDFKit.Controls.PDFControl
                                     WriteableBitmap writeableBitmap = CreateInkImage(signatureParam as InkParam);
                                     byte[] imageArray = new byte[writeableBitmap.PixelWidth * writeableBitmap.PixelHeight * 4];
                                     writeableBitmap.CopyPixels(imageArray, writeableBitmap.PixelWidth * 4, 0);
+                                    pdfViewerControl.PDFViewTool.GetCPDFViewer().SetMouseImageMaxSize(writeableBitmap.PixelWidth, writeableBitmap.PixelHeight);
                                     pdfViewerControl.SetStampMouseImage(imageArray, writeableBitmap.PixelWidth, writeableBitmap.PixelHeight);
                                     pdfViewerControl.SetIsVisibleCustomMouse(true);
                                     pdfViewerControl.SetIsShowStampMouse(true);
@@ -484,6 +485,7 @@ namespace ComPDFKit.Controls.PDFControl
             {
                 return null;
             }
+
             if (inkParam.InkPath != null && inkParam.InkPath.Count > 0)
             {
                 GeometryGroup PaintGeomtry = new GeometryGroup();
@@ -514,10 +516,10 @@ namespace ComPDFKit.Controls.PDFControl
                         }
                     }
                 }
+
                 if (minLeft >= 0 && maxLeft > minLeft && minTop >= 0 && maxTop > minTop)
                 {
                     List<List<CPoint>> points = new List<List<CPoint>>();
-
                     foreach (List<CPoint> Item in inkParam.InkPath)
                     {
                         PathGeometry PaintPath = new PathGeometry();
@@ -548,13 +550,13 @@ namespace ComPDFKit.Controls.PDFControl
                             points.Add(changeList);
                         }
                     }
+
                     int drawWidth = (int)DpiHelper.PDFNumToStandardNum(maxLeft - minLeft);
                     int drawHeight = (int)DpiHelper.PDFNumToStandardNum(maxTop - minTop);
 
                     inkParam.InkPath = points;
                     DefaultSettingParam defaultSettingParam = pdfViewerControl.PDFViewTool.GetDefaultSettingParam();
                     defaultSettingParam.SetAnnotParam(inkParam);
-
                     DrawingVisual copyVisual = new DrawingVisual();
                     DrawingContext copyContext = copyVisual.RenderOpen();
 
@@ -895,6 +897,8 @@ namespace ComPDFKit.Controls.PDFControl
                                     {
                                         frame.CopyPixels(imageArray, frame.PixelWidth * 4, 0);
                                     }
+
+                                    pdfViewerControl.PDFViewTool.GetCPDFViewer().SetMouseImageMaxSize(200, 300);
                                     pdfViewerControl.SetStampMouseImage(imageArray, frame.PixelWidth, frame.PixelHeight);
                                 }
 

+ 1 - 0
Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationPanel/PDFAnnotationUI/CPDFSignatureUI.xaml.cs

@@ -75,6 +75,7 @@ namespace ComPDFKit.Controls.Annotation.PDFAnnotationPanel.PDFAnnotationUI
             else
             {
                 FillForm(((sender as ListBoxItem).DataContext as CPDFSignatureData).SourcePath);
+                viewControl.PDFViewTool.IsDocumentModified = true;
             }
         }
 

+ 1 - 1
Demo/Examples/Compdfkit.Controls/Asset/Styles/ComboBoxStyle.xaml

@@ -394,7 +394,7 @@
                                     <Border.Effect>
                                         <DropShadowEffect Color="Black" BlurRadius="4" ShadowDepth="0" Opacity="0.5"/>
                                     </Border.Effect>
-                                    <ScrollViewer Margin="4,6,4,6" Style="{DynamicResource ScrollViewerStyle}" MaxHeight="{TemplateBinding MaxDropDownHeight}" SnapsToDevicePixels="True" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" CanContentScroll="True">
+                                    <ScrollViewer Margin="0,3,0,6" Style="{DynamicResource ScrollViewerStyle}" MaxHeight="{TemplateBinding MaxDropDownHeight}" SnapsToDevicePixels="True" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto" CanContentScroll="True">
                                         <StackPanel IsItemsHost="True" KeyboardNavigation.DirectionalNavigation="Contained" Background="White"/>
                                     </ScrollViewer>
                                 </Border>

+ 0 - 2
Demo/Examples/Compdfkit.Controls/Asset/Styles/ListBoxItemStyle.xaml

@@ -20,8 +20,6 @@
     <Style x:Key="ThumbnailListBoxItemStyle" TargetType="{x:Type ListBoxItem}">
         <Setter Property="SnapsToDevicePixels" Value="True"/>
         <Setter Property="Padding" Value="4,1"/>
-        <Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
-        <Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
         <Setter Property="Background" Value="Transparent"/>
         <Setter Property="BorderBrush" Value="Transparent"/>
         <Setter Property="BorderThickness" Value="1"/>

+ 4 - 0
Demo/Examples/Compdfkit.Controls/Common/BarControl/CPDFTitleBarControl.xaml

@@ -38,6 +38,8 @@
                         <MenuItem Header="{Binding Converter={StaticResource CommonResourceConverter},ConverterParameter=HelpMenu_Service}" Style="{StaticResource Sub_MenuItem}" Click="ServiceTerms_Click"></MenuItem>
                         <MenuItem Header="{Binding Converter={StaticResource CommonResourceConverter},ConverterParameter=HelpMenu_DeviceID}" Style="{StaticResource Sub_MenuItem}" Click="DeviceSerial_Click"></MenuItem>
                     </MenuItem>
+
+                    <MenuItem Header="{Binding Converter={StaticResource CommonResourceConverter},ConverterParameter=Printer_Print}" Style="{StaticResource Dropdown_MenuItem}" Click="PrintItem_Click"></MenuItem>
                 </Menu>
 
                 <Menu 
@@ -68,6 +70,8 @@
                         <MenuItem Header="Contact us" Style="{StaticResource Sub_MenuItem }"></MenuItem>
                     </MenuItem>
                 </Menu>
+                
+                
             </StackPanel>
         </Grid>
     </Grid>

+ 7 - 1
Demo/Examples/Compdfkit.Controls/Common/BarControl/CPDFTitleBarControl.xaml.cs

@@ -19,7 +19,8 @@ namespace ComPDFKit.Controls.PDFControl
         public event EventHandler SaveFileEvent;
         public event EventHandler SaveAsFileEvent;
         public event EventHandler FlattenEvent; 
-
+        public event EventHandler PrintEvent;
+           
         public CPDFTitleBarControl()
         {
             InitializeComponent();
@@ -79,5 +80,10 @@ namespace ComPDFKit.Controls.PDFControl
         {
             FlattenEvent?.Invoke(sender, RoutedEventArgs.Empty);
         }
+
+        private void PrintItem_Click(object sender, RoutedEventArgs e)
+        {
+            PrintEvent?.Invoke(sender, RoutedEventArgs.Empty);
+        }
     }
 }

+ 2 - 4
Demo/Examples/Compdfkit.Controls/Common/BaseControl/PageNumberControl.xaml

@@ -14,7 +14,6 @@
                 <ColumnDefinition Width="auto"></ColumnDefinition>
             </Grid.ColumnDefinitions>
 
-            <!--上一页-->
             <Border Background="Transparent" Width="20" Height="20" Margin="11,0,0,0" MouseLeftButtonDown="PrevPageBorder_MouseLeftButtonDown">
                 <Path Fill="White" VerticalAlignment="Center" HorizontalAlignment="Center">
                     <Path.Data>
@@ -26,16 +25,15 @@
                 </Path>
             </Border>
 
-            <!--页码范围-->
             <TextBlock Name="PageRangeText" Grid.Column="1" Foreground="White" FontSize="12" VerticalAlignment="Center" HorizontalAlignment="Center" 
-                       MouseLeftButtonUp="PageRangeText_MouseLeftButtonUp">19999/99999</TextBlock>
+                       MouseLeftButtonUp="PageRangeText_MouseLeftButtonUp">1/1</TextBlock>
 
             <TextBox Name="PageInputText" Grid.Column="1" VerticalAlignment="Center" Background="Transparent" Foreground="White" FontSize="12"
                      LostFocus="PageInputText_LostFocus" KeyDown="PageInputText_KeyDown" Visibility="Collapsed" InputMethod.IsInputMethodEnabled="False"
                      PreviewKeyDown="PageInputText_PreviewKeyDown" CaretBrush="White" CommandManager.PreviewCanExecute="PageInputText_CanExecute"
                      HorizontalContentAlignment="Center"
                       ></TextBox>
-            <!--下一页-->
+            
             <Border Width="20" Height="20" Background="Transparent" Grid.Column="2" Margin="0,0,11,0" MouseLeftButtonDown="NextPageBorder_MouseLeftButtonDown">
                 <Path Fill="White" VerticalAlignment="Center" HorizontalAlignment="Center">
                     <Path.Data>

+ 3 - 3
Demo/Examples/Compdfkit.Controls/Common/Convert/AnnotArgsTypeToVisibilityConverter.cs

@@ -1,4 +1,4 @@
-using ComPDFKit.PDFAnnotation;
+using ComPDFKit.Controls.Data;
 using System;
 using System.Globalization;
 using System.Windows;
@@ -6,12 +6,12 @@ using System.Windows.Data;
 
 namespace ComPDFKit.Controls.Common
 {
-    [ValueConversion(typeof(C_ANNOTATION_TYPE), typeof(Visibility))]
+    [ValueConversion(typeof(CPDFAnnotationType), typeof(Visibility))]
     public class AnnotArgsTypeToVisibilityConverter : IValueConverter
     {
         public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
         {
-            C_ANNOTATION_TYPE annotArgsType = (C_ANNOTATION_TYPE)value;
+            CPDFAnnotationType annotArgsType = (CPDFAnnotationType)value;
             if (annotArgsType.ToString() == parameter as string)
             {
                 return Visibility.Visible;

+ 25 - 0
Demo/Examples/Compdfkit.Controls/Common/Convert/AntiVisibilityConverter.cs

@@ -0,0 +1,25 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Data;
+
+namespace ComPDFKit.Controls.Common
+{
+    [ValueConversion(typeof(Visibility), typeof(Visibility))]
+    internal class AntiVisibilityConverter: IValueConverter
+    {
+        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            return (Visibility)value == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible;
+        }
+
+        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            return (Visibility)value == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible;
+        }
+    }
+}

+ 8 - 10
Demo/Examples/Compdfkit.Controls/Common/Convert/LanguageResourceConverter.cs

@@ -6,8 +6,6 @@ using ComPDFKit.Controls.Helper;
 
 namespace ComPDFKit.Controls.Common
 {
-
-
     public class BotaResourceConverter : IValueConverter
     {
         public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
@@ -22,7 +20,7 @@ namespace ComPDFKit.Controls.Common
 
         public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
         {
-            throw new NotSupportedException();
+            return null;
         }
     }
 
@@ -40,7 +38,7 @@ namespace ComPDFKit.Controls.Common
 
         public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
         {
-            throw new NotSupportedException();
+            return null;
         }
     }
 
@@ -58,7 +56,7 @@ namespace ComPDFKit.Controls.Common
 
         public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
         {
-            throw new NotSupportedException();
+            return null;
         }
     }
 
@@ -76,7 +74,7 @@ namespace ComPDFKit.Controls.Common
 
         public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
         {
-            throw new NotSupportedException();
+            return null;
         }
     }
 
@@ -94,7 +92,7 @@ namespace ComPDFKit.Controls.Common
 
         public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
         {
-            throw new NotSupportedException();
+            return null;
         }
     }
     
@@ -112,7 +110,7 @@ namespace ComPDFKit.Controls.Common
 
         public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
         {
-            throw new NotSupportedException();
+            return null;
         }
     }
     
@@ -130,7 +128,7 @@ namespace ComPDFKit.Controls.Common
 
         public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
         {
-            throw new NotSupportedException();
+            return null;
         }
     }
     
@@ -148,7 +146,7 @@ namespace ComPDFKit.Controls.Common
 
         public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
         {
-            throw new NotSupportedException();
+            return null;
         }
     }
 }

+ 28 - 0
Demo/Examples/Compdfkit.Controls/Common/Convert/SubtractionConverter.cs

@@ -0,0 +1,28 @@
+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.Controls.Common 
+{
+    [ValueConversion(typeof(double), typeof(double))]
+    public class SubtractionConverter : IValueConverter
+    {
+        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            if (value is double actualWidth && parameter is string parameterValue && double.TryParse(parameterValue, out double subtractValue))
+            {
+                return actualWidth - subtractValue;
+            }
+            return value;
+        }
+
+        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            return null;
+        }
+    }
+}

+ 1 - 1
Demo/Examples/Compdfkit.Controls/Common/PropertyControl/PDFFont/CPDFFontControl.xaml.cs

@@ -31,7 +31,7 @@ namespace ComPDFKit.Controls.Common
                 var _fontFamilyName = string.Empty;
                 var _fontStyleName = string.Empty;
                 _postScriptName = value;
-                CPDFFont.GetFamlyStyleName(_postScriptName, ref _fontFamilyName, ref _fontStyleName);
+                CPDFFont.GetFamilyStyleName(_postScriptName, ref _fontFamilyName, ref _fontStyleName);
                 FontFamilyValue = _fontFamilyName;
                 FontStyleValue = _fontStyleName;
             }

+ 48 - 7
Demo/Examples/Compdfkit.Controls/Compdfkit.Controls.csproj

@@ -28,6 +28,7 @@
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <PlatformTarget>AnyCPU</PlatformTarget>
@@ -37,6 +38,7 @@
     <DefineConstants>TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <PropertyGroup>
     <StartupObject />
@@ -52,6 +54,7 @@
     <PlatformTarget>x64</PlatformTarget>
     <LangVersion>7</LangVersion>
     <ErrorReport>prompt</ErrorReport>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
     <OutputPath>bin\x64\Release\</OutputPath>
@@ -61,6 +64,7 @@
     <PlatformTarget>x64</PlatformTarget>
     <LangVersion>7</LangVersion>
     <ErrorReport>prompt</ErrorReport>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
     <DebugSymbols>true</DebugSymbols>
@@ -70,6 +74,7 @@
     <PlatformTarget>x86</PlatformTarget>
     <LangVersion>7</LangVersion>
     <ErrorReport>prompt</ErrorReport>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
     <OutputPath>bin\x86\Release\</OutputPath>
@@ -79,6 +84,7 @@
     <PlatformTarget>x86</PlatformTarget>
     <LangVersion>7</LangVersion>
     <ErrorReport>prompt</ErrorReport>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="Nager.Country, Version=4.0.0.0, Culture=neutral, processorArchitecture=MSIL">
@@ -87,10 +93,12 @@
     <Reference Include="PresentationFramework.Aero2, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
       <HintPath>..\packages\PresentationFramework.Aero2.1.0.1\lib\PresentationFramework.Aero2.dll</HintPath>
     </Reference>
+    <Reference Include="ReachFramework" />
     <Reference Include="System" />
     <Reference Include="System.Data" />
     <Reference Include="System.Drawing" />
     <Reference Include="System.Management" />
+    <Reference Include="System.Printing" />
     <Reference Include="System.Windows.Forms" />
     <Reference Include="System.Xml" />
     <Reference Include="Microsoft.CSharp" />
@@ -118,8 +126,14 @@
     <Compile Include="Annotation\PDFAnnotationList\PDFAnnotationListControl\CPDFAnnotationListControl.xaml.cs">
       <DependentUpon>CPDFAnnotationListControl.xaml</DependentUpon>
     </Compile>
-    <Compile Include="Annotation\PDFAnnotationList\PDFAnnotationListUI\CPDFAnnoationListUI.xaml.cs">
-      <DependentUpon>CPDFAnnoationListUI.xaml</DependentUpon>
+    <Compile Include="Annotation\PDFAnnotationList\PDFAnnotationListUI\AnnotationReplyListControl.xaml.cs">
+      <DependentUpon>AnnotationReplyListControl.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="Annotation\PDFAnnotationList\PDFAnnotationListUI\CPDFAnnotationListUI.xaml.cs">
+      <DependentUpon>CPDFAnnotationListUI.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="Annotation\PDFAnnotationList\PDFAnnotationListUI\ReplyStatusControl.xaml.cs">
+      <DependentUpon>ReplyStatusControl.xaml</DependentUpon>
     </Compile>
     <Compile Include="Annotation\PDFAnnotationPanel\PDFAnnotationUI\CPDFFreehandUI.xaml.cs">
       <DependentUpon>CPDFFreehandUI.xaml</DependentUpon>
@@ -162,6 +176,7 @@
     <Compile Include="Common\BaseControl\PageNumberControl.xaml.cs">
       <DependentUpon>PageNumberControl.xaml</DependentUpon>
     </Compile>
+    <Compile Include="Common\Convert\AntiVisibilityConverter.cs" />
     <Compile Include="Common\Convert\BoolToColorConverter.cs" />
     <Compile Include="Common\Convert\HeightToTopMarginConverter.cs" />
     <Compile Include="Common\Convert\HomePageFileListHeightConverter.cs" />
@@ -178,6 +193,7 @@
     <Compile Include="Common\Convert\StringToVisibilityConverter.cs" />
     <Compile Include="Common\Convert\ShowDefaultCloseButtonConverter.cs" />
     <Compile Include="Common\Convert\ShowIconConverter.cs" />
+    <Compile Include="Common\Convert\SubtractionConverter.cs" />
     <Compile Include="Common\Convert\TagToBoolConverter.cs" />
     <Compile Include="Common\Convert\WindowStateToPathConverter.cs" />
     <Compile Include="Common\Convert\WindowStateToThicknessConverter.cs" />
@@ -380,6 +396,14 @@
     <Compile Include="Common\BarControl\FormBarControl.xaml.cs">
       <DependentUpon>FormBarControl.xaml</DependentUpon>
     </Compile>
+    <Compile Include="Printer\PrinterDialog.xaml.cs">
+      <DependentUpon>PrinterDialog.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="Printer\PrinterModel.cs" />
+    <Compile Include="Printer\PrintHelper.cs" />
+    <Compile Include="Printer\PrintPreviewControl.xaml.cs">
+      <DependentUpon>PrintPreviewControl.xaml</DependentUpon>
+    </Compile>
     <Compile Include="Security\Encryption\DecryptionDialog.xaml.cs">
       <DependentUpon>DecryptionDialog.xaml</DependentUpon>
     </Compile>
@@ -745,7 +769,15 @@
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
     </Page>
-    <Page Include="Annotation\PDFAnnotationList\PDFAnnotationListUI\CPDFAnnoationListUI.xaml">
+    <Page Include="Annotation\PDFAnnotationList\PDFAnnotationListUI\AnnotationReplyListControl.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
+    <Page Include="Annotation\PDFAnnotationList\PDFAnnotationListUI\CPDFAnnotationListUI.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
+    <Page Include="Annotation\PDFAnnotationList\PDFAnnotationListUI\ReplyStatusControl.xaml">
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
     </Page>
@@ -1081,6 +1113,14 @@
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
     </Page>
+    <Page Include="Printer\PrinterDialog.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
+    <Page Include="Printer\PrintPreviewControl.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
     <Page Include="Security\Encryption\DecryptionDialog.xaml" />
     <Page Include="Security\Encryption\EncryptionDialog.xaml" />
     <Page Include="Security\Encryption\FileGridListControl.xaml" />
@@ -1296,18 +1336,19 @@
     </Page>
   </ItemGroup>
   <ItemGroup>
-    <ProjectReference Include="..\..\..\..\compdfkit_windows\ComPDFKit\ComPDFKitCSharp\ComPDFKit.NET.csproj">
-      <Project>{56e518ad-c126-4b48-9a09-0a64c87020e4}</Project>
+    <ProjectReference Include="..\..\..\..\ComPDFKit-ForRebuild\ComPDFKit\ComPDFKitCSharp\ComPDFKit.NET.csproj">
+      <Project>{122caf49-dcf7-49b1-8872-80b363e187e4}</Project>
       <Name>ComPDFKit.NET</Name>
     </ProjectReference>
-    <ProjectReference Include="..\..\..\..\compdfkit_windows_rebuild\ComPDFKit.Tool\ComPDFKit.Tool.csproj">
+    <ProjectReference Include="..\..\..\..\ComPDFKit-Rebuild\ComPDFKit.Tool\ComPDFKit.Tool.csproj">
       <Project>{a061ee7a-6704-4bd9-86ee-48ed5df75e2f}</Project>
       <Name>ComPDFKit.Tool</Name>
     </ProjectReference>
-    <ProjectReference Include="..\..\..\..\compdfkit_windows_rebuild\ComPDFKit.Viewer\ComPDFKit.Viewer.csproj">
+    <ProjectReference Include="..\..\..\..\ComPDFKit-Rebuild\ComPDFKit.Viewer\ComPDFKit.Viewer.csproj">
       <Project>{783263cf-0da3-4095-9df8-2c4a6b3ff908}</Project>
       <Name>ComPDFKit.Viewer</Name>
     </ProjectReference>
   </ItemGroup>
+  <ItemGroup />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
 </Project>

+ 3 - 1
Demo/Examples/Compdfkit.Controls/DigitalSignature/DigitalSignatureControl/DigitalSignatureControl.xaml.cs

@@ -214,7 +214,9 @@ namespace ComPDFKit.Controls.PDFControl
 
         private void PDFViewControl_MouseLeftButtonDownHandler(object sender, MouseEventObject e)
         {
-            if (PDFViewControl.PDFViewTool.GetToolType() == ToolType.WidgetEdit && e.annotType== C_ANNOTATION_TYPE.C_ANNOTATION_WIDGET)
+            if (PDFViewControl.PDFViewTool.GetToolType() == ToolType.Viewer
+                || PDFViewControl.PDFViewTool.GetToolType() == ToolType.Pan 
+                && e.annotType== C_ANNOTATION_TYPE.C_ANNOTATION_WIDGET)
             {
                 BaseWidget baseWidget = PDFViewControl.GetCacheHitTestWidget();
                 if(baseWidget == null)

+ 102 - 36
Demo/Examples/Compdfkit.Controls/Edit/ContentEditCOntrol/ContentEditControl.xaml.cs

@@ -17,7 +17,6 @@ using System.Windows.Controls.Primitives;
 using System.Windows.Forms;
 using System.Windows.Input;
 using System.Windows.Media;
-using static ComPDFKit.Tool.CPDFToolManager;
 using System.Windows.Media.Imaging;
 using ComPDFKit.Import;
 using ComPDFKit.Tool.Help;
@@ -28,6 +27,7 @@ using KeyEventHandler = System.Windows.Input.KeyEventHandler;
 using MenuItem = System.Windows.Controls.MenuItem;
 using OpenFileDialog = Microsoft.Win32.OpenFileDialog;
 using UserControl = System.Windows.Controls.UserControl;
+using System.Linq;
 
 namespace ComPDFKit.Controls.PDFControl
 {
@@ -54,7 +54,7 @@ namespace ComPDFKit.Controls.PDFControl
         private bool textAreaCreating = false;
 
         public event PropertyChangedEventHandler PropertyChanged;
-         
+
         public bool CanUndo
         {
             get
@@ -70,8 +70,9 @@ namespace ComPDFKit.Controls.PDFControl
                 }
                 catch (Exception ex)
                 {
+                    return false;
+                }
 
-                } 
                 return false;
             }
         }
@@ -91,7 +92,7 @@ namespace ComPDFKit.Controls.PDFControl
                 }
                 catch (Exception ex)
                 {
-
+                    return false;
                 }
 
                 return false;
@@ -113,7 +114,7 @@ namespace ComPDFKit.Controls.PDFControl
                 }
                 catch (Exception ex)
                 {
-
+                    return false;
                 }
 
                 return false;
@@ -156,7 +157,7 @@ namespace ComPDFKit.Controls.PDFControl
             PdfViewControl.PDFViewTool.GetCPDFViewer().SetIsShowStampMouse(false);
             PdfViewControl.PDFViewTool.SelectedEditAreaForIndex(-1, -1);
         }
-         
+
         public void SetViewSettings(Visibility visibility, CPDFDisplaySettingsControl displaySettingsControl = null)
         {
             this.PropertyContainer.Child = displaySettingsControl;
@@ -173,7 +174,7 @@ namespace ComPDFKit.Controls.PDFControl
         {
             this.displaySettingsControl = displaySettingsControl;
         }
-         
+
         public void InitWithPDFViewer(PDFViewControl view)
         {
             PdfViewControl.PDFViewTool.GetCPDFViewer().UndoManager.PropertyChanged -= UndoManager_PropertyChanged;
@@ -197,6 +198,7 @@ namespace ComPDFKit.Controls.PDFControl
                 {
                     PdfViewControl.PDFViewTool.RemoveHandler(KeyDownEvent, KeyDownHandler);
                 }
+
                 KeyDownHandler = new KeyEventHandler(PDFView_KeyDown);
                 PdfViewControl.PDFViewTool.AddHandler(KeyDownEvent, KeyDownHandler, false);
             }
@@ -204,7 +206,7 @@ namespace ComPDFKit.Controls.PDFControl
 
         private void PdfViewControl_DrawChanged(object sender, EventArgs e)
         {
-            if(textAreaCreating && PdfViewControl.PDFToolManager.GetCreateContentEditType() == CPDFEditType.EditText)
+            if (textAreaCreating && PdfViewControl.PDFToolManager.GetCreateContentEditType() == CPDFEditType.EditText)
             {
                 textAreaCreating = false;
                 int pageIndex = -1;
@@ -218,7 +220,7 @@ namespace ComPDFKit.Controls.PDFControl
                     if (editAreaArea.Type == CPDFEditType.EditText)
                     {
                         PDFEditParam pDFEditParam = ParamConverter.CPDFDataConverterToPDFEitParam(PdfViewControl.PDFToolManager.GetDocument(), editAreaArea, pageIndex);
-                        pdfContentEditControl.SetPDFTextEditData((TextEditParam)pDFEditParam, true);
+                        pdfContentEditControl.SetPDFTextEditData(new List<TextEditParam> { (TextEditParam)pDFEditParam }, true);
                         PropertyContainer.Child = pdfContentEditControl;
                     }
                 }
@@ -234,6 +236,16 @@ namespace ComPDFKit.Controls.PDFControl
             {
                 return;
             }
+
+            if (e.Key == Key.LeftShift || e.Key == Key.RightShift)
+            {
+                PdfViewControl.PDFViewTool.SetMultiSelectKey(e.Key);
+            }
+            else if (e.Key == Key.LeftCtrl || e.Key == Key.RightCtrl)
+            {
+                PdfViewControl.PDFViewTool.SetMultiSelectKey(e.Key);
+            }
+
             int pageIndex = -1;
             CPDFEditTextArea textArea = PdfViewControl.PDFToolManager.GetSelectedEditAreaObject(ref pageIndex) as CPDFEditTextArea;
             if (textArea == null)
@@ -335,31 +347,34 @@ namespace ComPDFKit.Controls.PDFControl
 
             if (Keyboard.Modifiers == ModifierKeys.None)
             {
-                var oldFrame = textArea.GetFrame();
+                CRect textFrame = textArea.GetFrame();
                 if (e.Key == Key.Left)
                 {
-                    oldFrame.left -= 5;
+                    textFrame.left -= 5;
+                    textArea.SetFrame(textFrame);
                     e.Handled = true;
                 }
 
                 if (e.Key == Key.Right)
                 {
-                    oldFrame.left += 5;
+                    textFrame.left += 5;
+                    textArea.SetFrame(textFrame);
                     e.Handled = true;
                 }
 
                 if (e.Key == Key.Up)
                 {
-                    oldFrame.top -= 5;
+                    textFrame.top -= 5;
+                    textArea.SetFrame(textFrame);
                     e.Handled = true;
                 }
 
                 if (e.Key == Key.Down)
                 {
-                    oldFrame.top += 5;
+                    textFrame.top += 5;
+                    textArea.SetFrame(textFrame);
                     e.Handled = true;
                 }
-                textArea.SetFrame(oldFrame);
             }
 
             if (Keyboard.Modifiers == (ModifierKeys.Control | ModifierKeys.Shift))
@@ -369,6 +384,7 @@ namespace ComPDFKit.Controls.PDFControl
                     startPoint = GetPoint(textArea);
                     isUpdateStartPoint = false;
                 }
+
                 if (e.Key == Key.Left)
                 {
                     textArea.GetPreWordCharPlace();
@@ -431,7 +447,7 @@ namespace ComPDFKit.Controls.PDFControl
             PropertyContainer.Child = propertytPanel;
             PropertyContainer.Visibility = visible;
         }
-         
+
         private void PanelState_PropertyChanged(object sender, PropertyChangedEventArgs e)
         {
             if (e.PropertyName == nameof(PanelState.IsLeftPanelExpand))
@@ -475,15 +491,13 @@ namespace ComPDFKit.Controls.PDFControl
                     textEditParam.EditIndex = -1;
                     textEditParam.TextAlign = TextAlignType.AlignLeft;
                     textEditParam.Transparency = 255;
-                    pdfContentEditControl.SetPDFTextEditData(textEditParam);
+                    pdfContentEditControl.SetPDFTextEditData(new List<TextEditParam> { textEditParam });
                     DefaultSettingParam defaultSettingParam = PdfViewControl.PDFViewTool.GetDefaultSettingParam();
                     defaultSettingParam.SetPDFEditParamm(textEditParam);
                     panelState.RightPanel = PanelState.RightPanelState.PropertyPanel;
                     PdfViewControl.PDFToolManager.SetCreateContentEditType(CPDFEditType.EditText);
                     PdfViewControl.PDFViewTool.SetCurrentEditType(CPDFEditType.EditText);
                 }
-
-                PdfViewControl.PDFViewTool.GetCPDFViewer().UpdateRenderFrame();
             }
 
         }
@@ -494,7 +508,6 @@ namespace ComPDFKit.Controls.PDFControl
             if (senderBtn != null && PdfViewControl != null)
             {
                 ClearPDFEditState(senderBtn);
-                PdfViewControl.PDFViewTool.GetCPDFViewer().UpdateRenderFrame();
                 panelState.RightPanel = PanelState.RightPanelState.None;
                 senderBtn.IsChecked = false;
                 OpenFileDialog openFileDialog = new OpenFileDialog();
@@ -556,7 +569,7 @@ namespace ComPDFKit.Controls.PDFControl
             {
                 if (PdfViewControl.PDFToolManager.GetCreateContentEditType() == CPDFEditType.EditText)
                 {
-                    pdfContentEditControl.SetPDFTextEditData(pdfTextCreateParam);
+                    pdfContentEditControl.SetPDFTextEditData(new List<TextEditParam> { pdfTextCreateParam });
                 }
                 else if (PdfViewControl.PDFToolManager.GetCreateContentEditType() == CPDFEditType.None)
                 {
@@ -613,6 +626,19 @@ namespace ComPDFKit.Controls.PDFControl
                 case MouseHitTestType.ImageEdit:
                     CreateImageEditMenu(sender, ref ContextMenu);
                     break;
+                case MouseHitTestType.Unknown:
+                    List<int> pageInts = new List<int>();
+                    List<CPDFEditArea> editAreas = PdfViewControl.PDFToolManager.GetSelectedEditAreaListObject(ref pageInts);
+                    if (editAreas.Count > 0)
+                    {
+                        CreateMultiTextEditMenu(sender, ref ContextMenu);
+                    }
+                    else
+                    {
+                        ContextMenu.Items.Add(new MenuItem() { Header = LanguageHelper.CommonManager.GetString("Menu_Paste"), Command = ApplicationCommands.Paste, CommandTarget = (UIElement)sender });
+                        ContextMenu.Items.Add(new MenuItem() { Header = LanguageHelper.CommonManager.GetString("Menu_MatchPaste"), Command = CustomCommands.PasteWithoutStyle, CommandTarget = (UIElement)sender });
+                    }
+                    break;
                 default:
                     ContextMenu.Items.Add(new MenuItem() { Header = LanguageHelper.CommonManager.GetString("Menu_Paste"), Command = ApplicationCommands.Paste, CommandTarget = (UIElement)sender });
                     ContextMenu.Items.Add(new MenuItem() { Header = LanguageHelper.CommonManager.GetString("Menu_MatchPaste"), Command = CustomCommands.PasteWithoutStyle, CommandTarget = (UIElement)sender });
@@ -621,7 +647,7 @@ namespace ComPDFKit.Controls.PDFControl
             PdfViewControl.SetRightMenu(ContextMenu);
         }
         #endregion
-        
+
         #region Property changed
         protected void OnPropertyChanged([CallerMemberName] string name = null)
         {
@@ -683,27 +709,54 @@ namespace ComPDFKit.Controls.PDFControl
                     PdfViewControl.PDFToolManager.SetCreateContentEditType(CPDFEditType.None);
                 }
 
-                if(PdfViewControl.PDFToolManager.GetCreateContentEditType() == CPDFEditType.EditText)
+                if (PdfViewControl.PDFToolManager.GetCreateContentEditType() == CPDFEditType.EditText)
                 {
                     textAreaCreating = true;
                 }
             }
 
             int pageIndex = -1;
-            CPDFEditArea editAreaArea = PdfViewControl.PDFToolManager.GetSelectedEditAreaObject(ref pageIndex);
-            if (editAreaArea == null)
+            CPDFEditArea editArea = PdfViewControl.PDFToolManager.GetSelectedEditAreaObject(ref pageIndex);
+            List<int> pageInts = new List<int>();
+            List<CPDFEditArea> editAreas = PdfViewControl.PDFToolManager.GetSelectedEditAreaListObject(ref pageInts);
+
+            if (editArea != null)
             {
-                return;
+                if (editArea.Type == CPDFEditType.EditText)
+                {
+                    PDFEditParam editParam = ParamConverter.CPDFDataConverterToPDFEitParam(PdfViewControl.PDFToolManager.GetDocument(), editArea, pageIndex);
+                    pdfContentEditControl.SetPDFTextEditData(new List<TextEditParam> { (TextEditParam)editParam }, true);
+                    PropertyContainer.Child = pdfContentEditControl;
+                }
             }
-            else
+            else if (editAreas != null && editAreas.Count != 0)
             {
-                if (editAreaArea.Type == CPDFEditType.EditText)
+                List<CPDFEditTextArea> editTextAreas = editAreas.OfType<CPDFEditTextArea>().ToList();
+                editTextAreas.ForEach(textArea => textArea.SelectAllChars());
+                if (editAreas.Count == editTextAreas.Count)
                 {
-                    PDFEditParam pDFEditParam = ParamConverter.CPDFDataConverterToPDFEitParam(PdfViewControl.PDFToolManager.GetDocument(), editAreaArea, pageIndex);
-                    pdfContentEditControl.SetPDFTextEditData((TextEditParam)pDFEditParam, true);
+                    List<TextEditParam> editParams = editTextAreas.
+                        Select(area => ParamConverter.CPDFDataConverterToPDFEitParam(PdfViewControl.PDFToolManager.GetDocument(), area, pageInts.FirstOrDefault())).
+                        Cast<TextEditParam>().ToList();
+                    pdfContentEditControl.SetPDFTextEditData(editParams, true);
+                    PropertyContainer.Child = pdfContentEditControl;
+                }
+                else if (editTextAreas.Count == 0)
+                {
+                    List<ImageEditParam> editParams = editAreas.
+                        Select(area => ParamConverter.CPDFDataConverterToPDFEitParam(PdfViewControl.PDFToolManager.GetDocument(), area, pageInts.FirstOrDefault())).
+                        Cast<ImageEditParam>().ToList();
+                    pdfContentEditControl.SetPDFImageEditData(editParams);
                     PropertyContainer.Child = pdfContentEditControl;
                 }
-                //panelState.RightPanel = PanelState.RightPanelState.PropertyPanel;
+                else
+                {
+                    pdfContentEditControl.ClearContentControl();
+                }
+            }
+            else
+            {
+                return;
             }
         }
 
@@ -722,7 +775,7 @@ namespace ComPDFKit.Controls.PDFControl
             {
                 if (PdfViewControl.PDFToolManager.GetCreateContentEditType() != CPDFEditType.EditText)
                 {
-                    pdfContentEditControl.ClearContentControl(); 
+                    pdfContentEditControl.ClearContentControl();
                 }
                 return;
             }
@@ -731,7 +784,7 @@ namespace ComPDFKit.Controls.PDFControl
                 if (editAreaArea.Type == CPDFEditType.EditText)
                 {
                     PDFEditParam pDFEditParam = ParamConverter.CPDFDataConverterToPDFEitParam(PdfViewControl.PDFToolManager.GetDocument(), editAreaArea, pageIndex);
-                    pdfContentEditControl.SetPDFTextEditData((TextEditParam)pDFEditParam, true);
+                    pdfContentEditControl.SetPDFTextEditData(new List<TextEditParam> { (TextEditParam)pDFEditParam }, true);
                     PropertyContainer.Child = pdfContentEditControl;
                 }
 
@@ -744,9 +797,14 @@ namespace ComPDFKit.Controls.PDFControl
                         pageView.MouseLeftButtonUp += PageView_MouseLeftButtonUp;
                     }
                     PDFEditParam pDFEditParam = ParamConverter.CPDFDataConverterToPDFEitParam(PdfViewControl.PDFToolManager.GetDocument(), editAreaArea, pageIndex);
-                    pdfContentEditControl.SetPDFImageEditData((ImageEditParam)pDFEditParam);
+                    pdfContentEditControl.SetPDFImageEditData(new List<ImageEditParam> { (ImageEditParam)pDFEditParam });
                     PropertyContainer.Child = pdfContentEditControl;
-                } 
+                }
+
+                else
+                {
+
+                }
             }
         }
 
@@ -765,7 +823,7 @@ namespace ComPDFKit.Controls.PDFControl
             }
             if (imageAreaParam != null)
             {
-                pdfContentEditControl.SetPDFImageEditData((ImageEditParam)imageAreaParam);
+                pdfContentEditControl.SetPDFImageEditData(new List<ImageEditParam> { (ImageEditParam)imageAreaParam });
             }
         }
 
@@ -966,6 +1024,14 @@ namespace ComPDFKit.Controls.PDFControl
             menu.Items.Add(new MenuItem() { Header = LanguageHelper.CommonManager.GetString("Menu_Delete"), Command = ApplicationCommands.Delete, CommandTarget = (UIElement)sender });
             menu.Items.Add(new MenuItem() { Header = LanguageHelper.CommonManager.GetString("Menu_Paste"), Command = ApplicationCommands.Paste, CommandTarget = (UIElement)sender });
         }
+
+        private void CreateMultiTextEditMenu(object sender, ref ContextMenu menu)
+        {
+            menu.Items.Add(new MenuItem() { Header = LanguageHelper.CommonManager.GetString("Menu_Copy"), Command = ApplicationCommands.Copy, CommandTarget = (UIElement)sender });
+            menu.Items.Add(new MenuItem() { Header = LanguageHelper.CommonManager.GetString("Menu_Cut"), Command = ApplicationCommands.Cut, CommandTarget = (UIElement)sender });
+            menu.Items.Add(new MenuItem() { Header = LanguageHelper.CommonManager.GetString("Menu_Delete"), Command = ApplicationCommands.Delete, CommandTarget = (UIElement)sender });
+            menu.Items.Add(new MenuItem() { Header = LanguageHelper.CommonManager.GetString("Menu_Paste"), Command = ApplicationCommands.Paste, CommandTarget = (UIElement)sender });
+        }
     }
 }
 #endregion

+ 4 - 2
Demo/Examples/Compdfkit.Controls/Edit/PDFContentEditControl.xaml.cs

@@ -1,6 +1,7 @@
 using ComPDFKit.Tool;
 using ComPDFKit.Controls.PDFControl;
 using System.Windows.Controls;
+using System.Collections.Generic;
 
 namespace ComPDFKit.Controls.Edit
 {
@@ -32,7 +33,7 @@ namespace ComPDFKit.Controls.Edit
             PDFImageEditControl.SetRotationText(rotation);
         }
 
-        public void SetPDFTextEditData(TextEditParam editEvent, bool isTemp = false)
+        public void SetPDFTextEditData(List<TextEditParam> editEvent, bool isTemp = false)
         {
             if (!isTemp)
             {
@@ -59,12 +60,13 @@ namespace ComPDFKit.Controls.Edit
             ContentEditContainer.Child = null;
         }
 
-        public void SetPDFImageEditData(ImageEditParam editEvent)
+        public void SetPDFImageEditData(List<ImageEditParam> editEvent)
         {
             PDFImageEditControl.SetPDFImageEditData(editEvent);
             ContentEditContainer.Child = PDFImageEditControl;
         }
 
+
         //public void SetPDFImageMultiEditData(List<PDFEditEvent> editEventList)
         //{
         //    PDFImageEditControl.SetPDFImageMultiEditData(editEventList);

+ 90 - 96
Demo/Examples/Compdfkit.Controls/Edit/PDFImageEdit/PDFImageEditControl/PDFImageEditControl.xaml

@@ -6,7 +6,7 @@
              xmlns:local="clr-namespace:ComPDFKit.Controls.Edit"
              xmlns:common="clr-namespace:ComPDFKit.Controls.Common"
              mc:Ignorable="d" 
-             d:DesignHeight="480" d:DesignWidth="800" MinWidth="260" Padding="10"
+             d:DesignHeight="720" d:DesignWidth="280" MinWidth="260" Padding="10"
              Background="#FAFCFF">
     <UserControl.Resources>
         <ResourceDictionary>
@@ -18,48 +18,41 @@
             <common:CommonResourceConverter x:Key="CommonResourceConverter" />
         </ResourceDictionary>
     </UserControl.Resources>
-    
-    <Grid>
-        <Grid.RowDefinitions>
-            <RowDefinition Height="auto"></RowDefinition>
-            <RowDefinition Height="auto"></RowDefinition>
-            <RowDefinition Height="auto"></RowDefinition>
-            <RowDefinition Height="auto"></RowDefinition>
-            <RowDefinition Height="auto"></RowDefinition>
-            <RowDefinition Height="auto"></RowDefinition>
-        </Grid.RowDefinitions>
+    <ScrollViewer VerticalScrollBarVisibility="Auto">
 
-        <Border Background="White" Height="36">
-            <TextBlock FontSize="14" FontWeight="Bold" HorizontalAlignment="Center" Foreground="#42464D" VerticalAlignment="Center" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_ImageProperty}"></TextBlock>
-        </Border>
+        <StackPanel>
 
-        <Border Name="ImageThumbBorder" Background="White" Grid.Row="1" MinHeight="100" CornerRadius="5" Margin="0,16,0,0" BorderThickness="1" BorderBrush="#E2E3E6">
-            <Image Name="ImageThumbUI" MaxHeight="80" MaxWidth="230" Stretch="Uniform"></Image>
-        </Border>
-         
-        <StackPanel Grid.Row="2"  Margin="0,33,0,0" >
-            <local:CPDFImageRotateUI x:Name="RotateUI" FontSize="16"></local:CPDFImageRotateUI>
-            <Grid Margin="0,10,0,0">
-                <TextBlock Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Rotation}" FontFamily="Microsoft YaHei" FontSize="14" HorizontalAlignment="Left" VerticalAlignment="Center"></TextBlock>
-                <TextBox Padding="5,0,5,0" x:Name="RotationTxb" HorizontalAlignment="Right" VerticalContentAlignment="Center" Width="110" Height="32" LostFocus="RotationTxb_LostFocus" PreviewKeyDown="RotationTxb_PreviewKeyDown"></TextBox>
-            </Grid>
-        </StackPanel>
-        
-        <local:CPDFImageFlipUI x:Name="FlipUI" Grid.Row="3" FontSize="16" Margin="0,10,0,0"></local:CPDFImageFlipUI>
-         
-        <Grid Grid.Row="4" Margin="0,20,0,0">
-            <Grid.ColumnDefinitions>
-                <ColumnDefinition Width="*"></ColumnDefinition>
-                <ColumnDefinition Width="auto"></ColumnDefinition>
-            </Grid.ColumnDefinitions>
-            <Grid.RowDefinitions>
-                <RowDefinition Height="auto"></RowDefinition>
-                <RowDefinition Height="auto"></RowDefinition>
-            </Grid.RowDefinitions>
+            <Border Background="White" Height="36">
+                <TextBlock FontSize="14" FontWeight="Bold" HorizontalAlignment="Center" Foreground="#42464D" VerticalAlignment="Center" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_ImageProperty}"></TextBlock>
+            </Border>
+
+            <Border Name="ImageThumbBorder" Background="White" Grid.Row="1" MinHeight="100" CornerRadius="5" Margin="0,16,0,0" BorderThickness="1" BorderBrush="#E2E3E6" Visibility="{Binding OnlySingleVisible}">
+                <Image Name="ImageThumbUI" MaxHeight="80" MaxWidth="230" Stretch="Uniform"></Image>
+            </Border>
+
+            <StackPanel Grid.Row="2"  >
+                <local:CPDFImageRotateUI x:Name="RotateUI" FontSize="16"></local:CPDFImageRotateUI>
+                <Grid Margin="0,10,0,0">
+                    <TextBlock Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Rotation}" FontFamily="Microsoft YaHei" FontSize="14" HorizontalAlignment="Left" VerticalAlignment="Center"></TextBlock>
+                    <TextBox Padding="5,0,5,0" x:Name="RotationTxb" HorizontalAlignment="Right" VerticalContentAlignment="Center" Width="110" Height="32" LostFocus="RotationTxb_LostFocus" PreviewKeyDown="RotationTxb_PreviewKeyDown"></TextBox>
+                </Grid>
+            </StackPanel>
+
+            <local:CPDFImageFlipUI x:Name="FlipUI" Grid.Row="3" FontSize="16" Margin="0,10,0,0"></local:CPDFImageFlipUI>
+
+            <Grid Grid.Row="4" Margin="0,20,0,0">
+                <Grid.ColumnDefinitions>
+                    <ColumnDefinition Width="*"></ColumnDefinition>
+                    <ColumnDefinition Width="auto"></ColumnDefinition>
+                </Grid.ColumnDefinitions>
+                <Grid.RowDefinitions>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
+                </Grid.RowDefinitions>
 
-            <TextBlock FontSize="14" Foreground="#43474D" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Opacity}"></TextBlock>
+                <TextBlock FontSize="14" Foreground="#43474D" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Opacity}"></TextBlock>
 
-            <Slider Style="{StaticResource SliderStyle}" Grid.Row="1" Width="148" Height="28"
+                <Slider Style="{StaticResource SliderStyle}" Grid.Row="1" Width="148" Height="28"
                     Name="ImasgeOpacitySlider" 
                     Value="14"  
                     IsSelectionRangeEnabled="True" 
@@ -75,81 +68,82 @@
                     Tag="true"
                     />
 
-            <Grid Grid.Row="1" Grid.Column="1" Margin="0,10,0,0">
-                <ComboBox Name="OpacityComboBox" VerticalContentAlignment="Center" Width="72" Height="28" Foreground="#43474D" FontSize="14"
+                <Grid Grid.Row="1" Grid.Column="1" Margin="0,10,0,0">
+                    <ComboBox Name="OpacityComboBox" VerticalContentAlignment="Center" Width="72" Height="28" Foreground="#43474D" FontSize="14"
                               SelectionChanged="OpacityComboBox_SelectionChanged" BorderBrush="#1E000000">
-                    <ComboBoxItem>25%</ComboBoxItem>
-                    <ComboBoxItem>50%</ComboBoxItem>
-                    <ComboBoxItem>75%</ComboBoxItem>
-                    <ComboBoxItem>100%</ComboBoxItem>
-                </ComboBox>
-                <TextBox Name="OpacityTextBox" IsHitTestVisible="False" Width="72" Height="30" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"
+                        <ComboBoxItem>25%</ComboBoxItem>
+                        <ComboBoxItem>50%</ComboBoxItem>
+                        <ComboBoxItem>75%</ComboBoxItem>
+                        <ComboBoxItem>100%</ComboBoxItem>
+                    </ComboBox>
+                    <TextBox Name="OpacityTextBox" IsHitTestVisible="False" Width="72" Height="30" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"
                              IsReadOnly="True" Background="White" Padding="0,0,15,0" FontSize="14">100%</TextBox>
-                <Path Fill="#43474D" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,5,0" IsHitTestVisible="False">
-                    <Path.Data>
-                        M0.5 0.510248L4.5041 5.5L8.5 0.5L0.5 0.510248Z
-                    </Path.Data>
-                </Path>
+                    <Path Fill="#43474D" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,5,0" IsHitTestVisible="False">
+                        <Path.Data>
+                            M0.5 0.510248L4.5041 5.5L8.5 0.5L0.5 0.510248Z
+                        </Path.Data>
+                    </Path>
+                </Grid>
             </Grid>
-        </Grid>
-    
-        <Grid Grid.Row="5" Margin="0,20,0,0">
-            <Grid.RowDefinitions>
-                <RowDefinition Height="auto"></RowDefinition>
-                <RowDefinition Height="auto"></RowDefinition>
-            </Grid.RowDefinitions>
-            <TextBlock VerticalAlignment="Center" FontSize="14" Foreground="#43474D" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Tool}"></TextBlock>
 
-            <Border  Grid.Row="1" BorderThickness="1" BorderBrush="#E1E3E5"  Margin="0,14,0,0" HorizontalAlignment="Left">
-                <StackPanel Orientation="Horizontal">
-                    <Button Name="ImageReplaceBtn" Width="40" Height="25" BorderThickness="0" Click="ImageReplaceBtn_Click" Background="White" Style="{StaticResource LightButtonStyle}"
+            <Grid  Margin="0,20,0,0" Visibility="{Binding OnlySingleVisible}">
+                <Grid.RowDefinitions>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
+                </Grid.RowDefinitions>
+                <TextBlock VerticalAlignment="Center" FontSize="14" Foreground="#43474D" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Tool}"></TextBlock>
+
+                <Border  Grid.Row="1" BorderThickness="1" BorderBrush="#E1E3E5"  Margin="0,14,0,0" HorizontalAlignment="Left">
+                    <StackPanel Orientation="Horizontal">
+                        <Button Name="ImageReplaceBtn" Width="40" Height="25" BorderThickness="0" Click="ImageReplaceBtn_Click" Background="White" Style="{StaticResource LightButtonStyle}"
                             ToolTip="{Binding Converter={StaticResource CommonResourceConverter},ConverterParameter=Menu_Replace}">
-                        <Button.Content>
-                            <Path Fill="#43474D">
-                                <Path.Data>
-                                    M1.12988 1.88037H0.379883V2.63037V14.3971V15.1471H1.12988H4.47057V16.2589V17.7589H5.97057H11.9871V16.915L11.9995 16L8.64639 
+                            <Button.Content>
+                                <Path Fill="#43474D">
+                                    <Path.Data>
+                                        M1.12988 1.88037H0.379883V2.63037V14.3971V15.1471H1.12988H4.47057V16.2589V17.7589H5.97057H11.9871V16.915L11.9995 16L8.64639 
                                 14.3971L5.97057 15.9838V7.49225H18.0035V12.7161H19.5035V7.49225V5.99225H18.0035H16.9129V2.63037V1.88037H16.1629H1.12988ZM15.4129 
                                 5.99225V3.38037H1.87988V13.6471H4.47057V7.49225V5.99225H5.97057H15.4129ZM14.6574 10.5265C15.2097 10.5265 15.6574 10.0759 15.6574 
                                 9.5201C15.6574 8.9643 15.2097 8.51373 14.6574 8.51373C14.1051 8.51373 13.6574 8.9643 13.6574 9.5201C13.6574 10.0759 14.1051 10.5265 
                                 14.6574 10.5265ZM15.3635 12.4771L14.8863 11.8985L16.0436 10.9442L16.5208 11.5229L17.9828 13.2959L18.9947 
                                 14.5231H17.4042H12.9994H12.2494V13.0231H12.9994H15.8136L15.3635 12.4771ZM15.8007 17.2959L16.2779 17.8746L15.1206 18.8289L14.6434 
                                 18.2502L13.1814 16.4771L12.1695 15.25H13.76H18.1648H18.9148V16.75H18.1648H15.3506L15.8007 17.2959Z
-                                </Path.Data>
-                            </Path>
-                        </Button.Content>
-                    </Button>
- 
-                    <Button Grid.Column="1" Width="40" Height="25" BorderThickness="0" Click="ImageExportBtn_Click" Background="White" Style="{StaticResource LightButtonStyle}"
+                                    </Path.Data>
+                                </Path>
+                            </Button.Content>
+                        </Button>
+
+                        <Button Grid.Column="1" Width="40" Height="25" BorderThickness="0" Click="ImageExportBtn_Click" Background="White" Style="{StaticResource LightButtonStyle}"
                             ToolTip="{Binding Converter={StaticResource CommonResourceConverter},ConverterParameter=Menu_Export}">
-                        <Button.Content>
-                            <Path Fill="#43474D">
-                                <Path.Data>
-                                    M12.3597 7.35973L8.75 10.9694L8.75 1V0.25H7.25V1L7.25 10.9694L3.6403 7.35973L3.10997 6.8294L2.04931 7.89006L2.57964 8.42039L7.46967 
+                            <Button.Content>
+                                <Path Fill="#43474D">
+                                    <Path.Data>
+                                        M12.3597 7.35973L8.75 10.9694L8.75 1V0.25H7.25V1L7.25 10.9694L3.6403 7.35973L3.10997 6.8294L2.04931 7.89006L2.57964 8.42039L7.46967 
                                     13.3104C7.76256 13.6033 8.23744 13.6033 8.53033 13.3104L13.4204 8.42039L13.9507 7.89006L12.89 6.8294L12.3597 7.35973ZM1 
                                     15.1538H0.25V16.6538H1H15.3077H16.0577V15.1538H15.3077H1Z
-                                </Path.Data>
-                            </Path>
-                        </Button.Content>
-                    </Button>
+                                    </Path.Data>
+                                </Path>
+                            </Button.Content>
+                        </Button>
 
-                    <Button Name="ImageClipBtn" Grid.Column="1" Width="40" Height="25" BorderThickness="0" Click="ImageClipBtn_Click" Background="White" Style="{StaticResource LightButtonStyle}"
+                        <Button Name="ImageClipBtn" Grid.Column="1" Width="40" Height="25" BorderThickness="0" Click="ImageClipBtn_Click" Background="White" Style="{StaticResource LightButtonStyle}"
                             ToolTip="{Binding Converter={StaticResource CommonResourceConverter},ConverterParameter=Menu_Crop}">
-                        <Button.Content>
-                            <Path Fill="#43474D">
-                                <Path.Data>
-                                    M4.75 15.75V4.25H14.4074L13.9517 4.73826L15.0483 5.76174L15.25 5.54562V15.75H4.75ZM3.25 
+                            <Button.Content>
+                                <Path Fill="#43474D">
+                                    <Path.Data>
+                                        M4.75 15.75V4.25H14.4074L13.9517 4.73826L15.0483 5.76174L15.25 5.54562V15.75H4.75ZM3.25 
                                 16.5V4.25H0V2.75H3.25V0.5H4.75V2.75H16H16.75V3.5V15.75H20V17.25H16.75V19.5H15.25V17.25H4H3.25V16.5ZM17.8483 2.76174L18.5483 
                                 2.01174L17.4517 0.988261L16.7517 1.73826L17.8483 2.76174ZM12.2483 8.76174L13.6483 7.26174L12.5517 6.23826L11.1517 7.73826L12.2483 
                                 8.76174ZM9.44829 11.7617L10.8483 10.2617L9.75171 9.23826L8.35171 10.7383L9.44829 11.7617ZM6.64829 14.7617L8.04829 13.2617L6.95171 
                                 12.2383L5.55171 13.7383L6.64829 14.7617Z
-                                </Path.Data>
-                            </Path>
-                        </Button.Content>
-                    </Button>
-                </StackPanel>
-            </Border>
-          
-        </Grid>
-     
-    </Grid>
+                                    </Path.Data>
+                                </Path>
+                            </Button.Content>
+                        </Button>
+                    </StackPanel>
+                </Border>
+
+            </Grid>
+
+        </StackPanel>
+    </ScrollViewer>
 </UserControl>

+ 267 - 140
Demo/Examples/Compdfkit.Controls/Edit/PDFImageEdit/PDFImageEditControl/PDFImageEditControl.xaml.cs

@@ -17,25 +17,35 @@ using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Controls.Primitives;
 using System.Windows.Input;
-using System.Windows.Media;
 using System.Windows.Media.Imaging;
 using ComPDFKit.Tool.DrawTool;
 using ComPDFKitViewer.Helper;
 using ComPDFKit.Tool.Help;
+using System.Linq;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
 
 namespace ComPDFKit.Controls.Edit
 {
-    public partial class PDFImageEditControl : UserControl
+    public partial class PDFImageEditControl : UserControl, INotifyPropertyChanged
     {
         #region property
         public CPDFViewerTool ToolView { get; set; }
-        public ImageEditParam EditEvent { get; set; }
+        public List<ImageEditParam> EditEvents { get; set; } = new List<ImageEditParam>();
+
+        private Visibility _onlySingleVisible = Visibility.Collapsed;
+        public Visibility OnlySingleVisible
+        {
+            get => _onlySingleVisible;
+            set => UpdateProper(ref  _onlySingleVisible, value);
+        }
 
         //public List<PDFEditEvent> EditMultiEvents { get; set; }
         #endregion 
 
         public PDFImageEditControl()
         {
+            DataContext = this;
             InitializeComponent();
             Loaded += PDFImageEditControl_Loaded;
             Unloaded += PDFImageEditControl_Unloaded;
@@ -57,7 +67,7 @@ namespace ComPDFKit.Controls.Edit
         {
             RotateUI.RotationChanged -= RotateUI_RotationChanged;
             FlipUI.FlipChanged -= FlipUI_FlipChanged;
-        } 
+        }
 
         #endregion
 
@@ -66,24 +76,33 @@ namespace ComPDFKit.Controls.Edit
         {
             if (ToolView.GetIsCropMode())
             {
-                GetImageArea(out CPDFEditImageArea imageArea, out CPDFPage pdfPage, out CPDFEditPage editPage);
-                SelectedRect selectedRect = ToolView.GetSelectedRectForEditAreaObject(imageArea);
-                if (selectedRect != null)
+                GetImageArea(out List<CPDFEditImageArea> imageAreas, out CPDFPage pdfPage, out CPDFEditPage editPage);
+                if (imageAreas.Count == 0 || pdfPage == null || editPage == null)
+                    return;
+
+                SelectedRect selectedRect = ToolView.GetSelectedRectForEditAreaObject(imageAreas[0]);
+                if (selectedRect == null)
+                    return;
+
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(imageAreas[0].GetFrame());
+                double currentZoom = ToolView.GetCPDFViewer().CurrentRenderFrame.ZoomFactor;
+                Rect rect = selectedRect.GetRect();
+                Rect maxRect = selectedRect.GetMaxRect();
+                Rect pdfRect = new Rect((rect.X - maxRect.X) / currentZoom, (rect.Y - maxRect.Y) / currentZoom, rect.Width / currentZoom, rect.Height / currentZoom);
+                pdfRect = DpiHelper.StandardRectToPDFRect(pdfRect);
+                CRect newCRect = new CRect((float)pdfRect.Left, (float)pdfRect.Bottom, (float)pdfRect.Right, (float)pdfRect.Top);
+                if(imageAreas[0].CutWithRect(newCRect))
                 {
-                    Rect oldRect = DataConversionForWPF.CRectConversionForRect(imageArea.GetFrame());
-                    double currentZoom = ToolView.GetCPDFViewer().CurrentRenderFrame.ZoomFactor;
-                    Rect rect = selectedRect.GetRect();
-                    Rect maxRect = selectedRect.GetMaxRect();
-
-                    Rect pdfRect = new Rect((rect.X - maxRect.X) / currentZoom, (rect.Y - maxRect.Y) / currentZoom, rect.Width / currentZoom, rect.Height / currentZoom);
-                    pdfRect = DpiHelper.StandardRectToPDFRect(pdfRect);
-                    CRect newCRect = new CRect((float)pdfRect.Left, (float)pdfRect.Bottom, (float)pdfRect.Right, (float)pdfRect.Top);
-                    imageArea.CutWithRect(newCRect);
-
-                    SetImageThumb();
-                    ToolView.UpdateRender(oldRect, imageArea);
-                    editPage.EndEdit();
-                }
+                    PDFEditHistory editHistory = new PDFEditHistory();
+                    editHistory.EditPage = editPage;
+                    editHistory.PageIndex = pdfPage.PageIndex;
+
+                    ToolView.GetCPDFViewer().UndoManager.AddHistory(editHistory);
+                    ToolView.UpdateRender(oldRect, imageAreas[0]);
+                 }
+
+                editPage.EndEdit();
+                SetImageThumb();
             }
         }
 
@@ -110,16 +129,16 @@ namespace ComPDFKit.Controls.Edit
 
         public void SetImageThumb()
         {
-            if (EditEvent != null)
+            if (EditEvents.Count == 1)
             {
                 try
                 {
-                    GetImageArea(out CPDFEditImageArea imageArea, out CPDFPage pdfPage, out CPDFEditPage editPage);
+                    GetImageArea(out List<CPDFEditImageArea> imageAreas, out CPDFPage pdfPage, out CPDFEditPage editPage);
 
                     string path = Path.GetTempPath();
                     string uuid = Guid.NewGuid().ToString("N");
                     string imagePath = Path.Combine(path, uuid + ".tmp");
-                    imageArea.ExtractImage(imagePath);
+                    imageAreas.FirstOrDefault().ExtractImage(imagePath);
 
                     Bitmap bitmapImage = new Bitmap(imagePath);
                     MemoryStream memoryStream = new MemoryStream();
@@ -144,31 +163,33 @@ namespace ComPDFKit.Controls.Edit
             OpacityTextBox.Text = string.Format("{0}%", (int)(Math.Round(ImasgeOpacitySlider.Value * 100)));
         }
 
-        public void SetPDFImageEditData(ImageEditParam newEvent)
+        public void SetPDFImageEditData(List<ImageEditParam> newEvents)
         {
-            if (newEvent.EditIndex < 0)
+
+            EditEvents = newEvents.Where(newEvent => newEvent.EditIndex >= 0 && newEvent.EditType == CPDFEditType.EditImage).ToList();
+
+            if (EditEvents.Count > 0)
             {
-                EditEvent = null;
+                SetImageTransparency(EditEvents.FirstOrDefault().Transparency);
             }
-            else
+
+            if (RotationTxb != null && EditEvents.Count > 0)
             {
-                EditEvent = newEvent;
+                GetImageArea(out List<CPDFEditImageArea> imageAreas, out CPDFPage pdfPage, out CPDFEditPage editPage);
+                RotationTxb.Text = imageAreas?.FirstOrDefault()?.GetRotation().ToString();
             }
-            if (newEvent != null && newEvent.EditType == CPDFEditType.EditImage)
+
+            if (EditEvents.Count == 1)
             {
-                SetImageTransparency(newEvent.Transparency);
+                OnlySingleVisible = Visibility.Visible;
+                SetImageThumb();
             }
-
-            if (RotationTxb != null && newEvent != null && newEvent.EditType == CPDFEditType.EditImage)
+            else
             {
-                GetImageArea(out CPDFEditImageArea imageArea, out CPDFPage pdfPage, out CPDFEditPage editPage);
-                RotationTxb.Text = imageArea?.GetRotation().ToString();
-                //RotationTxb.Text = newEvent.Rotate.ToString(CultureInfo.CurrentCulture);
+                OnlySingleVisible = Visibility.Collapsed;
             }
-
-            EditEvent = newEvent;
-            SetImageThumb();
         }
+
         #endregion
 
         //public void SetPDFImageMultiEditData(List<PDFEditEvent> editEvents)
@@ -213,36 +234,64 @@ namespace ComPDFKit.Controls.Edit
 
         private void FlipUI_FlipChanged(object sender, bool e)
         {
-            GetImageArea(out CPDFEditImageArea imageArea, out CPDFPage pdfPage, out CPDFEditPage editPage);
-            if (imageArea != null)
+            GetImageArea(out List<CPDFEditImageArea> imageAreas, out CPDFPage pdfPage, out CPDFEditPage editPage);
+            if (imageAreas.Count == 0 || pdfPage == null || editPage == null)
+                return;
+
+            if(ToolView.CurrentEditAreaObject() != null)
             {
-                Rect oldRect = DataConversionForWPF.CRectConversionForRect(imageArea.GetFrame());
-                bool result = false;
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(imageAreas[0].GetFrame());
+                bool result;
                 if (e)
                 {
-                    result = imageArea.VerticalMirror();
+                    result = imageAreas[0].VerticalMirror();
                 }
                 else
                 {
-                    result = imageArea.HorizontalMirror();
+                    result = imageAreas[0].HorizontalMirror();
                 }
+
                 if (result)
                 {
                     PDFEditHistory editHistory = new PDFEditHistory();
                     editHistory.EditPage = editPage;
-                    if (pdfPage != null)
+                    editHistory.PageIndex = pdfPage.PageIndex;
+                    ToolView.GetCPDFViewer().UndoManager.AddHistory(editHistory);
+                    ToolView.UpdateRender(oldRect, imageAreas[0]);
+                }
+            }
+            else
+            {
+                GroupHistory groupHistory = new GroupHistory();
+                foreach (CPDFEditImageArea imageArea in imageAreas)
+                {
+                    bool result;
+                    if (e)
                     {
-                        editHistory.PageIndex = pdfPage.PageIndex;
+                        result = imageArea.VerticalMirror();
+                    }
+                    else
+                    {
+                        result = imageArea.HorizontalMirror();
                     }
 
-                    ToolView.GetCPDFViewer()?.UndoManager.AddHistory(editHistory);
-                    ToolView.UpdateRender(oldRect, imageArea);
-                    editPage.EndEdit();
+                    if (result)
+                    {
+                        PDFEditHistory editHistory = new PDFEditHistory();
+                        editHistory.EditPage = editPage;
+                        editHistory.PageIndex = pdfPage.PageIndex;
+                        groupHistory.Histories.Add(editHistory);
+                    }
                 }
 
-                SetImageThumb();
+                ToolView.GetCPDFViewer()?.UndoManager.AddHistory(groupHistory);
+                ToolView.GetCPDFViewer()?.UpdateRenderFrame();
             }
 
+            editPage.EndEdit();
+            if (imageAreas.Count == 1)
+                SetImageThumb();
+
             //if (EditMultiEvents != null)
             //{
             //    foreach (PDFEditEvent editEvent in EditMultiEvents)
@@ -262,28 +311,45 @@ namespace ComPDFKit.Controls.Edit
 
         private void RotateUI_RotationChanged(object sender, double e)
         {
-            GetImageArea(out CPDFEditImageArea imageArea, out CPDFPage pdfPage, out CPDFEditPage editPage);
-            if (imageArea != null)
+            GetImageArea(out List<CPDFEditImageArea> imageAreas, out CPDFPage pdfPage, out CPDFEditPage editPage);
+            if (imageAreas.Count == 0 || pdfPage == null || editPage == null)
+                return;
+
+            if(ToolView.CurrentEditAreaObject() != null)
             {
-                Rect oldRect = DataConversionForWPF.CRectConversionForRect(imageArea.GetFrame());
-                if (imageArea.Rotate((int)e))
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(imageAreas[0].GetFrame());
+                if (imageAreas[0].Rotate((int)e))
                 {
                     PDFEditHistory editHistory = new PDFEditHistory();
                     editHistory.EditPage = editPage;
-                    if (pdfPage != null)
+                    editHistory.PageIndex = pdfPage.PageIndex;
+                    ToolView.GetCPDFViewer().UndoManager.AddHistory(editHistory);
+                    ToolView.UpdateRender(oldRect, imageAreas[0]);
+                }
+            }
+            else
+            {
+                GroupHistory groupHistory = new GroupHistory();
+                foreach (CPDFEditImageArea imageArea in imageAreas)
+                {
+                    if (imageArea.Rotate((int)e))
                     {
+                        PDFEditHistory editHistory = new PDFEditHistory();
+                        editHistory.EditPage = editPage;
                         editHistory.PageIndex = pdfPage.PageIndex;
+                        groupHistory.Histories.Add(editHistory);
                     }
-
-                    ToolView.GetCPDFViewer()?.UndoManager.AddHistory(editHistory);
-                    //SetRotationText(EditEvent.CurrentRotated);
-                    SetImageThumb();
-                    ToolView.UpdateRender(oldRect, imageArea);
-                    editPage.EndEdit();
-                    RotationTxb.Text = imageArea.GetRotation().ToString();
                 }
+
+                ToolView.GetCPDFViewer()?.UndoManager.AddHistory(groupHistory);
+                ToolView.GetCPDFViewer()?.UpdateRenderFrame();
             }
 
+            editPage.EndEdit();
+            RotationTxb.Text = imageAreas.FirstOrDefault().GetRotation().ToString();
+            if (imageAreas.Count == 1)
+                SetImageThumb();
+
             //if (EditMultiEvents != null)
             //{
             //    foreach (PDFEditEvent editEvent in EditMultiEvents)
@@ -310,34 +376,44 @@ namespace ComPDFKit.Controls.Edit
             {
                 slider.Tag = "true";
             }
-            GetImageArea(out CPDFEditImageArea imageArea, out CPDFPage pdfPage, out CPDFEditPage editPage);
-            if (imageArea != null)
+
+            GetImageArea(out List<CPDFEditImageArea> imageAreas, out CPDFPage pdfPage, out CPDFEditPage editPage);
+            if (imageAreas.Count == 0 || pdfPage == null || editPage == null)
+                return;
+
+            if (ToolView.CurrentEditAreaObject() != null)
             {
-                Rect oldRect = DataConversionForWPF.CRectConversionForRect(imageArea.GetFrame());
-                if (imageArea.SetImageTransparency((byte)(ImasgeOpacitySlider.Value * 255)))
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(imageAreas[0].GetFrame());
+                if (imageAreas[0].SetImageTransparency((byte)(ImasgeOpacitySlider.Value * 255)))
                 {
                     PDFEditHistory editHistory = new PDFEditHistory();
                     editHistory.EditPage = editPage;
-                    if (pdfPage != null)
+                    editHistory.PageIndex = pdfPage.PageIndex;
+                    ToolView.GetCPDFViewer().UndoManager.AddHistory(editHistory);
+                    ToolView.UpdateRender(oldRect, imageAreas[0]);
+                }
+            }
+            else
+            {
+                GroupHistory groupHistory = new GroupHistory();
+                foreach (CPDFEditImageArea imageArea in imageAreas)
+                {
+                    if (imageArea.SetImageTransparency((byte)(ImasgeOpacitySlider.Value * 255)))
                     {
+                        PDFEditHistory editHistory = new PDFEditHistory();
+                        editHistory.EditPage = editPage;
                         editHistory.PageIndex = pdfPage.PageIndex;
+                        groupHistory.Histories.Add(editHistory);
                     }
-
-                    ToolView.GetCPDFViewer()?.UndoManager.AddHistory(editHistory);
-                    SetImageThumb();
-                    ToolView.UpdateRender(oldRect, imageArea);
-                    editPage.EndEdit();
                 }
+
+                ToolView.GetCPDFViewer()?.UndoManager.AddHistory(groupHistory);
+                ToolView.GetCPDFViewer()?.UpdateRenderFrame();
             }
 
-            //if (EditMultiEvents != null)
-            //{
-            //    foreach (PDFEditEvent editEvent in EditMultiEvents)
-            //    {
-            //        editEvent.Transparency = (int)(ImageOpacitySlider.Value * 255);
-            //    }
-            //    PDFEditEvent.UpdatePDFEditList(EditMultiEvents);
-            //}
+            editPage.EndEdit();
+            if (imageAreas.Count == 1)
+                SetImageThumb();
         }
 
         private void SliderOpacity_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
@@ -352,25 +428,44 @@ namespace ComPDFKit.Controls.Edit
             {
                 return;
             }
-            GetImageArea(out CPDFEditImageArea imageArea, out CPDFPage pdfPage, out CPDFEditPage editPage);
-            if (imageArea != null)
+
+            GetImageArea(out List<CPDFEditImageArea> imageAreas, out CPDFPage pdfPage, out CPDFEditPage editPage);
+            if (imageAreas.Count == 0 || pdfPage == null || editPage == null)
+                return;
+
+            if (ToolView.CurrentEditAreaObject() != null)
             {
-                Rect oldRect = DataConversionForWPF.CRectConversionForRect(imageArea.GetFrame());
-                if (imageArea.SetImageTransparency((byte)(ImasgeOpacitySlider.Value * 255)))
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(imageAreas[0].GetFrame());
+                if (imageAreas[0].SetImageTransparency((byte)(ImasgeOpacitySlider.Value * 255)))
                 {
                     PDFEditHistory editHistory = new PDFEditHistory();
                     editHistory.EditPage = editPage;
-                    if (pdfPage != null)
+                    editHistory.PageIndex = pdfPage.PageIndex;
+                    ToolView.GetCPDFViewer().UndoManager.AddHistory(editHistory);
+                    ToolView.UpdateRender(oldRect, imageAreas[0]);
+                }
+            }
+            else
+            {
+                GroupHistory groupHistory = new GroupHistory();
+                foreach (CPDFEditImageArea imageArea in imageAreas)
+                {
+                    if (imageArea.SetImageTransparency((byte)(ImasgeOpacitySlider.Value * 255)))
                     {
+                        PDFEditHistory editHistory = new PDFEditHistory();
+                        editHistory.EditPage = editPage;
                         editHistory.PageIndex = pdfPage.PageIndex;
+                        groupHistory.Histories.Add(editHistory);
                     }
-
-                    ToolView.GetCPDFViewer()?.UndoManager.AddHistory(editHistory);
-                    SetImageThumb();
-                    ToolView.UpdateRender(oldRect, imageArea);
-                    editPage.EndEdit();
                 }
+
+                ToolView.GetCPDFViewer()?.UndoManager.AddHistory(groupHistory);
+                ToolView.GetCPDFViewer()?.UpdateRenderFrame();
             }
+
+            editPage.EndEdit();
+            if (imageAreas.Count == 1)
+                SetImageThumb();
         }
 
         private void ImageReplaceBtn_Click(object sender, RoutedEventArgs e)
@@ -380,39 +475,35 @@ namespace ComPDFKit.Controls.Edit
             //    return;
             //}
 
-            if (EditEvent != null)
+            if (EditEvents.Count > 0)
             {
                 OpenFileDialog openFileDialog = new OpenFileDialog();
                 openFileDialog.Filter = "Image Files(*.jpg;*.jpeg;*.png;*.bmp)|*.jpg;*.jpeg;*.png;*.bmp;";
                 if (openFileDialog.ShowDialog() == true)
                 {
-                    GetImageArea(out CPDFEditImageArea imageArea, out CPDFPage pdfPage, out CPDFEditPage editPage);
-                    if (imageArea != null)
+                    GetImageArea(out List<CPDFEditImageArea> imageAreas, out CPDFPage pdfPage, out CPDFEditPage editPage);
+                    if (imageAreas.Count == 0 || pdfPage == null || editPage == null)
+                        return;
+
+                    int imageWidth = 0;
+                    int imageHeight = 0;
+                    byte[] imageData = null;
+                    PDFHelp.ImagePathToByte(openFileDialog.FileName, ref imageData, ref imageWidth, ref imageHeight);
+                    if (imageData != null && imageWidth > 0 && imageHeight > 0)
                     {
-                        int imageWidth = 0;
-                        int imageHeight = 0;
-                        byte[] imageData = null;
-                        PDFHelp.ImagePathToByte(openFileDialog.FileName, ref imageData, ref imageWidth, ref imageHeight);
-
-                        if (imageData != null && imageWidth > 0 && imageHeight > 0)
+                        Rect oldRect = DataConversionForWPF.CRectConversionForRect(imageAreas[0].GetFrame());
+                        CRect imageRect = imageAreas[0].GetClipRect();
+                        if (imageAreas[0].ReplaceImageArea(imageRect, imageData, imageWidth, imageHeight))
                         {
-                            Rect oldRect = DataConversionForWPF.CRectConversionForRect(imageArea.GetFrame());
-                            CRect imageRect = imageArea.GetClipRect();
-                            if (imageArea.ReplaceImageArea(imageRect, imageData, imageWidth, imageHeight))
-                            {
-                                PDFEditHistory editHistory = new PDFEditHistory();
-                                editHistory.EditPage = editPage;
-                                if (pdfPage != null)
-                                {
-                                    editHistory.PageIndex = pdfPage.PageIndex;
-                                }
-
-                                ToolView.GetCPDFViewer()?.UndoManager.AddHistory(editHistory);
-                                SetImageThumb();
-                                ToolView.UpdateRender(oldRect, imageArea);
-                                editPage.EndEdit();
-                            }
+                            PDFEditHistory editHistory = new PDFEditHistory();
+                            editHistory.EditPage = editPage;
+                            editHistory.PageIndex = pdfPage.PageIndex;
+                            ToolView.GetCPDFViewer().UndoManager.AddHistory(editHistory);
+                            ToolView.UpdateRender(oldRect, imageAreas[0]);
                         }
+
+                        editPage.EndEdit();
+                        SetImageThumb();
                     }
                 }
             }
@@ -472,27 +563,29 @@ namespace ComPDFKit.Controls.Edit
             }
         }
 
-        private void GetImageArea(out CPDFEditImageArea imageArea, out CPDFPage pdfPage, out CPDFEditPage editPage)
+        private void GetImageArea(out List<CPDFEditImageArea> imageAreas, out CPDFPage pdfPage, out CPDFEditPage editPage)
         {
-            imageArea = null;
+            imageAreas = new List<CPDFEditImageArea>();
             editPage = null;
             pdfPage = null;
-            if (ToolView == null || EditEvent == null)
+            if (ToolView == null || EditEvents.Count == 0)
             {
                 return;
             }
-
             try
             {
-                CPDFViewer pdfViewer = ToolView.GetCPDFViewer();
-                CPDFDocument pdfDoc = pdfViewer.GetDocument();
-                pdfPage = pdfDoc.PageAtIndex(EditEvent.PageIndex);
-                editPage = pdfPage.GetEditPage();
-                List<CPDFEditArea> editAreas = editPage.GetEditAreaList();
-                if (editAreas != null && editAreas.Count > EditEvent.EditIndex)
+                foreach (var EditEvent in EditEvents)
                 {
-                    imageArea = editAreas[EditEvent.EditIndex] as CPDFEditImageArea;
-                }
+                    CPDFViewer pdfViewer = ToolView.GetCPDFViewer();
+                    CPDFDocument pdfDoc = pdfViewer.GetDocument();
+                    pdfPage = pdfDoc.PageAtIndex(EditEvent.PageIndex);
+                    editPage = pdfPage.GetEditPage();
+                    List<CPDFEditArea> editAreas = editPage.GetEditAreaList();
+                    if (editAreas != null && editAreas.Count > EditEvent.EditIndex)
+                    {
+                        imageAreas.Add(editAreas[EditEvent.EditIndex] as CPDFEditImageArea);
+                    }
+                } 
             }
             catch (Exception ex)
             {
@@ -502,26 +595,45 @@ namespace ComPDFKit.Controls.Edit
 
         private void SetAbsRotation(double absRotation)
         {
-            GetImageArea(out CPDFEditImageArea imageArea, out CPDFPage pdfPage, out CPDFEditPage editPage);
-            if (imageArea != null)
+            GetImageArea(out List<CPDFEditImageArea> imageAreas, out CPDFPage pdfPage, out CPDFEditPage editPage);
+            if (imageAreas.Count == 0 || pdfPage == null || editPage == null)
+                return;
+
+            if (ToolView.CurrentEditAreaObject() != null)
             {
-                int rotation = (int)absRotation - imageArea.GetRotation();
-                Rect oldRect = DataConversionForWPF.CRectConversionForRect(imageArea.GetFrame());
-                if (imageArea.Rotate(rotation))
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(imageAreas[0].GetFrame());
+                int rotation = (int)absRotation - imageAreas[0].GetRotation();
+                if (imageAreas[0].Rotate(rotation))
                 {
                     PDFEditHistory editHistory = new PDFEditHistory();
                     editHistory.EditPage = editPage;
-                    if (pdfPage != null)
+                    editHistory.PageIndex = pdfPage.PageIndex;
+                    ToolView.GetCPDFViewer().UndoManager.AddHistory(editHistory);
+                    ToolView.UpdateRender(oldRect, imageAreas[0]);
+                }
+            }
+            else
+            {
+                GroupHistory groupHistory = new GroupHistory();
+                foreach (CPDFEditImageArea imageArea in imageAreas)
+                {
+                    int rotation = (int)absRotation - imageArea.GetRotation();
+                    if (imageArea.Rotate(rotation))
                     {
+                        PDFEditHistory editHistory = new PDFEditHistory();
+                        editHistory.EditPage = editPage;
                         editHistory.PageIndex = pdfPage.PageIndex;
+                        groupHistory.Histories.Add(editHistory);
                     }
-
-                    ToolView.GetCPDFViewer()?.UndoManager.AddHistory(editHistory);
-                    SetImageThumb();
-                    ToolView.UpdateRender(oldRect, imageArea);
-                    editPage.EndEdit();
                 }
+
+                ToolView.GetCPDFViewer()?.UndoManager.AddHistory(groupHistory);
+                ToolView.GetCPDFViewer()?.UpdateRenderFrame();
             }
+
+            editPage.EndEdit();
+            if(imageAreas.Count == 1)
+                SetImageThumb();
         }
 
         private void RotationTxb_LostFocus(object sender, RoutedEventArgs e)
@@ -540,6 +652,21 @@ namespace ComPDFKit.Controls.Edit
                 RotationTxb_LostFocus(null, null);
             }
         }
-        #endregion 
+        #endregion
+
+        public event PropertyChangedEventHandler PropertyChanged;
+        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;
+        }
+        protected void OnPropertyChanged([CallerMemberName] string propertyName = "") =>
+    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
     }
 }

+ 53 - 44
Demo/Examples/Compdfkit.Controls/Edit/PDFTextEdit/PDFTextEditControl/PDFTextEditControl.xaml

@@ -15,46 +15,49 @@
             <common:PropertyPanelResourceConverter x:Key="PropertyPanelResourceConverter"></common:PropertyPanelResourceConverter>
         </ResourceDictionary>
     </UserControl.Resources>
-    <Grid>
-        <Grid.RowDefinitions>
-            <RowDefinition Height="auto"></RowDefinition>
-            <RowDefinition Height="auto"></RowDefinition>
-        </Grid.RowDefinitions>
-        
-        <Border Height="36" Background="White">
-            <TextBlock FontSize="14" FontWeight="Bold" HorizontalAlignment="Center" LineHeight="17" VerticalAlignment="Center"
-                       Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_TextProperty}"></TextBlock>
-        </Border>
+    <ScrollViewer VerticalScrollBarVisibility="Auto">
 
-        <Grid Grid.Row="1">
+        <Grid>
             <Grid.RowDefinitions>
                 <RowDefinition Height="auto"></RowDefinition>
                 <RowDefinition Height="auto"></RowDefinition>
-                <RowDefinition Height="auto"></RowDefinition>
-                <RowDefinition Height="auto"></RowDefinition>
-                <RowDefinition Height="auto"></RowDefinition>
-                <RowDefinition Height="auto"></RowDefinition>
             </Grid.RowDefinitions>
 
-            <TextBlock Margin="0,20,0,0" Foreground="#0E1114" FontSize="14"
-                       Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_FontColor}"></TextBlock>
-
-            <common:ColorPickerControl x:Name="FontColorUI" Grid.Row="1" Margin="0,20,0,0" TransparentBtnProperty="Collapsed"></common:ColorPickerControl>
+            <Border Height="36" Background="White">
+                <TextBlock FontSize="14" FontWeight="Bold" HorizontalAlignment="Center" LineHeight="17" VerticalAlignment="Center"
+                       Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_TextProperty}"></TextBlock>
+            </Border>
 
-            <Grid Grid.Row="2" Margin="0,20,0,0" Visibility="Visible">
-                <Grid.ColumnDefinitions>
-                    <ColumnDefinition Width="*"></ColumnDefinition>
-                    <ColumnDefinition Width="auto"></ColumnDefinition>
-                </Grid.ColumnDefinitions>
+            <Grid Grid.Row="1">
                 <Grid.RowDefinitions>
                     <RowDefinition Height="auto"></RowDefinition>
                     <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
+                    <RowDefinition Height="auto"></RowDefinition>
                 </Grid.RowDefinitions>
 
-                <TextBlock FontSize="14" Foreground="#43474D"
+                <TextBlock Margin="0,20,0,0" Foreground="#0E1114" FontSize="14"
+                       Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_FontColor}"></TextBlock>
+
+                <common:ColorPickerControl x:Name="FontColorUI" Grid.Row="1" Margin="0,20,0,0" TransparentBtnProperty="Collapsed"></common:ColorPickerControl>
+
+                <Grid Grid.Row="2" Margin="0,20,0,0" Visibility="Visible">
+                    <Grid.ColumnDefinitions>
+                        <ColumnDefinition Width="*"></ColumnDefinition>
+                        <ColumnDefinition Width="auto"></ColumnDefinition>
+                    </Grid.ColumnDefinitions>
+                    <Grid.RowDefinitions>
+                        <RowDefinition Height="auto"></RowDefinition>
+                        <RowDefinition Height="auto"></RowDefinition>
+                    </Grid.RowDefinitions>
+
+                    <TextBlock FontSize="14" Foreground="#43474D"
                            Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Opacity}"></TextBlock>
 
-                <Slider Style="{StaticResource SliderStyle}" Grid.Row="1" Width="148" Height="28"
+                    <Slider Style="{StaticResource SliderStyle}" Grid.Row="1" Width="148" Height="28"
                     Name="FontOpacitySlider" 
                     Value="14"  
                     IsSelectionRangeEnabled="True" 
@@ -70,29 +73,35 @@
                     Tag="true"
                     />
 
-                <Grid Grid.Row="1" Grid.Column="1" Margin="0,10,0,0">
-                    <ComboBox Name="OpacityComboBox" VerticalContentAlignment="Center" Width="72" Height="28" Foreground="#43474D" FontSize="14"
+                    <Grid Grid.Row="1" Grid.Column="1" Margin="0,10,0,0">
+                        <ComboBox Name="OpacityComboBox" VerticalContentAlignment="Center" Width="72" Height="28" Foreground="#43474D" FontSize="14"
                               SelectionChanged="OpacityComboBox_SelectionChanged" BorderBrush="#1E000000">
-                        <ComboBoxItem>25%</ComboBoxItem>
-                        <ComboBoxItem>50%</ComboBoxItem>
-                        <ComboBoxItem>75%</ComboBoxItem>
-                        <ComboBoxItem>100%</ComboBoxItem>
-                    </ComboBox>
-                    <TextBox Name="OpacityTextBox" IsHitTestVisible="False" Width="72" Height="30" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"
+                            <ComboBoxItem>25%</ComboBoxItem>
+                            <ComboBoxItem>50%</ComboBoxItem>
+                            <ComboBoxItem>75%</ComboBoxItem>
+                            <ComboBoxItem>100%</ComboBoxItem>
+                        </ComboBox>
+                        <TextBox Name="OpacityTextBox" IsHitTestVisible="False" Width="72" Height="30" VerticalContentAlignment="Center" HorizontalContentAlignment="Center"
                              IsReadOnly="True" Background="White" Padding="0,0,15,0" FontSize="14">100%</TextBox>
-                    <Path Fill="#43474D" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,5,0" IsHitTestVisible="False">
-                        <Path.Data>
-                            M0.5 0.510248L4.5041 5.5L8.5 0.5L0.5 0.510248Z
-                        </Path.Data>
-                    </Path>
+                        <Path Fill="#43474D" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0,0,5,0" IsHitTestVisible="False">
+                            <Path.Data>
+                                M0.5 0.510248L4.5041 5.5L8.5 0.5L0.5 0.510248Z
+                            </Path.Data>
+                        </Path>
+                    </Grid>
                 </Grid>
-            </Grid>
 
-            <local:CPDFTextStyleUI x:Name="TextStyleUI" Grid.Row="3" FontSize="16" Margin="0,20,0,0"></local:CPDFTextStyleUI>
+                <local:CPDFTextStyleUI x:Name="TextStyleUI" Grid.Row="3" FontSize="16" Margin="0,20,0,0"></local:CPDFTextStyleUI>
+
+                <local:CPDFTextAlignUI x:Name="TextAlignUI" Grid.Row="4" FontSize="16" Margin="0,20,0,0" Width="150" HorizontalAlignment="Left"></local:CPDFTextAlignUI>
+                <StackPanel Grid.Row="5">
+                    <CheckBox x:Name="chkMulti" IsChecked="{Binding IsMultiSelected}"  Content="Multi Selected" Margin="0,10,0,0" Click="chkMulti_Click"></CheckBox>
 
-            <local:CPDFTextAlignUI x:Name="TextAlignUI" Grid.Row="4" FontSize="16" Margin="0,20,0,0" Width="150" HorizontalAlignment="Left"></local:CPDFTextAlignUI>
-            
+                    <CheckBox x:Name="chkEditPen" IsChecked="{Binding ShowBorder}" Content="Show Border" Margin="0,10,0,0" Click="chkEditPen_Click"></CheckBox>
+
+                </StackPanel>
+            </Grid>
         </Grid>
+    </ScrollViewer>
 
-    </Grid>
 </UserControl>

+ 360 - 151
Demo/Examples/Compdfkit.Controls/Edit/PDFTextEdit/PDFTextEditControl/PDFTextEditControl.xaml.cs

@@ -5,7 +5,6 @@ using ComPDFKit.Tool;
 using ComPDFKit.Tool.SettingParam;
 using ComPDFKit.Tool.UndoManger;
 using ComPDFKit.Viewer.Helper;
-using ComPDFKit.Controls.PDFControl;
 using ComPDFKitViewer;
 using System;
 using System.Collections.Generic;
@@ -13,22 +12,48 @@ using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Controls.Primitives;
 using System.Windows.Media;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+using System.Linq;
+
 namespace ComPDFKit.Controls.Edit
 {
-    public partial class PDFTextEditControl : UserControl
+    public partial class PDFTextEditControl : UserControl, INotifyPropertyChanged
     {
         #region Property
         public CPDFViewerTool ToolView { get; private set; }
-        public TextEditParam EditEvent { get; set; }
+        public List<TextEditParam> EditEvents { get; set; }
+
 
-        //public List<PDFEditEvent> EditMultiEvents { get; set; }
+        public event PropertyChangedEventHandler PropertyChanged;
+
+        private bool _isMultiSelected = true;
+        public bool IsMultiSelected
+        {
+            get => _isMultiSelected;
+            set
+            {
+                UpdateProper(ref _isMultiSelected, value);
+            }
+        }
 
+        private bool _showBorder;
+        public bool ShowBorder
+        {
+            get => _showBorder;
+            set
+            {
+                UpdateProper(ref _showBorder, value);
+            }
+        }
         #endregion 
 
         public PDFTextEditControl()
         {
+            DataContext = this;
             InitializeComponent();
             Loaded += PDFTextEditControl_Loaded;
+
         }
 
         #region Init PDFView
@@ -39,23 +64,18 @@ namespace ComPDFKit.Controls.Edit
         #endregion
 
         #region UI
-        public void SetPDFTextEditData(TextEditParam newEvent)
+        public void SetPDFTextEditData(List<TextEditParam> newEvents)
         {
-            if (newEvent.EditIndex<0)
-            {
-                EditEvent = null;
-            }
-            else
+            EditEvents = newEvents.Where(newEvent => newEvent.EditIndex >= 0 && newEvent.EditType == CPDFEditType.EditText).ToList();
+            TextEditParam defaultEvent = EditEvents.FirstOrDefault();
+            if (EditEvents.Count > 0)
             {
-                EditEvent = newEvent;
-            }
-            if (newEvent != null && newEvent.EditType == CPDFEditType.EditText)
-            {
-                GetTextArea(out CPDFEditTextArea textArea, out CPDFPage pdfPage, out CPDFEditPage editPage);
+                GetTextArea(out List<CPDFEditTextArea> textArea, out CPDFPage pdfPage, out CPDFEditPage editPage);
+
                 List<string> sysfontList = new List<string>();
                 if (textArea != null)
                 {
-                    sysfontList = textArea.GetFontList();
+                    sysfontList = textArea.FirstOrDefault().GetFontList();
                 }
                 if (sysfontList.Count == 0)
                 {
@@ -63,28 +83,26 @@ namespace ComPDFKit.Controls.Edit
                     sysfontList.Add("Courier New");
                     sysfontList.Add("Times New Roman");
                 }
-                if (sysfontList.Contains(newEvent.FontName) == false && string.IsNullOrEmpty(newEvent.FontName) == false)
+                if (sysfontList.Contains(defaultEvent.FontName) == false && string.IsNullOrEmpty(defaultEvent.FontName) == false)
                 {
-                    sysfontList.Add(newEvent.FontName);
+                    sysfontList.Add(defaultEvent.FontName);
                 }
 
                 TextStyleUI.SetFontNames(sysfontList);
-                TextStyleUI.SelectFontName(newEvent.FontName);
-                TextStyleUI.SetFontStyle(newEvent.IsBold, newEvent.IsItalic);
-                TextStyleUI.SetFontSize(newEvent.FontSize);
-                OpacityTextBox.Text = string.Format("{0}%", (int)(Math.Ceiling(newEvent.Transparency * 100 / 255D)));
-                FontOpacitySlider.Value = ((int)(Math.Ceiling(newEvent.Transparency * 100 / 255D))) / 100D;
-                TextAlignUI.SetFontAlign(newEvent.TextAlign);
-                if (newEvent.FontColor != null && newEvent.FontColor.Length == 3)
+                TextStyleUI.SelectFontName(defaultEvent.FontName);
+                TextStyleUI.SetFontStyle(defaultEvent.IsBold, defaultEvent.IsItalic);
+                TextStyleUI.SetFontSize(defaultEvent.FontSize);
+                OpacityTextBox.Text = string.Format("{0}%", (int)(Math.Ceiling(defaultEvent.Transparency * 100 / 255D)));
+                FontOpacitySlider.Value = ((int)(Math.Ceiling(defaultEvent.Transparency * 100 / 255D))) / 100D;
+                TextAlignUI.SetFontAlign(defaultEvent.TextAlign);
+                if (defaultEvent.FontColor != null && defaultEvent.FontColor.Length == 3)
                 {
                     FontColorUI.SetCheckedForColor(Color.FromRgb(
-                        newEvent.FontColor[0],
-                        newEvent.FontColor[1],
-                        newEvent.FontColor[2]));
+                        defaultEvent.FontColor[0],
+                        defaultEvent.FontColor[1],
+                        defaultEvent.FontColor[2]));
                 }
-
             }
-            EditEvent = newEvent;
         }
 
         //public void SetPDFTextMultiEditData(List<PDFEditEvent> editEvents)
@@ -131,12 +149,15 @@ namespace ComPDFKit.Controls.Edit
                 slider.Tag = "true";
             }
 
-            GetTextArea(out CPDFEditTextArea textArea, out CPDFPage pdfPage, out CPDFEditPage editPage);
-            if (textArea != null)
+            GetTextArea(out List<CPDFEditTextArea> textAreas, out CPDFPage pdfPage, out CPDFEditPage editPage);
+            if (textAreas.Count == 0 || pdfPage == null || editPage == null)
+                return;
+
+            if (ToolView.CurrentEditAreaObject() != null)
             {
-                Rect oldRect = DataConversionForWPF.CRectConversionForRect(textArea.GetFrame());
                 bool result;
-                if (string.IsNullOrEmpty(textArea.SelectText))
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(textAreas[0].GetFrame());
+                if (string.IsNullOrEmpty(textAreas[0].SelectText))
                 {
                     string fontName = "Helvetica";
                     float fontSize = 14;
@@ -144,33 +165,47 @@ namespace ComPDFKit.Controls.Edit
                     byte transparency = 255;
                     bool isBold = false;
                     bool isItalic = false;
-                    textArea.GetTextStyle(ref fontName, ref fontSize, ref fontColor, ref transparency, ref isBold, ref isItalic);
-                    result = textArea.SetCurTextStyle(fontName, fontSize, fontColor[0], fontColor[1], fontColor[2], (byte)(FontOpacitySlider.Value * 255), isBold, isItalic);
+                    textAreas[0].GetTextStyle(ref fontName, ref fontSize, ref fontColor, ref transparency, ref isBold, ref isItalic);
+                    result = textAreas[0].SetCurTextStyle(fontName, fontSize, fontColor[0], fontColor[1], fontColor[2], (byte)(FontOpacitySlider.Value * 255), isBold, isItalic);
                 }
                 else
                 {
-                    result = textArea.SetCharsFontTransparency((byte)(FontOpacitySlider.Value * 255));
+                    result = textAreas[0].SetCharsFontTransparency((byte)(FontOpacitySlider.Value * 255));
                 }
 
                 if (result)
                 {
                     PDFEditHistory editHistory = new PDFEditHistory();
                     editHistory.EditPage = editPage;
-                    if (pdfPage != null)
+                    editHistory.PageIndex = pdfPage.PageIndex;
+                    ToolView.GetCPDFViewer().UndoManager.AddHistory(editHistory);
+                    ToolView.UpdateRender(oldRect, textAreas[0]);
+                }
+            }
+            else
+            {
+                GroupHistory groupHistory = new GroupHistory();
+                foreach (CPDFEditTextArea textArea in textAreas)
+                {
+                    if (textArea.SetCharsFontTransparency((byte)(FontOpacitySlider.Value * 255)))
                     {
+                        PDFEditHistory editHistory = new PDFEditHistory();
+                        editHistory.EditPage = editPage;
                         editHistory.PageIndex = pdfPage.PageIndex;
+                        groupHistory.Histories.Add(editHistory);
                     }
-                    ToolView.GetCPDFViewer()?.UndoManager.AddHistory(editHistory);
-                    ToolView.UpdateRender(oldRect, textArea);
-                    editPage.EndEdit();
                 }
+
+                ToolView.GetCPDFViewer()?.UndoManager.AddHistory(groupHistory);
+                ToolView.GetCPDFViewer()?.UpdateRenderFrame();
             }
 
-            if (EditEvent != null && textArea == null)
+            editPage.EndEdit();
+            if (EditEvents.Count > 0 && textAreas.Count > 0)
             {
-                EditEvent.Transparency = (byte)(FontOpacitySlider.Value * 255);
+                EditEvents.FirstOrDefault().Transparency = (byte)(FontOpacitySlider.Value * 255);
                 DefaultSettingParam defaultSettingParam = ToolView.GetDefaultSettingParam();
-                defaultSettingParam.SetPDFEditParamm(EditEvent);
+                defaultSettingParam.SetPDFEditParamm(EditEvents.FirstOrDefault());
             }
         }
 
@@ -187,12 +222,15 @@ namespace ComPDFKit.Controls.Edit
                 return;
             }
 
-            GetTextArea(out CPDFEditTextArea textArea, out CPDFPage pdfPage, out CPDFEditPage editPage);
-            if (textArea != null)
+            GetTextArea(out List<CPDFEditTextArea> textAreas, out CPDFPage pdfPage, out CPDFEditPage editPage);
+            if (textAreas.Count == 0 || pdfPage == null || editPage == null)
+                return;
+
+            if (ToolView.CurrentEditAreaObject() != null)
             {
-                Rect oldRect = DataConversionForWPF.CRectConversionForRect(textArea.GetFrame());
                 bool result;
-                if (string.IsNullOrEmpty(textArea.SelectText))
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(textAreas[0].GetFrame());
+                if (string.IsNullOrEmpty(textAreas[0].SelectText))
                 {
                     string fontName = "Helvetica";
                     float fontSize = 14;
@@ -200,34 +238,47 @@ namespace ComPDFKit.Controls.Edit
                     byte transparency = 255;
                     bool isBold = false;
                     bool isItalic = false;
-                    textArea.GetTextStyle(ref fontName, ref fontSize, ref fontColor, ref transparency, ref isBold, ref isItalic);
-                    result = textArea.SetCurTextStyle(fontName, fontSize, fontColor[0], fontColor[1], fontColor[2], (byte)(FontOpacitySlider.Value * 255), isBold, isItalic);
+                    textAreas[0].GetTextStyle(ref fontName, ref fontSize, ref fontColor, ref transparency, ref isBold, ref isItalic);
+                    result = textAreas[0].SetCurTextStyle(fontName, fontSize, fontColor[0], fontColor[1], fontColor[2], (byte)(FontOpacitySlider.Value * 255), isBold, isItalic);
                 }
                 else
                 {
-                    result = textArea.SetCharsFontTransparency((byte)(FontOpacitySlider.Value * 255));
+                    result = textAreas[0].SetCharsFontTransparency((byte)(FontOpacitySlider.Value * 255));
                 }
 
                 if (result)
                 {
                     PDFEditHistory editHistory = new PDFEditHistory();
                     editHistory.EditPage = editPage;
-                    if (pdfPage != null)
+                    editHistory.PageIndex = pdfPage.PageIndex;
+                    ToolView.GetCPDFViewer().UndoManager.AddHistory(editHistory);
+                    ToolView.UpdateRender(oldRect, textAreas[0]);
+                }
+            }
+            else
+            {
+                GroupHistory groupHistory = new GroupHistory();
+                foreach (CPDFEditTextArea textArea in textAreas)
+                {
+                    if (textArea.SetCharsFontTransparency((byte)(FontOpacitySlider.Value * 255)))
                     {
+                        PDFEditHistory editHistory = new PDFEditHistory();
+                        editHistory.EditPage = editPage;
                         editHistory.PageIndex = pdfPage.PageIndex;
+                        groupHistory.Histories.Add(editHistory);
                     }
-
-                    ToolView.GetCPDFViewer()?.UndoManager.AddHistory(editHistory);
-                    ToolView.UpdateRender(oldRect, textArea);
-                    editPage.EndEdit();
                 }
+
+                ToolView.GetCPDFViewer()?.UndoManager.AddHistory(groupHistory);
+                ToolView.GetCPDFViewer()?.UpdateRenderFrame();
             }
 
-            if (EditEvent != null && textArea == null)
+            editPage.EndEdit();
+            if (EditEvents?.Count > 0 && textAreas.Count > 0)
             {
-                EditEvent.Transparency = (byte)(FontOpacitySlider.Value * 255);
+                EditEvents.FirstOrDefault().Transparency = (byte)(FontOpacitySlider.Value * 255);
                 DefaultSettingParam defaultSettingParam = ToolView.GetDefaultSettingParam();
-                defaultSettingParam.SetPDFEditParamm(EditEvent);
+                defaultSettingParam.SetPDFEditParamm(EditEvents.FirstOrDefault());
             }
         }
 
@@ -258,6 +309,9 @@ namespace ComPDFKit.Controls.Edit
             TextStyleUI.TextSizeChanged += TextStyleUI_TextSizeChanged;
             TextAlignUI.TextAlignChanged += TextAlignUI_TextAlignChanged;
             FontColorUI.ColorChanged += FontColorUI_ColorChanged;
+
+            IsMultiSelected = ToolView.GetIsMultiSelected();
+            ShowBorder = ToolView.GetEditPen() == null || ToolView.GetEditPen().Thickness != 0;
         }
 
         #endregion
@@ -266,12 +320,15 @@ namespace ComPDFKit.Controls.Edit
 
         private void TextStyleUI_TextSizeChanged(object sender, double e)
         {
-            GetTextArea(out CPDFEditTextArea textArea, out CPDFPage pdfPage, out CPDFEditPage editPage);
-            if (textArea != null)
+            GetTextArea(out List<CPDFEditTextArea> textAreas, out CPDFPage pdfPage, out CPDFEditPage editPage);
+            if (textAreas.Count == 0 || pdfPage == null || editPage == null)
+                return;
+
+            if (ToolView.CurrentEditAreaObject() != null)
             {
-                Rect oldRect = DataConversionForWPF.CRectConversionForRect(textArea.GetFrame());
                 bool result;
-                if (string.IsNullOrEmpty(textArea.SelectText))
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(textAreas[0].GetFrame());
+                if (string.IsNullOrEmpty(textAreas[0].SelectText))
                 {
                     string fontName = "Helvetica";
                     float fontSize = 14;
@@ -279,33 +336,47 @@ namespace ComPDFKit.Controls.Edit
                     byte transparency = 255;
                     bool isBold = false;
                     bool isItalic = false;
-                    textArea.GetTextStyle(ref fontName, ref fontSize, ref fontColor, ref transparency, ref isBold, ref isItalic);
-                    result = textArea.SetCurTextStyle(fontName, (float)e, fontColor[0], fontColor[1], fontColor[2], transparency, isBold, isItalic);
+                    textAreas[0].GetTextStyle(ref fontName, ref fontSize, ref fontColor, ref transparency, ref isBold, ref isItalic);
+                    result = textAreas[0].SetCurTextStyle(fontName, (float)e, fontColor[0], fontColor[1], fontColor[2], transparency, isBold, isItalic);
                 }
                 else
                 {
-                    result = textArea.SetCharsFontSize((float)e,true);
+                    result = textAreas[0].SetCharsFontSize((float)e, true);
                 }
 
                 if (result)
                 {
                     PDFEditHistory editHistory = new PDFEditHistory();
                     editHistory.EditPage = editPage;
-                    if (pdfPage != null)
+                    editHistory.PageIndex = pdfPage.PageIndex;
+                    ToolView.GetCPDFViewer().UndoManager.AddHistory(editHistory);
+                    ToolView.UpdateRender(oldRect, textAreas[0]);
+                }
+            }
+            else
+            {
+                GroupHistory groupHistory = new GroupHistory();
+                foreach (CPDFEditTextArea textArea in textAreas)
+                {
+                    if (textArea.SetCharsFontSize((float)e, true))
                     {
+                        PDFEditHistory editHistory = new PDFEditHistory();
+                        editHistory.EditPage = editPage;
                         editHistory.PageIndex = pdfPage.PageIndex;
+                        groupHistory.Histories.Add(editHistory);
                     }
-                    ToolView.GetCPDFViewer()?.UndoManager.AddHistory(editHistory);
-                    ToolView.UpdateRender(oldRect, textArea);
-                    editPage.EndEdit();
                 }
+
+                ToolView.GetCPDFViewer()?.UndoManager.AddHistory(groupHistory);
+                ToolView.GetCPDFViewer()?.UpdateRenderFrame();
             }
 
-            if (EditEvent != null && textArea == null)
+            editPage.EndEdit();
+            if (EditEvents.Count > 0 && textAreas.Count > 0)
             {
-                EditEvent.FontSize = e;
+                EditEvents.FirstOrDefault().FontSize = e;
                 DefaultSettingParam defaultSettingParam = ToolView.GetDefaultSettingParam();
-                defaultSettingParam.SetPDFEditParamm(EditEvent);
+                defaultSettingParam.SetPDFEditParamm(EditEvents.FirstOrDefault());
             }
 
             //if (EditMultiEvents != null)
@@ -321,12 +392,15 @@ namespace ComPDFKit.Controls.Edit
         private void FontColorUI_ColorChanged(object sender, EventArgs e)
         {
             SolidColorBrush newBrush = FontColorUI.Brush as SolidColorBrush;
-            GetTextArea(out CPDFEditTextArea textArea, out CPDFPage pdfPage, out CPDFEditPage editPage);
-            if (textArea != null && newBrush != null)
+            GetTextArea(out List<CPDFEditTextArea> textAreas, out CPDFPage pdfPage, out CPDFEditPage editPage);
+            if (textAreas.Count == 0 || pdfPage == null || editPage == null)
+                return;
+
+            if (ToolView.CurrentEditAreaObject() != null)
             {
-                Rect oldRect = DataConversionForWPF.CRectConversionForRect(textArea.GetFrame());
                 bool result;
-                if (string.IsNullOrEmpty(textArea.SelectText))
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(textAreas[0].GetFrame());
+                if (string.IsNullOrEmpty(textAreas[0].SelectText))
                 {
                     string fontName = "Helvetica";
                     float fontSize = 14;
@@ -334,75 +408,116 @@ namespace ComPDFKit.Controls.Edit
                     byte transparency = 255;
                     bool isBold = false;
                     bool isItalic = false;
-                    textArea.GetTextStyle(ref fontName, ref fontSize, ref fontColor, ref transparency, ref isBold, ref isItalic);
-                    result = textArea.SetCurTextStyle(fontName, fontSize, newBrush.Color.R, newBrush.Color.G, newBrush.Color.B, transparency, isBold, isItalic);
+                    textAreas[0].GetTextStyle(ref fontName, ref fontSize, ref fontColor, ref transparency, ref isBold, ref isItalic);
+                    result = textAreas[0].SetCurTextStyle(fontName, fontSize, newBrush.Color.R, newBrush.Color.G, newBrush.Color.B, transparency, isBold, isItalic);
                 }
                 else
                 {
-                    result = textArea.SetCharsFontColor(newBrush.Color.R, newBrush.Color.G, newBrush.Color.B);
+                    result = textAreas[0].SetCharsFontColor(newBrush.Color.R, newBrush.Color.G, newBrush.Color.B);
                 }
 
-                if(result)
+                if (result)
                 {
                     PDFEditHistory editHistory = new PDFEditHistory();
                     editHistory.EditPage = editPage;
-                    if (pdfPage != null)
+                    editHistory.PageIndex = pdfPage.PageIndex;
+                    ToolView.GetCPDFViewer().UndoManager.AddHistory(editHistory);
+                    ToolView.UpdateRender(oldRect, textAreas[0]);
+                }
+            }
+            else
+            {
+                GroupHistory groupHistory = new GroupHistory();
+                foreach (CPDFEditTextArea textArea in textAreas)
+                {
+                    if (textArea.SetCharsFontColor(newBrush.Color.R, newBrush.Color.G, newBrush.Color.B))
                     {
+                        PDFEditHistory editHistory = new PDFEditHistory();
+                        editHistory.EditPage = editPage;
                         editHistory.PageIndex = pdfPage.PageIndex;
+                        groupHistory.Histories.Add(editHistory);
                     }
 
-                    ToolView.GetCPDFViewer()?.UndoManager.AddHistory(editHistory);
-                    ToolView.UpdateRender(oldRect, textArea);
-                    editPage.EndEdit();
+                    ToolView.GetCPDFViewer()?.UndoManager.AddHistory(groupHistory);
+                    ToolView.GetCPDFViewer()?.UpdateRenderFrame();
                 }
             }
 
-            if (EditEvent != null && textArea == null && newBrush != null)
+            editPage.EndEdit();
+            if (EditEvents.Count > 0 && newBrush != null)
             {
                 byte[] Color = new byte[3];
                 Color[0] = newBrush.Color.R;
                 Color[1] = newBrush.Color.G;
                 Color[2] = newBrush.Color.B;
-                EditEvent.FontColor = Color;
+                EditEvents.FirstOrDefault().FontColor = Color;
                 DefaultSettingParam defaultSettingParam = ToolView.GetDefaultSettingParam();
-                defaultSettingParam.SetPDFEditParamm(EditEvent);
+                defaultSettingParam.SetPDFEditParamm(EditEvents.FirstOrDefault());
             }
         }
 
         private void TextAlignUI_TextAlignChanged(object sender, TextAlignType e)
         {
-            GetTextArea(out CPDFEditTextArea textArea, out CPDFPage pdfPage, out CPDFEditPage editPage);
-            if (textArea != null)
+            GetTextArea(out List<CPDFEditTextArea> textAreas, out CPDFPage pdfPage, out CPDFEditPage editPage);
+            if (textAreas.Count == 0 || pdfPage == null || editPage == null)
+                return;
+
+            if (ToolView.CurrentEditAreaObject() != null)
             {
-                bool result = false;
-                Rect oldRect = DataConversionForWPF.CRectConversionForRect(textArea.GetFrame());
-                if (textArea.SelectLineRects != null && textArea.SelectLineRects.Count > 0)
+                bool result;
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(textAreas[0].GetFrame());
+                if (textAreas[0].SelectLineRects != null && textAreas[0].SelectLineRects.Count > 0)
                 {
-                    result = textArea.SetTextRangeAlign(e);
+                    result = textAreas[0].SetTextRangeAlign(e);
                 }
                 else
                 {
-                    result = textArea.SetTextAreaAlign(e);
+                    result = textAreas[0].SetTextAreaAlign(e);
                 }
+
                 if (result)
                 {
                     PDFEditHistory editHistory = new PDFEditHistory();
                     editHistory.EditPage = editPage;
-                    if (pdfPage != null)
+                    editHistory.PageIndex = pdfPage.PageIndex;
+                    ToolView.GetCPDFViewer().UndoManager.AddHistory(editHistory);
+                    ToolView.UpdateRender(oldRect, textAreas[0]);
+                }
+            }
+            else
+            {
+                GroupHistory groupHistory = new GroupHistory();
+                foreach (CPDFEditTextArea textArea in textAreas)
+                {
+                    bool result;
+                    if (textArea.SelectLineRects != null && textArea.SelectLineRects.Count > 0)
+                    {
+                        result = textArea.SetTextRangeAlign(e);
+                    }
+                    else
                     {
+                        result = textArea.SetTextAreaAlign(e);
+                    }
+
+                    if (result)
+                    {
+                        PDFEditHistory editHistory = new PDFEditHistory();
+                        editHistory.EditPage = editPage;
                         editHistory.PageIndex = pdfPage.PageIndex;
+                        groupHistory.Histories.Add(editHistory);
                     }
-                    ToolView.GetCPDFViewer()?.UndoManager.AddHistory(editHistory);
-                    ToolView.UpdateRender(oldRect, textArea);
-                    editPage.EndEdit();
                 }
+
+                ToolView.GetCPDFViewer()?.UndoManager.AddHistory(groupHistory);
+                ToolView.GetCPDFViewer()?.UpdateRenderFrame();
             }
 
-            if (EditEvent != null && textArea == null)
+            editPage.EndEdit();
+            if (EditEvents.Count > 0 && textAreas.Count > 0)
             {
-                EditEvent.TextAlign = e;
+                EditEvents.FirstOrDefault().TextAlign = e;
                 DefaultSettingParam defaultSettingParam = ToolView.GetDefaultSettingParam();
-                defaultSettingParam.SetPDFEditParamm(EditEvent);
+                defaultSettingParam.SetPDFEditParamm(EditEvents.FirstOrDefault());
             }
 
             //if (EditMultiEvents != null)
@@ -417,12 +532,15 @@ namespace ComPDFKit.Controls.Edit
 
         private void TextStyleUI_TextItalicChanged(object sender, bool e)
         {
-            GetTextArea(out CPDFEditTextArea textArea, out CPDFPage pdfPage, out CPDFEditPage editPage);
-            if (textArea != null)
+            GetTextArea(out List<CPDFEditTextArea> textAreas, out CPDFPage pdfPage, out CPDFEditPage editPage);
+            if (textAreas.Count == 0 || pdfPage == null || editPage == null)
+                return;
+
+            if (ToolView.CurrentEditAreaObject() != null)
             {
-                Rect oldRect = DataConversionForWPF.CRectConversionForRect(textArea.GetFrame());
                 bool result;
-                if (string.IsNullOrEmpty(textArea.SelectText))
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(textAreas[0].GetFrame());
+                if (string.IsNullOrEmpty(textAreas[0].SelectText))
                 {
                     string fontName = "Helvetica";
                     float fontSize = 14;
@@ -430,34 +548,47 @@ namespace ComPDFKit.Controls.Edit
                     byte transparency = 255;
                     bool isBold = false;
                     bool isItalic = false;
-                    textArea.GetTextStyle(ref fontName, ref fontSize, ref fontColor, ref transparency, ref isBold, ref isItalic);
-                    result = textArea.SetCurTextStyle(fontName, fontSize, fontColor[0], fontColor[1], fontColor[2], transparency, isBold, e);
+                    textAreas[0].GetTextStyle(ref fontName, ref fontSize, ref fontColor, ref transparency, ref isBold, ref isItalic);
+                    result = textAreas[0].SetCurTextStyle(fontName, fontSize, fontColor[0], fontColor[1], fontColor[2], transparency, isBold, e);
                 }
                 else
                 {
-                    result = textArea.SetCharsFontItalic(e);
+                    result = textAreas[0].SetCharsFontItalic(e);
                 }
 
                 if (result)
                 {
                     PDFEditHistory editHistory = new PDFEditHistory();
                     editHistory.EditPage = editPage;
-                    if (pdfPage != null)
+                    editHistory.PageIndex = pdfPage.PageIndex;
+                    ToolView.GetCPDFViewer().UndoManager.AddHistory(editHistory);
+                    ToolView.UpdateRender(oldRect, textAreas[0]);
+                }
+            }
+            else
+            {
+                GroupHistory groupHistory = new GroupHistory();
+                foreach (CPDFEditTextArea textArea in textAreas)
+                {
+                    if (textArea.SetCharsFontItalic(e))
                     {
+                        PDFEditHistory editHistory = new PDFEditHistory();
+                        editHistory.EditPage = editPage;
                         editHistory.PageIndex = pdfPage.PageIndex;
+                        groupHistory.Histories.Add(editHistory);
                     }
-
-                    ToolView.GetCPDFViewer()?.UndoManager.AddHistory(editHistory);
-                    ToolView.UpdateRender(oldRect, textArea);
-                    editPage.EndEdit();
                 }
+
+                ToolView.GetCPDFViewer()?.UndoManager.AddHistory(groupHistory);
+                ToolView.GetCPDFViewer()?.UpdateRenderFrame();
             }
 
-            if (EditEvent != null && textArea == null)
+            editPage.EndEdit();
+            if (EditEvents.Count > 0 && textAreas.Count > 0)
             {
-                EditEvent.IsItalic = e;
+                EditEvents.FirstOrDefault().IsItalic = e;
                 DefaultSettingParam defaultSettingParam = ToolView.GetDefaultSettingParam();
-                defaultSettingParam.SetPDFEditParamm(EditEvent);
+                defaultSettingParam.SetPDFEditParamm(EditEvents.FirstOrDefault());
             }
 
             //if (EditMultiEvents != null)
@@ -472,12 +603,15 @@ namespace ComPDFKit.Controls.Edit
 
         private void TextStyleUI_TextBoldChanged(object sender, bool e)
         {
-            GetTextArea(out CPDFEditTextArea textArea, out CPDFPage pdfPage, out CPDFEditPage editPage);
-            if (textArea != null)
+            GetTextArea(out List<CPDFEditTextArea> textAreas, out CPDFPage pdfPage, out CPDFEditPage editPage);
+            if (textAreas.Count == 0 || pdfPage == null || editPage == null)
+                return;
+
+            if (ToolView.CurrentEditAreaObject() != null)
             {
-                Rect oldRect = DataConversionForWPF.CRectConversionForRect(textArea.GetFrame());
                 bool result;
-                if (string.IsNullOrEmpty(textArea.SelectText))
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(textAreas[0].GetFrame());
+                if (string.IsNullOrEmpty(textAreas[0].SelectText))
                 {
                     string fontName = "Helvetica";
                     float fontSize = 14;
@@ -485,33 +619,47 @@ namespace ComPDFKit.Controls.Edit
                     byte transparency = 255;
                     bool isBold = false;
                     bool isItalic = false;
-                    textArea.GetTextStyle(ref fontName, ref fontSize, ref fontColor, ref transparency, ref isBold, ref isItalic);
-                    result = textArea.SetCurTextStyle(fontName, fontSize, fontColor[0], fontColor[1], fontColor[2], transparency, e, isItalic);
+                    textAreas[0].GetTextStyle(ref fontName, ref fontSize, ref fontColor, ref transparency, ref isBold, ref isItalic);
+                    result = textAreas[0].SetCurTextStyle(fontName, fontSize, fontColor[0], fontColor[1], fontColor[2], transparency, e, isItalic);
                 }
                 else
                 {
-                    result = textArea.SetCharsFontBold(e);
+                    result = textAreas[0].SetCharsFontBold(e);
                 }
 
                 if (result)
                 {
                     PDFEditHistory editHistory = new PDFEditHistory();
                     editHistory.EditPage = editPage;
-                    if (pdfPage != null)
+                    editHistory.PageIndex = pdfPage.PageIndex;
+                    ToolView.GetCPDFViewer().UndoManager.AddHistory(editHistory);
+                    ToolView.UpdateRender(oldRect, textAreas[0]);
+                }
+            }
+            else
+            {
+                GroupHistory groupHistory = new GroupHistory();
+                foreach (CPDFEditTextArea textArea in textAreas)
+                {
+                    if (textArea.SetCharsFontBold(e))
                     {
+                        PDFEditHistory editHistory = new PDFEditHistory();
+                        editHistory.EditPage = editPage;
                         editHistory.PageIndex = pdfPage.PageIndex;
+                        groupHistory.Histories.Add(editHistory);
                     }
-                    ToolView.GetCPDFViewer()?.UndoManager.AddHistory(editHistory);
-                    ToolView.UpdateRender(oldRect, textArea);
-                    editPage.EndEdit();
                 }
+
+                ToolView.GetCPDFViewer()?.UndoManager.AddHistory(groupHistory);
+                ToolView.GetCPDFViewer()?.UpdateRenderFrame();
             }
 
-            if (EditEvent != null && textArea == null)
+            editPage.EndEdit();
+            if (EditEvents.Count > 0 && textAreas.Count > 0)
             {
-                EditEvent.IsBold = e;
+                EditEvents.FirstOrDefault().IsBold = e;
                 DefaultSettingParam defaultSettingParam = ToolView.GetDefaultSettingParam();
-                defaultSettingParam.SetPDFEditParamm(EditEvent);
+                defaultSettingParam.SetPDFEditParamm(EditEvents.FirstOrDefault());
             }
 
             //if (EditMultiEvents != null)
@@ -526,12 +674,15 @@ namespace ComPDFKit.Controls.Edit
 
         private void TextStyleUI_TextFontChanged(object sender, string e)
         {
-            GetTextArea(out CPDFEditTextArea textArea, out CPDFPage pdfPage, out CPDFEditPage editPage);
-            if (textArea != null)
+            GetTextArea(out List<CPDFEditTextArea> textAreas, out CPDFPage pdfPage, out CPDFEditPage editPage);
+            if (textAreas.Count == 0 || pdfPage == null || editPage == null)
+                return;
+
+            if (ToolView.CurrentEditAreaObject() != null)
             {
-                Rect oldRect = DataConversionForWPF.CRectConversionForRect(textArea.GetFrame());
                 bool result;
-                if (string.IsNullOrEmpty(textArea.SelectText))
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(textAreas[0].GetFrame());
+                if (string.IsNullOrEmpty(textAreas[0].SelectText))
                 {
                     string fontName = "Helvetica";
                     float fontSize = 14;
@@ -539,33 +690,47 @@ namespace ComPDFKit.Controls.Edit
                     byte transparency = 255;
                     bool isBold = false;
                     bool isItalic = false;
-                    textArea.GetTextStyle(ref fontName, ref fontSize, ref fontColor, ref transparency, ref isBold, ref isItalic);
-                    result = textArea.SetCurTextStyle(e, fontSize, fontColor[0], fontColor[1], fontColor[2], transparency, isBold, isItalic);
+                    textAreas[0].GetTextStyle(ref fontName, ref fontSize, ref fontColor, ref transparency, ref isBold, ref isItalic);
+                    result = textAreas[0].SetCurTextStyle(e, fontSize, fontColor[0], fontColor[1], fontColor[2], transparency, isBold, isItalic);
                 }
                 else
                 {
-                    result = textArea.SetCharsFontName(e);
+                    result = textAreas[0].SetCharsFontName(e);
                 }
 
                 if (result)
                 {
                     PDFEditHistory editHistory = new PDFEditHistory();
                     editHistory.EditPage = editPage;
-                    if (pdfPage != null)
+                    editHistory.PageIndex = pdfPage.PageIndex;
+                    ToolView.GetCPDFViewer().UndoManager.AddHistory(editHistory);
+                    ToolView.UpdateRender(oldRect, textAreas[0]);
+                }
+            }
+            else
+            {
+                GroupHistory groupHistory = new GroupHistory();
+                foreach (CPDFEditTextArea textArea in textAreas)
+                {
+                    if (textArea.SetCharsFontName(e))
                     {
+                        PDFEditHistory editHistory = new PDFEditHistory();
+                        editHistory.EditPage = editPage;
                         editHistory.PageIndex = pdfPage.PageIndex;
+                        groupHistory.Histories.Add(editHistory);
                     }
-                    ToolView.GetCPDFViewer()?.UndoManager.AddHistory(editHistory);
-                    ToolView.UpdateRender(oldRect, textArea);
-                    editPage.EndEdit();
                 }
+
+                ToolView.GetCPDFViewer()?.UndoManager.AddHistory(groupHistory);
+                ToolView.GetCPDFViewer()?.UpdateRenderFrame();
             }
 
-            if (EditEvent != null && textArea == null)
+            editPage.EndEdit();
+            if (EditEvents.Count > 0 && textAreas.Count > 0)
             {
-                EditEvent.FontName = e;
+                EditEvents.FirstOrDefault().FontName = e;
                 DefaultSettingParam defaultSettingParam = ToolView.GetDefaultSettingParam();
-                defaultSettingParam.SetPDFEditParamm(EditEvent);
+                defaultSettingParam.SetPDFEditParamm(EditEvents.FirstOrDefault());
             }
 
             //if (EditMultiEvents != null)
@@ -594,27 +759,30 @@ namespace ComPDFKit.Controls.Edit
         #endregion
 
         #region Text Edit
-        private void GetTextArea(out CPDFEditTextArea textArea, out CPDFPage pdfPage, out CPDFEditPage editPage)
+        private void GetTextArea(out List<CPDFEditTextArea> textAreas, out CPDFPage pdfPage, out CPDFEditPage editPage)
         {
-            textArea = null;
+            textAreas = new List<CPDFEditTextArea>();
             editPage = null;
             pdfPage = null;
             if (ToolView == null)
             {
                 return;
             }
-            if (EditEvent != null)
+            if (EditEvents != null && EditEvents.Count>0 )
             {
                 try
                 {
                     CPDFViewer pdfViewer = ToolView.GetCPDFViewer();
                     CPDFDocument pdfDoc = pdfViewer.GetDocument();
-                    pdfPage = pdfDoc.PageAtIndex(EditEvent.PageIndex);
+                    pdfPage = pdfDoc.PageAtIndex(EditEvents.FirstOrDefault().PageIndex);
                     editPage = pdfPage.GetEditPage();
                     List<CPDFEditArea> editAreas = editPage.GetEditAreaList();
-                    if (editAreas != null && editAreas.Count > EditEvent.EditIndex)
+                    foreach (TextEditParam editEvent in EditEvents)
                     {
-                        textArea = editAreas[EditEvent.EditIndex] as CPDFEditTextArea;
+                        if (editAreas != null && editAreas.Count > editEvent.EditIndex)
+                        {
+                            textAreas.Add(editAreas[editEvent.EditIndex] as CPDFEditTextArea);
+                        }
                     }
                 }
                 catch (Exception ex)
@@ -633,5 +801,46 @@ namespace ComPDFKit.Controls.Edit
             }
         }
         #endregion
+
+        private void chkMulti_Click(object sender, RoutedEventArgs e)
+        {
+            ToolView.SetIsMultiSelected((e.Source as CheckBox).IsChecked.GetValueOrDefault());
+        }
+
+        private void chkEditPen_Click(object sender, RoutedEventArgs e)
+        {
+            if ((e.Source as CheckBox).IsChecked.GetValueOrDefault())
+            {
+                ToolView.SetEditPen(null);
+            }
+            else
+            {
+                ToolView.SetEditPen(new Pen()
+                {
+                    Brush = new SolidColorBrush(Colors.Black),
+                    Thickness = 0
+                });
+            }
+            ShowBorder = ToolView.GetEditPen() == null || ToolView.GetEditPen().Thickness != 0;
+
+            ToolView.GetCPDFViewer().UpdateRenderFrame();
+        }
+
+        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;
+        }
+
+
+        protected void OnPropertyChanged([CallerMemberName] string propertyName = "") =>
+            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
     }
 }
+

+ 80 - 77
Demo/Examples/Compdfkit.Controls/Form/Property/CheckBoxProperty.xaml

@@ -18,85 +18,88 @@
             <cpdfcommon:PropertyPanelResourceConverter x:Key="PropertyPanelResourceConverter"></cpdfcommon:PropertyPanelResourceConverter>
         </ResourceDictionary>
     </UserControl.Resources>
-    <Grid>
-        <Grid.RowDefinitions>
-            <RowDefinition Height="40"/>
-            <RowDefinition Height="*"/>
-        </Grid.RowDefinitions>
-        <Border BorderThickness="0" BorderBrush="#1A000000">
-            <Grid  Height="40" Background="White" >
-                <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_Chb}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
-            </Grid>
-        </Border>
-        <TabControl Grid.Row="1" Style="{DynamicResource TabControlStyle1}" BorderThickness="0">
-            <TabItem Height="32" Style="{DynamicResource TabItemStyle1}" Header="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_General}">
-                <Grid>
-                    <Grid.ColumnDefinitions>
-                        <ColumnDefinition Width="16"/>
-                        <ColumnDefinition Width="*"/>
-                        <ColumnDefinition Width="16"/>
-                    </Grid.ColumnDefinitions>
-                    <StackPanel Grid.Column="1">
-                        <StackPanel  >
-                            <TextBlock Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Name}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
-                            <TextBox x:Name="FieldNameText" Height="32" Margin="0,8,0,0" TextChanged="FieldNameText_TextChanged"/>
-                        </StackPanel>
-                        <StackPanel >
-                            <TextBlock Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Visibility}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
-                            <ComboBox x:Name="FormFieldCmb" Margin="0,8,0,0" Height="32" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="FormFieldCmb_SelectionChanged">
-                                <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_Visible}"/>
-                                <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_Hidden}"/>
-                                <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_NoPrint}"/>
-                                <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_Print}"/>
-                            </ComboBox>
-                        </StackPanel>
-                    </StackPanel>
+    <ScrollViewer VerticalScrollBarVisibility="Auto">
+
+        <Grid>
+            <Grid.RowDefinitions>
+                <RowDefinition Height="40"/>
+                <RowDefinition Height="*"/>
+            </Grid.RowDefinitions>
+            <Border BorderThickness="0" BorderBrush="#1A000000">
+                <Grid  Height="40" Background="White" >
+                    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_Chb}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
                 </Grid>
-            </TabItem>
-            <TabItem Height="32" Style="{DynamicResource TabItemStyle1}" Header="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_Appearance}">
-                <Grid>
-                    <Grid.ColumnDefinitions>
-                        <ColumnDefinition Width="16"/>
-                        <ColumnDefinition Width="*"/>
-                        <ColumnDefinition Width="16"/>
-                    </Grid.ColumnDefinitions>
-                    <StackPanel Grid.Column="1">
-                        <StackPanel>
-                            <TextBlock  Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_StrokeColor}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
-                            <cpdfcommon:ColorPickerControl Margin="0,18,0,0" x:Name="BorderColorPickerControl" ColorChanged="BorderColorPickerControl_ColorChanged"/>
+            </Border>
+            <TabControl Grid.Row="1" Style="{DynamicResource TabControlStyle1}" BorderThickness="0">
+                <TabItem Height="32" Style="{DynamicResource TabItemStyle1}" Header="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_General}">
+                    <Grid>
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="16"/>
+                            <ColumnDefinition Width="*"/>
+                            <ColumnDefinition Width="16"/>
+                        </Grid.ColumnDefinitions>
+                        <StackPanel Grid.Column="1">
+                            <StackPanel  >
+                                <TextBlock Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Name}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
+                                <TextBox x:Name="FieldNameText" Height="32" Margin="0,8,0,0" TextChanged="FieldNameText_TextChanged"/>
+                            </StackPanel>
+                            <StackPanel >
+                                <TextBlock Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Visibility}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
+                                <ComboBox x:Name="FormFieldCmb" Margin="0,8,0,0" Height="32" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="FormFieldCmb_SelectionChanged">
+                                    <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_Visible}"/>
+                                    <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_Hidden}"/>
+                                    <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_NoPrint}"/>
+                                    <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_Print}"/>
+                                </ComboBox>
+                            </StackPanel>
                         </StackPanel>
-                        <StackPanel>
-                            <TextBlock  Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_BgColor}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
-                            <cpdfcommon:ColorPickerControl Margin="0,18,0,0" x:Name="BackgroundColorPickerControl" ColorChanged="BackgroundColorPickerControl_ColorChanged"/>
+                    </Grid>
+                </TabItem>
+                <TabItem Height="32" Style="{DynamicResource TabItemStyle1}" Header="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_Appearance}">
+                    <Grid>
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="16"/>
+                            <ColumnDefinition Width="*"/>
+                            <ColumnDefinition Width="16"/>
+                        </Grid.ColumnDefinitions>
+                        <StackPanel Grid.Column="1">
+                            <StackPanel>
+                                <TextBlock  Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_StrokeColor}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
+                                <cpdfcommon:ColorPickerControl Margin="0,18,0,0" x:Name="BorderColorPickerControl" ColorChanged="BorderColorPickerControl_ColorChanged"/>
+                            </StackPanel>
+                            <StackPanel>
+                                <TextBlock  Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_BgColor}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
+                                <cpdfcommon:ColorPickerControl Margin="0,18,0,0" x:Name="BackgroundColorPickerControl" ColorChanged="BackgroundColorPickerControl_ColorChanged"/>
+                            </StackPanel>
                         </StackPanel>
-                    </StackPanel>
-                </Grid>
-            </TabItem>
-            <TabItem Height="32" Style="{DynamicResource TabItemStyle1}" Header="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_Preferences}">
-                <Grid>
-                    <Grid.ColumnDefinitions>
-                        <ColumnDefinition Width="16"/>
-                        <ColumnDefinition Width="*"/>
-                        <ColumnDefinition Width="16"/>
-                    </Grid.ColumnDefinitions>
-                    <StackPanel Grid.Column="1">
-                        <StackPanel  >
-                            <TextBlock Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Check_Style}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
-                            <ComboBox x:Name="CheckButtonStyleCmb" Height="32" Margin="0,8,0,0" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="CheckButtonStyleCmb_SelectionChanged">
-                                <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Style_Check}"/>
-                                <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Style_Circle}"/>
-                                <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Style_Cross}"/>
-                                <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Style_Diamond}"/>
-                                <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Style_Square}"/>
-                                <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Style_Star}"/>
-                            </ComboBox>
+                    </Grid>
+                </TabItem>
+                <TabItem Height="32" Style="{DynamicResource TabItemStyle1}" Header="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_Preferences}">
+                    <Grid>
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="16"/>
+                            <ColumnDefinition Width="*"/>
+                            <ColumnDefinition Width="16"/>
+                        </Grid.ColumnDefinitions>
+                        <StackPanel Grid.Column="1">
+                            <StackPanel  >
+                                <TextBlock Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Check_Style}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
+                                <ComboBox x:Name="CheckButtonStyleCmb" Height="32" Margin="0,8,0,0" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="CheckButtonStyleCmb_SelectionChanged">
+                                    <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Style_Check}"/>
+                                    <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Style_Circle}"/>
+                                    <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Style_Cross}"/>
+                                    <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Style_Diamond}"/>
+                                    <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Style_Square}"/>
+                                    <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Style_Star}"/>
+                                </ComboBox>
+                            </StackPanel>
+                            <StackPanel >
+                                <CheckBox x:Name="chkSelected" Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Style_Default}" FontSize="14" VerticalContentAlignment="Center" FontFamily="Microsoft YaHei" FontWeight="Bold" Margin="0 14 0 0" Checked="chkSelected_Checked"  Unchecked="chkSelected_Unchecked"/>
+                            </StackPanel>
                         </StackPanel>
-                        <StackPanel >
-                            <CheckBox x:Name="chkSelected" Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Style_Default}" FontSize="14" VerticalContentAlignment="Center" FontFamily="Microsoft YaHei" FontWeight="Bold" Margin="0 14 0 0" Checked="chkSelected_Checked"  Unchecked="chkSelected_Unchecked"/>
-                        </StackPanel>
-                    </StackPanel>
-                </Grid>
-            </TabItem>
-        </TabControl>
-    </Grid>
+                    </Grid>
+                </TabItem>
+            </TabControl>
+        </Grid>
+    </ScrollViewer>
 </UserControl>

Diff do ficheiro suprimidas por serem muito extensas
+ 104 - 101
Demo/Examples/Compdfkit.Controls/Form/Property/ComboBoxProperty.xaml


+ 1 - 1
Demo/Examples/Compdfkit.Controls/Form/Property/ComboBoxProperty.xaml.cs

@@ -65,7 +65,7 @@ namespace ComPDFKit.Controls.PDFControl
             string familyName = string.Empty;
             string styleName = string.Empty;
 
-            CPDFFont.GetFamlyStyleName(widgetParam.FontName, ref familyName, ref styleName);
+            CPDFFont.GetFamilyStyleName(widgetParam.FontName, ref familyName, ref styleName);
 
             FontCmb.ItemsSource = CPDFFont.GetFontNameDictionary().Keys.ToList();
 

Diff do ficheiro suprimidas por serem muito extensas
+ 104 - 101
Demo/Examples/Compdfkit.Controls/Form/Property/ListBoxProperty.xaml


+ 1 - 1
Demo/Examples/Compdfkit.Controls/Form/Property/ListBoxProperty.xaml.cs

@@ -66,7 +66,7 @@ namespace ComPDFKit.Controls.PDFControl
             string familyName = string.Empty;
             string styleName = string.Empty;
 
-            CPDFFont.GetFamlyStyleName(widgetParam.FontName, ref familyName, ref styleName);
+            CPDFFont.GetFamilyStyleName(widgetParam.FontName, ref familyName, ref styleName);
 
             FontCmb.ItemsSource = CPDFFont.GetFontNameDictionary().Keys.ToList();
 

+ 90 - 88
Demo/Examples/Compdfkit.Controls/Form/Property/PushButtonProperty.xaml

@@ -36,98 +36,100 @@
             </Style>
         </ResourceDictionary>
     </UserControl.Resources>
-    <Grid>
-        <Grid.RowDefinitions>
-            <RowDefinition Height="40"/>
-            <RowDefinition Height="*"/>
-        </Grid.RowDefinitions>
-        <Border BorderThickness="0" BorderBrush="#1A000000">
-            <Grid  Height="40" Background="White" >
-                <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_Btn}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
-            </Grid>
-        </Border>
-        <TabControl x:Name="TopTabControl" Grid.Row="1" Style="{DynamicResource TabControlStyle1}" BorderThickness="0">
-            <TabItem Height="32" Style="{DynamicResource TabItemStyle1}" Header="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_General}">
-                <Grid>
-                    <Grid.ColumnDefinitions>
-                        <ColumnDefinition Width="16"/>
-                        <ColumnDefinition Width="*"/>
-                        <ColumnDefinition Width="16"/>
-                    </Grid.ColumnDefinitions>
-                    <StackPanel Grid.Column="1">
-                        <StackPanel>
-                            <TextBlock Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Name}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
-                            <TextBox x:Name="FieldNameText" Height="32" Margin="0,8,0,0" TextChanged="FieldNameText_TextChanged"/>
-                        </StackPanel>
-                        <StackPanel >
-                            <TextBlock Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Visibility}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
-                            <ComboBox x:Name="FormFieldCmb" Height="32" Margin="0,8,0,0" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="FormFieldCmb_SelectionChanged">
-                                <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_Visible}"/>
-                                <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_Hidden}"/>
-                                <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_NoPrint}"/>
-                                <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_Print}"/>
-                            </ComboBox>
-                        </StackPanel>
-                    </StackPanel>
+    <ScrollViewer VerticalScrollBarVisibility="Auto">
+        <Grid>
+            <Grid.RowDefinitions>
+                <RowDefinition Height="40"/>
+                <RowDefinition Height="*"/>
+            </Grid.RowDefinitions>
+            <Border BorderThickness="0" BorderBrush="#1A000000">
+                <Grid  Height="40" Background="White" >
+                    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_Btn}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
                 </Grid>
-            </TabItem>
-            <TabItem Height="32" Style="{DynamicResource TabItemStyle1}" Header="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_Appearance}">
-                <Grid>
-                    <Grid.ColumnDefinitions>
-                        <ColumnDefinition Width="16"/>
-                        <ColumnDefinition Width="*"/>
-                        <ColumnDefinition Width="16"/>
-                    </Grid.ColumnDefinitions>
-                    <StackPanel Grid.Column="1">
-                        <StackPanel>
-                            <TextBlock  Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_StrokeColor}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
-                            <cpdfcommon:ColorPickerControl Margin="0,18,0,0" x:Name="BorderColorPickerControl" ColorChanged="BorderColorPickerControl_ColorChanged"/>
-                        </StackPanel>
-                        <StackPanel>
-                            <TextBlock  Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_BgColor}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
-                            <cpdfcommon:ColorPickerControl Margin="0,18,0,0" x:Name="BackgroundColorPickerControl" ColorChanged="BackgroundColorPickerControl_ColorChanged"/>
-                        </StackPanel>
-                        <StackPanel>
-                            <TextBlock  Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_FontColor}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
-                            <cpdfcommon:ColorPickerControl Margin="0,18,0,0" x:Name="TextColorPickerControl" ColorChanged="TextColorPickerControl_ColorChanged"/>
-                        </StackPanel>
-                        <StackPanel>
-                            <TextBlock  Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Font}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold" />
-                            <ComboBox x:Name="FontCmb" Height="28" Margin="0,8,0,0" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" PreviewMouseDown="FontCmb_PreviewMouseDown" SelectionChanged="FontCmb_SelectionChanged">
-                            </ComboBox>
-                            <StackPanel Orientation="Horizontal"  Height="28" Margin="0,8,0,0">
-                                <ComboBox x:Name="FontStyleCmb" Width="148" Style="{StaticResource ComboBoxStyle1}" PreviewMouseDown="FontStyleCmb_PreviewMouseDown" SelectedIndex="0" SelectionChanged="FontStyleCmb_SelectionChanged">
+            </Border>
+            <TabControl x:Name="TopTabControl" Grid.Row="1" Style="{DynamicResource TabControlStyle1}" BorderThickness="0">
+                <TabItem Height="32" Style="{DynamicResource TabItemStyle1}" Header="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_General}">
+                    <Grid>
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="16"/>
+                            <ColumnDefinition Width="*"/>
+                            <ColumnDefinition Width="16"/>
+                        </Grid.ColumnDefinitions>
+                        <StackPanel Grid.Column="1">
+                            <StackPanel>
+                                <TextBlock Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Name}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
+                                <TextBox x:Name="FieldNameText" Height="32" Margin="0,8,0,0" TextChanged="FieldNameText_TextChanged"/>
+                            </StackPanel>
+                            <StackPanel >
+                                <TextBlock Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Visibility}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
+                                <ComboBox x:Name="FormFieldCmb" Height="32" Margin="0,8,0,0" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="FormFieldCmb_SelectionChanged">
+                                    <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_Visible}"/>
+                                    <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_Hidden}"/>
+                                    <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_NoPrint}"/>
+                                    <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_Print}"/>
                                 </ComboBox>
-                                <ComboBox x:Name="FontSizeCmb" Width="72" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="FontSizeCmb_SelectionChanged" Margin="12,0,0,0"/>
                             </StackPanel>
                         </StackPanel>
-                    </StackPanel>
-                </Grid>
-            </TabItem>
-            <TabItem Height="32" Style="{DynamicResource TabItemStyle1}" Header="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_Preferences}">
-                <Grid>
-                    <Grid.ColumnDefinitions>
-                        <ColumnDefinition Width="16"/>
-                        <ColumnDefinition Width="*"/>
-                        <ColumnDefinition Width="16"/>
-                    </Grid.ColumnDefinitions>
-                    <StackPanel Grid.Column="1">
-                        <StackPanel>
-                            <TextBlock Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_BtnContent}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
-                            <TextBox x:Name="ItemText" Height="32" Margin="0,8,0,0" TextChanged="ItemText_TextChanged"/>
+                    </Grid>
+                </TabItem>
+                <TabItem Height="32" Style="{DynamicResource TabItemStyle1}" Header="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_Appearance}">
+                    <Grid>
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="16"/>
+                            <ColumnDefinition Width="*"/>
+                            <ColumnDefinition Width="16"/>
+                        </Grid.ColumnDefinitions>
+                        <StackPanel Grid.Column="1">
+                            <StackPanel>
+                                <TextBlock  Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_StrokeColor}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
+                                <cpdfcommon:ColorPickerControl Margin="0,18,0,0" x:Name="BorderColorPickerControl" ColorChanged="BorderColorPickerControl_ColorChanged"/>
+                            </StackPanel>
+                            <StackPanel>
+                                <TextBlock  Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_BgColor}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
+                                <cpdfcommon:ColorPickerControl Margin="0,18,0,0" x:Name="BackgroundColorPickerControl" ColorChanged="BackgroundColorPickerControl_ColorChanged"/>
+                            </StackPanel>
+                            <StackPanel>
+                                <TextBlock  Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_FontColor}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
+                                <cpdfcommon:ColorPickerControl Margin="0,18,0,0" x:Name="TextColorPickerControl" ColorChanged="TextColorPickerControl_ColorChanged"/>
+                            </StackPanel>
+                            <StackPanel>
+                                <TextBlock  Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Font}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold" />
+                                <ComboBox x:Name="FontCmb" Height="28" Margin="0,8,0,0" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" PreviewMouseDown="FontCmb_PreviewMouseDown" SelectionChanged="FontCmb_SelectionChanged">
+                                </ComboBox>
+                                <StackPanel Orientation="Horizontal"  Height="28" Margin="0,8,0,0">
+                                    <ComboBox x:Name="FontStyleCmb" Width="148" Style="{StaticResource ComboBoxStyle1}" PreviewMouseDown="FontStyleCmb_PreviewMouseDown" SelectedIndex="0" SelectionChanged="FontStyleCmb_SelectionChanged">
+                                    </ComboBox>
+                                    <ComboBox x:Name="FontSizeCmb" Width="72" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="FontSizeCmb_SelectionChanged" Margin="12,0,0,0"/>
+                                </StackPanel>
+                            </StackPanel>
                         </StackPanel>
-                        <StackPanel>
-                            <TextBlock Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Btn_Action}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
-                            <ComboBox x:Name="TextAlignmentCmb" Height="32" Margin="0,8,0,0" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="TextAlignmentCmb_SelectionChanged">
-                                <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Action_None}"/>
-                                <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Action_Jump}"/>
-                                <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Action_Link}"/>
-                            </ComboBox>
-                            <TextBox x:Name="ActionContentText" Height="32" Margin="0,4,0,0" Text="123" TextChanged="ActionContentText_TextChanged" Visibility="Collapsed"/>
+                    </Grid>
+                </TabItem>
+                <TabItem Height="32" Style="{DynamicResource TabItemStyle1}" Header="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_Preferences}">
+                    <Grid>
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="16"/>
+                            <ColumnDefinition Width="*"/>
+                            <ColumnDefinition Width="16"/>
+                        </Grid.ColumnDefinitions>
+                        <StackPanel Grid.Column="1">
+                            <StackPanel>
+                                <TextBlock Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_BtnContent}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
+                                <TextBox x:Name="ItemText" Height="32" Margin="0,8,0,0" TextChanged="ItemText_TextChanged"/>
+                            </StackPanel>
+                            <StackPanel>
+                                <TextBlock Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Btn_Action}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
+                                <ComboBox x:Name="TextAlignmentCmb" Height="32" Margin="0,8,0,0" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="TextAlignmentCmb_SelectionChanged">
+                                    <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Action_None}"/>
+                                    <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Action_Jump}"/>
+                                    <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Action_Link}"/>
+                                </ComboBox>
+                                <TextBox x:Name="ActionContentText" Height="32" Margin="0,4,0,0" Text="123" TextChanged="ActionContentText_TextChanged" Visibility="Collapsed"/>
+                            </StackPanel>
                         </StackPanel>
-                    </StackPanel>
-                </Grid>
-            </TabItem>
-        </TabControl>
-    </Grid>
+                    </Grid>
+                </TabItem>
+            </TabControl>
+        </Grid>
+    </ScrollViewer>
 </UserControl>

+ 1 - 1
Demo/Examples/Compdfkit.Controls/Form/Property/PushButtonProperty.xaml.cs

@@ -79,7 +79,7 @@ namespace ComPDFKit.Controls.PDFControl
             string familyName = string.Empty;
             string styleName = string.Empty;
 
-            CPDFFont.GetFamlyStyleName(widgetParam.FontName,ref familyName,ref styleName);
+            CPDFFont.GetFamilyStyleName(widgetParam.FontName,ref familyName,ref styleName);
 
             FontCmb.ItemsSource = CPDFFont.GetFontNameDictionary().Keys.ToList();
 

+ 3 - 1
Demo/Examples/Compdfkit.Controls/Form/Property/RadioButtonProperty.xaml

@@ -19,7 +19,8 @@
             <cpdfcommon:PropertyPanelResourceConverter x:Key="PropertyPanelResourceConverter"></cpdfcommon:PropertyPanelResourceConverter>
         </ResourceDictionary>
     </UserControl.Resources>
-    <Grid>
+    <ScrollViewer VerticalScrollBarVisibility="Auto">
+        <Grid>
         <Grid.RowDefinitions>
             <RowDefinition Height="40"/>
             <RowDefinition Height="*"/>
@@ -115,4 +116,5 @@
             </TabItem>
         </TabControl>
     </Grid>
+    </ScrollViewer>
 </UserControl>

+ 29 - 26
Demo/Examples/Compdfkit.Controls/Form/Property/SignatureProperty.xaml

@@ -17,32 +17,35 @@
             <cpdfcommon:PropertyPanelResourceConverter x:Key="PropertyPanelResourceConverter"></cpdfcommon:PropertyPanelResourceConverter>
         </ResourceDictionary>
     </UserControl.Resources>
-    <Grid Background="White">
-        <Grid.RowDefinitions>
-            <RowDefinition Height="40"/>
-            <RowDefinition Height="*"/>
-        </Grid.RowDefinitions>
-        <Border BorderThickness="0" BorderBrush="#1A000000">
-            <Grid  Height="40" Background="White" >
-                <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_Sig}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
-            </Grid>
-        </Border>
-        <Grid Grid.Row="1">
-            <Grid.ColumnDefinitions>
-                <ColumnDefinition Width="16"/>
-                <ColumnDefinition Width="*"/>
-                <ColumnDefinition Width="16"/>
-            </Grid.ColumnDefinitions>
+    <ScrollViewer VerticalScrollBarVisibility="Auto">
+
+        <Grid Background="White">
+            <Grid.RowDefinitions>
+                <RowDefinition Height="40"/>
+                <RowDefinition Height="*"/>
+            </Grid.RowDefinitions>
+            <Border BorderThickness="0" BorderBrush="#1A000000">
+                <Grid  Height="40" Background="White" >
+                    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_Sig}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
+                </Grid>
+            </Border>
+            <Grid Grid.Row="1">
+                <Grid.ColumnDefinitions>
+                    <ColumnDefinition Width="16"/>
+                    <ColumnDefinition Width="*"/>
+                    <ColumnDefinition Width="16"/>
+                </Grid.ColumnDefinitions>
 
-            <StackPanel Grid.Column="1">
-                <TextBlock Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Visibility}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
-                <ComboBox x:Name="FormFieldCmb" Margin="0,8,0,0" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="FormFieldCmb_SelectionChanged" Height="32">
-                    <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_Visible}"/>
-                    <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_Hidden}"/>
-                    <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_NoPrint}"/>
-                    <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_Print}"/>
-                </ComboBox>
-            </StackPanel>
+                <StackPanel Grid.Column="1">
+                    <TextBlock Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Visibility}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
+                    <ComboBox x:Name="FormFieldCmb" Margin="0,8,0,0" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="FormFieldCmb_SelectionChanged" Height="32">
+                        <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_Visible}"/>
+                        <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_Hidden}"/>
+                        <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_NoPrint}"/>
+                        <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_Print}"/>
+                    </ComboBox>
+                </StackPanel>
+            </Grid>
         </Grid>
-    </Grid>
+    </ScrollViewer>
 </UserControl>

+ 91 - 88
Demo/Examples/Compdfkit.Controls/Form/Property/TextFieldProperty.xaml

@@ -19,98 +19,101 @@
             <cpdfcommon:PropertyPanelResourceConverter x:Key="PropertyPanelResourceConverter"></cpdfcommon:PropertyPanelResourceConverter>
         </ResourceDictionary>
     </UserControl.Resources>
-    <Grid>
-        <Grid.RowDefinitions>
-            <RowDefinition Height="40"/>
-            <RowDefinition Height="*"/>
-        </Grid.RowDefinitions>
-        <Border BorderThickness="0" BorderBrush="#1A000000">
-            <Grid  Height="40" Background="White" >
-                <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_TextField}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
-            </Grid>
-        </Border>
-        <TabControl Grid.Row="1" Style="{DynamicResource TabControlStyle1}" BorderThickness="0">
-            <TabItem Height="32" Style="{DynamicResource TabItemStyle1}" Header="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_General}">
-                <Grid>
-                    <Grid.ColumnDefinitions>
-                        <ColumnDefinition Width="16"/>
-                        <ColumnDefinition Width="*"/>
-                        <ColumnDefinition Width="16"/>
-                    </Grid.ColumnDefinitions>
-                    <StackPanel Grid.Column="1">
-                        <StackPanel  >
-                            <TextBlock Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Name}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
-                            <TextBox x:Name="FieldNameText" Height="32" Margin="0,8,0,0" TextChanged="FieldNameText_TextChanged"/>
-                        </StackPanel>
-                        <StackPanel >
-                            <TextBlock Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Visibility}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
-                            <ComboBox x:Name="FormFieldCmb" Height="32" Margin="0,8,0,0" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="FormFieldCmb_SelectionChanged">
-                                <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_Visible}"/>
-                                <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_Hidden}"/>
-                                <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_NoPrint}"/>
-                                <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_Print}"/>
-                            </ComboBox>
-                        </StackPanel>
-                    </StackPanel>
+    <ScrollViewer VerticalScrollBarVisibility="Auto">
+
+        <Grid>
+            <Grid.RowDefinitions>
+                <RowDefinition Height="40"/>
+                <RowDefinition Height="*"/>
+            </Grid.RowDefinitions>
+            <Border BorderThickness="0" BorderBrush="#1A000000">
+                <Grid  Height="40" Background="White" >
+                    <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_TextField}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
                 </Grid>
-            </TabItem>
-            <TabItem Height="32" Style="{DynamicResource TabItemStyle1}" Header="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_Appearance}">
-                <Grid>
-                    <Grid.ColumnDefinitions>
-                        <ColumnDefinition Width="16"/>
-                        <ColumnDefinition Width="*"/>
-                        <ColumnDefinition Width="16"/>
-                    </Grid.ColumnDefinitions>
-                    <StackPanel Grid.Column="1">
-                        <StackPanel>
-                            <TextBlock  Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_StrokeColor}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
-                            <cpdfcommon:ColorPickerControl Margin="0,18,0,0" x:Name="BorderColorPickerControl" ColorChanged="BorderColorPickerControl_ColorChanged"/>
-                        </StackPanel>
-                        <StackPanel>
-                            <TextBlock  Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_BgColor}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
-                            <cpdfcommon:ColorPickerControl Margin="0,18,0,0" x:Name="BackgroundColorPickerControl" ColorChanged="BackgroundColorPickerControl_ColorChanged"/>
-                        </StackPanel>
-                        <StackPanel>
-                            <TextBlock  Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_FontColor}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
-                            <cpdfcommon:ColorPickerControl Margin="0,18,0,0" x:Name="TextColorPickerControl" ColorChanged="TextColorPickerControl_ColorChanged"/>
-                        </StackPanel>
-                        <StackPanel>
-                            <TextBlock  Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Font}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold" />
-                            <ComboBox x:Name="FontCmb" Height="28" Margin="0,8,0,0" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="FontCmb_SelectionChanged">
-                            </ComboBox>
-                            <StackPanel Orientation="Horizontal"  Height="28" Margin="0,8,0,0">
-                                <ComboBox x:Name="FontStyleCmb"  Margin="0,0,0,0" Width="148" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="FontStyleCmb_SelectionChanged">
+            </Border>
+            <TabControl Grid.Row="1" Style="{DynamicResource TabControlStyle1}" BorderThickness="0">
+                <TabItem Height="32" Style="{DynamicResource TabItemStyle1}" Header="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_General}">
+                    <Grid>
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="16"/>
+                            <ColumnDefinition Width="*"/>
+                            <ColumnDefinition Width="16"/>
+                        </Grid.ColumnDefinitions>
+                        <StackPanel Grid.Column="1">
+                            <StackPanel  >
+                                <TextBlock Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Name}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
+                                <TextBox x:Name="FieldNameText" Height="32" Margin="0,8,0,0" TextChanged="FieldNameText_TextChanged"/>
+                            </StackPanel>
+                            <StackPanel >
+                                <TextBlock Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Visibility}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
+                                <ComboBox x:Name="FormFieldCmb" Height="32" Margin="0,8,0,0" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="FormFieldCmb_SelectionChanged">
+                                    <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_Visible}"/>
+                                    <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_Hidden}"/>
+                                    <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_NoPrint}"/>
+                                    <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Option_Print}"/>
                                 </ComboBox>
-                                <ComboBox x:Name="FontSizeCmb" Margin="4,0,0,0" Width="72" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="FontSizeCmb_SelectionChanged"/>
                             </StackPanel>
                         </StackPanel>
-                    </StackPanel>
-                </Grid>
-            </TabItem>
-            <TabItem Height="32" Style="{DynamicResource TabItemStyle1}" Header="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_Preferences}">
-                <Grid>
-                    <Grid.ColumnDefinitions>
-                        <ColumnDefinition Width="16"/>
-                        <ColumnDefinition Width="*"/>
-                        <ColumnDefinition Width="16"/>
-                    </Grid.ColumnDefinitions>
-                    <StackPanel Grid.Column="1">
-                        <StackPanel  >
-                            <TextBlock Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Alignment}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
-                            <ComboBox x:Name="TextAlignmentCmb" Height="32" Margin="0,8,0,0" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="TextAlignmentCmb_SelectionChanged">
-                                <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Alignment_Left}"/>
-                                <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Alignment_Center}"/>
-                                <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Alignment_Right}"/>
-                            </ComboBox>
+                    </Grid>
+                </TabItem>
+                <TabItem Height="32" Style="{DynamicResource TabItemStyle1}" Header="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_Appearance}">
+                    <Grid>
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="16"/>
+                            <ColumnDefinition Width="*"/>
+                            <ColumnDefinition Width="16"/>
+                        </Grid.ColumnDefinitions>
+                        <StackPanel Grid.Column="1">
+                            <StackPanel>
+                                <TextBlock  Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_StrokeColor}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
+                                <cpdfcommon:ColorPickerControl Margin="0,18,0,0" x:Name="BorderColorPickerControl" ColorChanged="BorderColorPickerControl_ColorChanged"/>
+                            </StackPanel>
+                            <StackPanel>
+                                <TextBlock  Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_BgColor}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
+                                <cpdfcommon:ColorPickerControl Margin="0,18,0,0" x:Name="BackgroundColorPickerControl" ColorChanged="BackgroundColorPickerControl_ColorChanged"/>
+                            </StackPanel>
+                            <StackPanel>
+                                <TextBlock  Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_FontColor}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
+                                <cpdfcommon:ColorPickerControl Margin="0,18,0,0" x:Name="TextColorPickerControl" ColorChanged="TextColorPickerControl_ColorChanged"/>
+                            </StackPanel>
+                            <StackPanel>
+                                <TextBlock  Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Font}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold" />
+                                <ComboBox x:Name="FontCmb" Height="28" Margin="0,8,0,0" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="FontCmb_SelectionChanged">
+                                </ComboBox>
+                                <StackPanel Orientation="Horizontal"  Height="28" Margin="0,8,0,0">
+                                    <ComboBox x:Name="FontStyleCmb"  Margin="0,0,0,0" Width="148" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="FontStyleCmb_SelectionChanged">
+                                    </ComboBox>
+                                    <ComboBox x:Name="FontSizeCmb" Margin="4,0,0,0" Width="72" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="FontSizeCmb_SelectionChanged"/>
+                                </StackPanel>
+                            </StackPanel>
                         </StackPanel>
-                        <StackPanel >
-                            <TextBlock Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_DefaultValue}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
-                            <TextBox x:Name="DefaultText" Margin="0,8,0,0"  Width="224" Height="112" AcceptsReturn="True" TextWrapping="Wrap" TextChanged="DefaultText_TextChanged"/>
-                            <CheckBox x:Name="chkMutiline" Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_MultiLine}" FontSize="14" VerticalContentAlignment="Center" Margin="0 14 0 0" Checked="chkMutiline_Checked" Unchecked="chkMutiline_Unchecked"/>
+                    </Grid>
+                </TabItem>
+                <TabItem Height="32" Style="{DynamicResource TabItemStyle1}" Header="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_Preferences}">
+                    <Grid>
+                        <Grid.ColumnDefinitions>
+                            <ColumnDefinition Width="16"/>
+                            <ColumnDefinition Width="*"/>
+                            <ColumnDefinition Width="16"/>
+                        </Grid.ColumnDefinitions>
+                        <StackPanel Grid.Column="1">
+                            <StackPanel  >
+                                <TextBlock Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Alignment}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
+                                <ComboBox x:Name="TextAlignmentCmb" Height="32" Margin="0,8,0,0" Style="{StaticResource ComboBoxStyle1}" SelectedIndex="0" SelectionChanged="TextAlignmentCmb_SelectionChanged">
+                                    <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Alignment_Left}"/>
+                                    <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Alignment_Center}"/>
+                                    <ComboBoxItem Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Alignment_Right}"/>
+                                </ComboBox>
+                            </StackPanel>
+                            <StackPanel >
+                                <TextBlock Margin="0,20,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_DefaultValue}" FontSize="14" FontFamily="Microsoft YaHei" FontWeight="Bold"/>
+                                <TextBox x:Name="DefaultText" Margin="0,8,0,0"  Width="224" Height="112" AcceptsReturn="True" TextWrapping="Wrap" TextChanged="DefaultText_TextChanged"/>
+                                <CheckBox x:Name="chkMutiline" Content="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_MultiLine}" FontSize="14" VerticalContentAlignment="Center" Margin="0 14 0 0" Checked="chkMutiline_Checked" Unchecked="chkMutiline_Unchecked"/>
+                            </StackPanel>
                         </StackPanel>
-                    </StackPanel>
-                </Grid>
-            </TabItem>
-        </TabControl>
-    </Grid>
+                    </Grid>
+                </TabItem>
+            </TabControl>
+        </Grid>
+    </ScrollViewer>
 </UserControl>

+ 1 - 1
Demo/Examples/Compdfkit.Controls/Form/Property/TextFieldProperty.xaml.cs

@@ -63,7 +63,7 @@ namespace ComPDFKit.Controls.PDFControl
             string familyName = string.Empty;
             string styleName = string.Empty;
 
-            CPDFFont.GetFamlyStyleName(widgetParam.FontName, ref familyName, ref styleName);
+            CPDFFont.GetFamilyStyleName(widgetParam.FontName, ref familyName, ref styleName);
 
             FontCmb.ItemsSource = CPDFFont.GetFontNameDictionary().Keys.ToList();
 

+ 2 - 2
Demo/Examples/Compdfkit.Controls/Measure/MeasureControl.xaml.cs

@@ -292,7 +292,7 @@ namespace ComPDFKit.Controls.Measure
                 if (annot.Type == C_ANNOTATION_TYPE.C_ANNOTATION_LINE)
                 {
                     CPDFLineAnnotation lineAnnot = annot as CPDFLineAnnotation;
-                    if (lineAnnot.IsMersured() && lineAnnot.Points != null && lineAnnot.Points.Count() == 2)
+                    if (lineAnnot.IsMeasured() && lineAnnot.Points != null && lineAnnot.Points.Count() == 2)
                     {
                         InfoPanel.SetMeasureInfo(lineAnnot);
                         SetMeasureInfoType(CPDFMeasureType.CPDF_DISTANCE_MEASURE);
@@ -302,7 +302,7 @@ namespace ComPDFKit.Controls.Measure
                 if (annot.Type == C_ANNOTATION_TYPE.C_ANNOTATION_POLYLINE)
                 {
                     CPDFPolylineAnnotation polylineAnnot = annot as CPDFPolylineAnnotation;
-                    if (polylineAnnot.IsMersured() && polylineAnnot.Points != null && polylineAnnot.Points.Count() >= 2)
+                    if (polylineAnnot.IsMeasured() && polylineAnnot.Points != null && polylineAnnot.Points.Count() >= 2)
                     {
                         InfoPanel.SetMeasureInfo(polylineAnnot);
                         SetMeasureInfoType(CPDFMeasureType.CPDF_PERIMETER_MEASURE);

+ 3 - 3
Demo/Examples/Compdfkit.Controls/Measure/MeasureSettingPanel.xaml.cs

@@ -219,7 +219,7 @@ namespace ComPDFKit.Controls.Measure
         {
             if(annot is CPDFLineAnnotation lineAnnot)
             {
-                if (lineAnnot.IsMersured())
+                if (lineAnnot.IsMeasured())
                 {
                     CPDFDistanceMeasure lineMeasure = lineAnnot.GetDistanceMeasure();
                     CPDFMeasureInfo info = lineMeasure.MeasureInfo;
@@ -240,7 +240,7 @@ namespace ComPDFKit.Controls.Measure
             }
             else if(annot is CPDFPolylineAnnotation polylineAnnot)
             {
-                if (polylineAnnot.IsMersured())
+                if (polylineAnnot.IsMeasured())
                 {
                     CPDFPerimeterMeasure polylineMeasure = polylineAnnot.GetPerimeterMeasure();
                     CPDFMeasureInfo info = polylineMeasure.MeasureInfo;
@@ -258,7 +258,7 @@ namespace ComPDFKit.Controls.Measure
             }
             else if(annot is CPDFPolygonAnnotation areaAnnot)
             {
-                if (areaAnnot.IsMersured())
+                if (areaAnnot.IsMeasured())
                 {
                     CPDFAreaMeasure areaMeasure = areaAnnot.GetAreaMeasure();
                     CPDFMeasureInfo info = areaMeasure.MeasureInfo;

+ 4 - 1
Demo/Examples/Compdfkit.Controls/PDFView/PDFDisplaySettings/PDFDisplaySettingsControl/CPDFDisplaySettingsControl.xaml

@@ -7,13 +7,15 @@
              xmlns:pdftoolsui="clr-namespace:ComPDFKit.Controls.PDFControlUI"
              xmlns:common="clr-namespace:ComPDFKit.Controls.Common"
              mc:Ignorable="d" 
-             d:DesignHeight="450" d:DesignWidth="800" Width="260"
+             d:DesignHeight="720" d:DesignWidth="280" Width="260"
              Background="#ffffff">
     <UserControl.Resources>
         <ResourceDictionary>
             <common:CommonResourceConverter x:Key="CommonResourceConverter"/>
         </ResourceDictionary>
     </UserControl.Resources>
+    <ScrollViewer VerticalScrollBarVisibility="Auto">
+        
     <Grid>
         <Grid.RowDefinitions>
             <RowDefinition Height="auto"></RowDefinition>
@@ -34,4 +36,5 @@
                 </StackPanel> 
         </Border>
     </Grid>
+    </ScrollViewer>
 </UserControl>

+ 0 - 0
Demo/Examples/Compdfkit.Controls/PDFView/PDFSearch/PDFSearchControl/CPDFSearchControl.xaml.cs


Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff