Selaa lähdekoodia

Merge branch 'compdfkit_demo_win_dev_v2.2.0' into compdfkit_demo_win_dev1_v2.2.0

# Conflicts:
#	Demo/Examples/ComPDFKit.Tool/CPDFToolManager.cs
#	Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.SelectedRect.cs
#	Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.TextEdit.cs
#	Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.xaml.cs
#	Demo/Examples/ComPDFKit.Tool/DrawTool/CreateAnnotTool.cs
#	Demo/Examples/ComPDFKit.Tool/DrawTool/SelectedRect.cs
#	Demo/Examples/ComPDFKit.Tool/DrawTool/SelectedRect.protected.cs
#	Demo/Examples/ComPDFKit.Tool/Help/ParamConverter.cs
#	Demo/Examples/ComPDFKit.Tool/Resource/Cursor/Rotation.cur
#	Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/LineMeasureParam.cs
#	Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/StampAnnotHistory.cs
liyijie 22 tuntia sitten
vanhempi
commit
9bb5ff9929
100 muutettua tiedostoa jossa 8345 lisäystä ja 1633 poistoa
  1. 85 70
      Demo/Examples/ComPDFKit.Tool/CPDFToolManager.cs
  2. 26 26
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.Annot.cs
  3. 4 4
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.AnnotEdit.cs
  4. 136 4
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.Command.cs
  5. 60 50
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.DataMethod.cs
  6. 2 2
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.FindReplace.cs
  7. 9 7
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.MultiSelectedRect.cs
  8. 1 1
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.PageSelected.cs
  9. 2 2
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.SelectedRect.cs
  10. 295 112
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.TextEdit.cs
  11. 22 13
      Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.xaml.cs
  12. 8 11
      Demo/Examples/ComPDFKit.Tool/ComPDFKit.Tool.csproj
  13. 33 30
      Demo/Examples/ComPDFKit.Tool/DrawTool/AnnotEdit.cs
  14. 248 196
      Demo/Examples/ComPDFKit.Tool/DrawTool/CreateAnnotTool.cs
  15. 1 27
      Demo/Examples/ComPDFKit.Tool/DrawTool/FrameSelectTool.cs
  16. 3 12
      Demo/Examples/ComPDFKit.Tool/DrawTool/MultiSelectedRect.cs
  17. 144 31
      Demo/Examples/ComPDFKit.Tool/DrawTool/SelectedRect.cs
  18. 369 34
      Demo/Examples/ComPDFKit.Tool/DrawTool/SelectedRect.protected.cs
  19. 100 39
      Demo/Examples/ComPDFKit.Tool/Help/ParamConverter.cs
  20. 2 2
      Demo/Examples/ComPDFKit.Tool/Properties/AssemblyInfo.cs
  21. BIN
      Demo/Examples/ComPDFKit.Tool/Resource/Cursor/Rotation.cur
  22. 11 7
      Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam.cs
  23. 1 1
      Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/FreeTextParam.cs
  24. 5 5
      Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/HighlightParam.cs
  25. 25 13
      Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/LineMeasureParam.cs
  26. 18 7
      Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/PolyLineMeasureParam.cs
  27. 47 24
      Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/PolygonMeasureParam.cs
  28. 1 1
      Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/SquigglyParam.cs
  29. 7 9
      Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/StampParam.cs
  30. 1 1
      Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/StrikeoutParam.cs
  31. 30 30
      Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/UnderlineParam.cs
  32. 7 7
      Demo/Examples/ComPDFKit.Tool/SettingParam/DefaultSettingParam.cs
  33. 1 10
      Demo/Examples/ComPDFKit.Tool/SettingParam/PDFEditParam/ImageEditParam.cs
  34. 1 3
      Demo/Examples/ComPDFKit.Tool/SettingParam/PDFEditParam/PDFEditParam.cs
  35. 31 0
      Demo/Examples/ComPDFKit.Tool/SettingParam/PDFEditParam/PathEditParam.cs
  36. 2 11
      Demo/Examples/ComPDFKit.Tool/SettingParam/PDFEditParam/TextEditParam.cs
  37. 0 1
      Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/HighlightAnnotHistory.cs
  38. 1 1
      Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/PolyLineMeasureAnnotHistory.cs
  39. 242 0
      Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/PolygonAnnotHistory.cs
  40. 45 33
      Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/PolygonMeasureAnnotHistory.cs
  41. 1 2
      Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/SquigglyAnnotHistory.cs
  42. 26 176
      Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/StampAnnotHistory.cs
  43. 21 4
      Demo/Examples/Compdfkit.Controls/Annotation/AnnotationControl/AnnotationControl.xaml.cs
  44. 8 1
      Demo/Examples/Compdfkit.Controls/Annotation/CPDFAnnotationPreviewerControl.xaml
  45. 60 1
      Demo/Examples/Compdfkit.Controls/Annotation/CPDFAnnotationPreviewerControl.xaml.cs
  46. 21 3
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationData/CPDFAnnotationData.cs
  47. 2 2
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationList/PDFAnnotationListControl/CPDFAnnotationListControl.xaml.cs
  48. 175 91
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationPanel/PDFAnnotationControl/CPDFAnnotationControl.xaml.cs
  49. 61 0
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationPanel/PDFAnnotationUI/CPDFCloudUI.xaml
  50. 339 0
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationPanel/PDFAnnotationUI/CPDFCloudUI.xaml.cs
  51. 52 52
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationPanel/PDFAnnotationUI/CPDFFreehandUI.xaml
  52. 1 1
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationPanel/PDFAnnotationUI/CPDFMarkupUI.xaml.cs
  53. 1 1
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationPanel/PDFAnnotationUI/CPDFShapeUI.xaml
  54. 1 2
      Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationPanel/PDFAnnotationUI/CPDFShapeUI.xaml.cs
  55. 19 5
      Demo/Examples/Compdfkit.Controls/Common/BarControl/CPDFAnnotationBarControl.xaml.cs
  56. 107 122
      Demo/Examples/Compdfkit.Controls/Common/BarControl/CPDFMeasureBarControl.xaml.cs
  57. 532 0
      Demo/Examples/Compdfkit.Controls/Common/BaseControl/MessageBoxEx.cs
  58. 67 2
      Demo/Examples/Compdfkit.Controls/Common/Helper/CommonHelper.cs
  59. 1 0
      Demo/Examples/Compdfkit.Controls/Common/Helper/LanguageHelper.cs
  60. 8 2
      Demo/Examples/Compdfkit.Controls/Common/HomePage/HomePageControl.xaml.cs
  61. 4 0
      Demo/Examples/Compdfkit.Controls/Common/PasswordControl/PasswordWindow.xaml.cs
  62. 2 3
      Demo/Examples/Compdfkit.Controls/Common/PropertyControl/ColorPickerControl.xaml.cs
  63. 116 0
      Demo/Examples/Compdfkit.Controls/Common/PropertyControl/PDFLineStyle/CPDFCloudStyleControl.xaml
  64. 102 0
      Demo/Examples/Compdfkit.Controls/Common/PropertyControl/PDFLineStyle/CPDFCloudStyleControl.xaml.cs
  65. 61 0
      Demo/Examples/Compdfkit.Controls/Compdfkit.Controls.csproj
  66. 447 0
      Demo/Examples/Compdfkit.Controls/Compress/CompressDialog.xaml
  67. 778 0
      Demo/Examples/Compdfkit.Controls/Compress/CompressDialog.xaml.cs
  68. 209 82
      Demo/Examples/Compdfkit.Controls/Edit/ContentEditCOntrol/ContentEditControl.xaml.cs
  69. 9 3
      Demo/Examples/Compdfkit.Controls/Edit/PDFContentEditControl.xaml.cs
  70. 0 14
      Demo/Examples/Compdfkit.Controls/Edit/PDFImageEdit/PDFImageUI/CPDFImageFlipUI.xaml.cs
  71. 2 2
      Demo/Examples/Compdfkit.Controls/Edit/PDFImageEdit/PDFImageUI/CPDFImageRotateUI.xaml.cs
  72. 122 0
      Demo/Examples/Compdfkit.Controls/Edit/PDFPathEdit/PDFPathEditControl/PDFPathEditControl.xaml
  73. 604 0
      Demo/Examples/Compdfkit.Controls/Edit/PDFPathEdit/PDFPathEditControl/PDFPathEditControl.xaml.cs
  74. 5 4
      Demo/Examples/Compdfkit.Controls/Edit/PDFTextEdit/PDFTextEditControl/PDFTextEditControl.xaml
  75. 131 29
      Demo/Examples/Compdfkit.Controls/Edit/PDFTextEdit/PDFTextEditControl/PDFTextEditControl.xaml.cs
  76. 58 0
      Demo/Examples/Compdfkit.Controls/Edit/PDFTextEdit/PDFTextEditUI/CPDFTextMarkupUI.xaml
  77. 37 0
      Demo/Examples/Compdfkit.Controls/Edit/PDFTextEdit/PDFTextEditUI/CPDFTextMarkupUI.xaml.cs
  78. 27 24
      Demo/Examples/Compdfkit.Controls/Measure/MeasureControl.xaml.cs
  79. 3 9
      Demo/Examples/Compdfkit.Controls/Measure/MeasureInfoPanel.xaml.cs
  80. 1 1
      Demo/Examples/Compdfkit.Controls/Measure/MeasurePropertyControl.xaml
  81. 146 10
      Demo/Examples/Compdfkit.Controls/Measure/MeasurePropertyControl.xaml.cs
  82. 2 1
      Demo/Examples/Compdfkit.Controls/Measure/Property/MultilineProperty.xaml
  83. 101 37
      Demo/Examples/Compdfkit.Controls/Measure/Property/MultilineProperty.xaml.cs
  84. 150 47
      Demo/Examples/Compdfkit.Controls/Measure/Property/PolygonalProperty.xaml.cs
  85. 1 1
      Demo/Examples/Compdfkit.Controls/Measure/Property/StraightnessProperty.xaml
  86. 111 36
      Demo/Examples/Compdfkit.Controls/Measure/Property/StraightnessProperty.xaml.cs
  87. 14 1
      Demo/Examples/Compdfkit.Controls/PDFView/PDFSearch/PDFSearchControl/CPDFSearchControl.xaml.cs
  88. 90 19
      Demo/Examples/Compdfkit.Controls/PDFView/PDFSearch/PDFSearchUI/CPDFSearchResultUI.xaml.cs
  89. 130 4
      Demo/Examples/Compdfkit.Controls/PDFView/PDFViewControl/PDFViewControl.xaml.cs
  90. 1 0
      Demo/Examples/Compdfkit.Controls/PageEdit/PDFPageEdit/CPDFPageEditControl.xaml.cs
  91. 2 2
      Demo/Examples/Compdfkit.Controls/Properties/AssemblyInfo.cs
  92. 142 0
      Demo/Examples/Compdfkit.Controls/Snapshot/SnapshotMenu.xaml
  93. 311 0
      Demo/Examples/Compdfkit.Controls/Snapshot/SnapshotMenu.xaml.cs
  94. 3 0
      Demo/Examples/Compdfkit.Controls/Strings/Common.resx
  95. 3 0
      Demo/Examples/Compdfkit.Controls/Strings/Common.zh.resx
  96. 405 0
      Demo/Examples/Compdfkit.Controls/Strings/Compress.Designer.cs
  97. 234 0
      Demo/Examples/Compdfkit.Controls/Strings/Compress.resx
  98. 234 0
      Demo/Examples/Compdfkit.Controls/Strings/Compress.zh.resx
  99. 18 0
      Demo/Examples/Compdfkit.Controls/Strings/PropertyPanel.Designer.cs
  100. 0 0
      Demo/Examples/Compdfkit.Controls/Strings/PropertyPanel.resx

+ 85 - 70
Demo/Examples/ComPDFKit.Tool/CPDFToolManager.cs

@@ -23,8 +23,6 @@ using System.Globalization;
 using ComPDFKitViewer.Layer;
 using ComPDFKitViewer;
 using ComPDFKitViewer.Annot;
-using System.Windows.Annotations;
-using ComPDFKit.Viewer.Annot;
 
 namespace ComPDFKit.Tool
 {
@@ -270,12 +268,12 @@ namespace ComPDFKit.Tool
             createContentEditType = editType;
             return true;
         }
+
         public CPDFEditType GetCreateContentEditType()
         {
             return createContentEditType;
         }
 
-
         public void ClearSelect()
         {
             /// Clear some UI effects of other modules
@@ -478,9 +476,19 @@ namespace ComPDFKit.Tool
                     e.Square.Width / e.annotData.CurrentZoom,
                     e.Square.Height / e.annotData.CurrentZoom
                     );
+
                 Rect rect = DpiHelper.StandardRectToPDFRect(rect1);
                 CRect cRect = new CRect((float)rect.Left, (float)rect.Bottom, (float)rect.Right, (float)rect.Top);
-                e.annotData.Annot.SetRect(cRect);
+                if (e.annotData.AnnotType == C_ANNOTATION_TYPE.C_ANNOTATION_STAMP)
+                {
+                    CPDFStampAnnotation stampAnnot = e.annotData.Annot as CPDFStampAnnotation;
+                    stampAnnot.SetSourceRect(cRect);
+                    stampAnnot.AnnotationRotator.SetRotation(-e.rotationAngle);
+                }
+                else
+                {
+                    e.annotData.Annot.SetRect(cRect);
+                }
             }
 
             switch (e.annotData.AnnotType)
@@ -498,7 +506,7 @@ namespace ComPDFKit.Tool
                         if (e.annotData.AnnotType != C_ANNOTATION_TYPE.C_ANNOTATION_SOUND)
                         {
                             e.annotData.Annot.UpdateAp();
-                            if(e.annotData.Annot is CPDFTextAnnotation)
+                            if (e.annotData.Annot is CPDFTextAnnotation)
                             {
                                 CommonHelper.UpdateStickyAP(e.annotData.Annot as CPDFTextAnnotation);
                             }
@@ -654,7 +662,6 @@ namespace ComPDFKit.Tool
                         List<Point> cPoints = new List<Point>();
                         for (int i = 0; i < e.Points.Count; i++)
                         {
-
                             Point cPoint = new Point((float)((e.Points[i].X - e.annotData.PaintOffset.X) / e.annotData.CurrentZoom),
                             (float)((e.Points[i].Y - e.annotData.PaintOffset.Y) / e.annotData.CurrentZoom));
                             cPoints.Add(cPoint);
@@ -697,27 +704,28 @@ namespace ComPDFKit.Tool
                         {
                             lineMeasure.SetLeadLength(-(float)saveLength);
                         }
+
                         if (lineCenterPoint.Y > crossCenterPoint.Y)
                         {
                             lineMeasure.SetLeadLength((float)saveLength);
                         }
+
                         if (lineCenterPoint.Y == crossCenterPoint.Y)
                         {
                             if (lineCenterPoint.X > crossCenterPoint.X)
                             {
                                 lineMeasure.SetLeadLength(-(float)saveLength);
                             }
+
                             if (lineCenterPoint.X < crossCenterPoint.X)
                             {
                                 lineMeasure.SetLeadLength((float)saveLength);
                             }
                         }
-                        lineMeasure.UpdateAnnotMeasure();
+
                         annotLine.UpdateAp();
-                        if (annotLine.IsMeasured())
-                        {
-                            PostMeasureInfo(this, annotLine);
-                        }
+                        lineMeasure.UpdateAnnotMeasure();
+                        PostMeasureInfo(this, annotLine);
                     }
                     else
                     {
@@ -748,25 +756,24 @@ namespace ComPDFKit.Tool
                             (float)((e.Points[i].Y - e.annotData.PaintOffset.Y) / e.annotData.CurrentZoom));
                             cPoints.Add(DataConversionForWPF.PointConversionForCPoint(DpiHelper.StandardPointToPDFPoint(cPoint)));
                         }
-                        CPDFPolygonAnnotation annotLine = (e.annotData.Annot as CPDFPolygonAnnotation);
-
-                        annotLine.SetPoints(cPoints);
 
+                        CPDFPolygonAnnotation polygonAnnot = (e.annotData.Annot as CPDFPolygonAnnotation);
+                        polygonAnnot.SetPoints(cPoints);
                         double left = cPoints.AsEnumerable().Select(x => x.x).Min();
                         double right = cPoints.AsEnumerable().Select(x => x.x).Max();
                         double top = cPoints.AsEnumerable().Select(x => x.y).Min();
                         double bottom = cPoints.AsEnumerable().Select(x => x.y).Max();
-
-                        annotLine.SetRect(new CRect(
+                        polygonAnnot.SetRect(new CRect(
                             (float)left,
                             (float)bottom,
                             (float)right,
                             (float)top));
-                        annotLine.GetAreaMeasure().UpdateAnnotMeasure();
-                        annotLine.UpdateAp();
-                        if (annotLine.IsMeasured())
+
+                        polygonAnnot.UpdateAp();
+                        if (polygonAnnot.IsMeasured())
                         {
-                            PostMeasureInfo(this, annotLine);
+                            polygonAnnot.GetAreaMeasure().UpdateAnnotMeasure();
+                            PostMeasureInfo(this, polygonAnnot);
                         }
                     }
                     break;
@@ -779,26 +786,24 @@ namespace ComPDFKit.Tool
                             (float)((e.Points[i].Y - e.annotData.PaintOffset.Y) / e.annotData.CurrentZoom));
                             cPoints.Add(DataConversionForWPF.PointConversionForCPoint(DpiHelper.StandardPointToPDFPoint(cPoint)));
                         }
-                        CPDFPolylineAnnotation annotLine = (e.annotData.Annot as CPDFPolylineAnnotation);
-
-                        annotLine.SetPoints(cPoints);
 
+                        CPDFPolylineAnnotation polylineAnnot = (e.annotData.Annot as CPDFPolylineAnnotation);
+                        polylineAnnot.SetPoints(cPoints);
                         double left = cPoints.AsEnumerable().Select(x => x.x).Min();
                         double right = cPoints.AsEnumerable().Select(x => x.x).Max();
                         double top = cPoints.AsEnumerable().Select(x => x.y).Min();
                         double bottom = cPoints.AsEnumerable().Select(x => x.y).Max();
-
-                        annotLine.SetRect(new CRect(
+                        polylineAnnot.SetRect(new CRect(
                             (float)left,
                             (float)bottom,
                             (float)right,
                             (float)top));
 
-                        annotLine.GetPerimeterMeasure().UpdateAnnotMeasure();
-                        annotLine.UpdateAp();
-                        if (annotLine.IsMeasured())
+                        polylineAnnot.UpdateAp();
+                        if (polylineAnnot.IsMeasured())
                         {
-                            PostMeasureInfo(this, annotLine);
+                            polylineAnnot.GetPerimeterMeasure().UpdateAnnotMeasure();
+                            PostMeasureInfo(this, polylineAnnot);
                         }
                     }
                     break;
@@ -831,14 +836,7 @@ namespace ComPDFKit.Tool
             annotHistory.CurrentParam = currentParam;
             annotHistory.Action = HistoryAction.Update;
             viewerTool.GetCPDFViewer().UndoManager.AddHistory(annotHistory);
-            if (e.annotData.Annot.IsMeasured())
-            {
-                viewerTool.GetCPDFViewer().UpdateRenderFrame();
-            }
-            else
-            {
-                viewerTool.GetCPDFViewer().UpdateAnnotFrame();
-            }
+            viewerTool.GetCPDFViewer().UpdateAnnotFrame();
         }
 
         private void ViewerTool_MouseLeftButtonUpHandler(object sender, MouseEventObject e)
@@ -882,11 +880,11 @@ namespace ComPDFKit.Tool
             if (e.hitTestType == MouseHitTestType.SelectRect)
             {
                 List<C_ANNOTATION_TYPE> list = new List<C_ANNOTATION_TYPE>()
-                        {
-                            C_ANNOTATION_TYPE.C_ANNOTATION_LINE,
-                            C_ANNOTATION_TYPE.C_ANNOTATION_POLYLINE,
-                            C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON,
-                        };
+                {
+                    C_ANNOTATION_TYPE.C_ANNOTATION_LINE,
+                    C_ANNOTATION_TYPE.C_ANNOTATION_POLYLINE,
+                    C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON,
+                };
                 if (list.Contains(e.annotType))
                 {
                     viewerTool.DrawEndEditAnnot();
@@ -1107,8 +1105,7 @@ namespace ComPDFKit.Tool
             }
         }
 
-        #region MouseLeftButtonUpCreateAnnot
-
+        #region MouseLeftButtonUpCreateAnnot 
         private void CreateAnnotTypeMouseLeftUp(ref MouseEventObject e)
         {
             //Mersured
@@ -1129,7 +1126,7 @@ namespace ComPDFKit.Tool
                         }
                         break;
                     case C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON:
-                        if ((cPDFAnnotation as CPDFPolygonAnnotation).IsMeasured())
+                        // if ((cPDFAnnotation as CPDFPolygonAnnotation).IsMeasured())
                         {
                             DefaultSettingParam defSetting = viewerTool.GetDefaultSettingParam();
                             if (defSetting.IsCreateSquarePolygonMeasure)
@@ -1157,7 +1154,7 @@ namespace ComPDFKit.Tool
 
         private void SaveCreateAnnotation(ref CPDFAnnotation annotation, ref MouseEventObject e)
         {
-            if (annotation == null)
+            if (annotation == null || !annotation.IsValid())
             {
                 return;
             }
@@ -1389,18 +1386,25 @@ namespace ComPDFKit.Tool
                                         (mousePoint.Y - pageBound.Y + (cropPoint.Y * viewerTool.GetCPDFViewer().GetZoom())) / viewerTool.GetCPDFViewer().GetZoom(),
                                         stampRect.Width, stampRect.Height)
                                         );
+
+                                    if (annotation.Page.Rotation % 2 != 0)
+                                    {
+                                        PDFRect = RotateRect90(PDFRect);
+                                    }
+
                                     CRect cStampRect = new CRect((float)PDFRect.Left, (float)PDFRect.Bottom, (float)PDFRect.Right, (float)PDFRect.Top);
-                                    annotation.SetRect(cStampRect);
+                                    annotation.SetSourceRect(cStampRect);
+                                    (annotation as CPDFStampAnnotation).AnnotationRotator.SetRotation(annotation.Page.Rotation * 90);
                                     annotation.UpdateAp();
                                     e.IsCreate = true;
                                     e.annotType = C_ANNOTATION_TYPE.C_ANNOTATION_STAMP;
                                     e.Data = GetAnnotExpandObject(annotation);
-                                    StampAnnotHistory freeTextAnnotHistory = new StampAnnotHistory();
+                                    StampAnnotHistory stampAnnotHistory = new StampAnnotHistory();
                                     AnnotParam annotParam = ParamConverter.AnnotConverter(viewerTool.GetCPDFViewer().GetDocument(), annotation);
                                     annotParam.AnnotIndex = annotation.Page.GetAnnotCount() - 1;
-                                    freeTextAnnotHistory.CurrentParam = (StampParam)annotParam;
-                                    freeTextAnnotHistory.PDFDoc = viewerTool.GetCPDFViewer().GetDocument();
-                                    viewerTool.GetCPDFViewer().UndoManager.AddHistory(freeTextAnnotHistory);
+                                    stampAnnotHistory.CurrentParam = annotParam;
+                                    stampAnnotHistory.PDFDoc = viewerTool.GetCPDFViewer().GetDocument();
+                                    viewerTool.GetCPDFViewer().UndoManager.AddHistory(stampAnnotHistory);
                                 }
                                 viewerTool.GetCPDFViewer().UpdateAnnotFrame();
                             }
@@ -1464,7 +1468,7 @@ namespace ComPDFKit.Tool
 
                 annotation.SetRect(cRect);
                 SaveSharpAnnotBoundText(annotation);
-                if (annotation.Type!=C_ANNOTATION_TYPE.C_ANNOTATION_TEXT)
+                if (annotation.Type != C_ANNOTATION_TYPE.C_ANNOTATION_TEXT)
                 {
                     annotation.UpdateAp();
                 }
@@ -1472,7 +1476,6 @@ namespace ComPDFKit.Tool
                 {
                     CommonHelper.UpdateStickyAP(annotation as CPDFTextAnnotation);
                 }
-               
 
                 AnnotHistory annotHistory = ParamConverter.CreateHistory(annotation);
                 if (annotHistory == null)
@@ -1536,14 +1539,14 @@ namespace ComPDFKit.Tool
                 return;
             }
 
-            CPDFTextPage textPage=  boundAnnot.Page.GetTextPage();
-            if (textPage == null || textPage.IsValid()==false)
+            CPDFTextPage textPage = boundAnnot.Page.GetTextPage();
+            if (textPage == null || textPage.IsValid() == false)
             {
                 return;
             }
 
             string boundText = textPage.GetBoundedText(boundAnnot.GetRect());
-            if(string.IsNullOrEmpty(boundText)==false)
+            if (string.IsNullOrEmpty(boundText) == false)
             {
                 boundAnnot.SetContent(boundText);
             }
@@ -2054,7 +2057,6 @@ namespace ComPDFKit.Tool
                                 viewerTool.DrawMoveFrameSelect();
                             }
                         }
-
                     }
 
                     if (cursor == Cursors.Arrow && createContentEditType == CPDFEditType.EditText)
@@ -2068,7 +2070,6 @@ namespace ComPDFKit.Tool
                 {
                     Cursor cursor = Cursors.Arrow;
                     MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(viewerTool.PDFViewer.GetViewForTag(viewerTool.MultiSelectedRectViewTag));
-
                     if (viewerTool.GetLastSelectedRect() != null)
                     {
                         if (editSelected)
@@ -2167,13 +2168,9 @@ namespace ComPDFKit.Tool
                                                 {
                                                     bool cansave = true;
                                                     CPDFPolygonAnnotation PolyAnnotation = (cPDFAnnotation as CPDFPolygonAnnotation);
-                                                    PolyAnnotation?.IsMeasured();
                                                     if (PolyAnnotation != null)
                                                     {
-                                                        if (PolyAnnotation.IsMeasured())
-                                                        {
-                                                            cansave = false;
-                                                        }
+                                                        cansave = false;
                                                     }
                                                     viewerTool.SetIsCanSave(cansave);
                                                 }
@@ -2208,12 +2205,13 @@ namespace ComPDFKit.Tool
                                     {
                                         if (!viewerTool.IsCanSave())
                                         {
-                                            viewerTool.SetIsCanSave(true);
+                                            BaseLayer baseLayer = viewerTool.PDFViewer.GetViewForTag(viewerTool.CreateAnnotTag);
+                                            bool finshed = (baseLayer as CreateAnnotTool).IsCreateFinshed();
+                                            viewerTool.SetIsCanSave(finshed);
                                         }
                                     }
                                     break;
                             }
-
                         }
                         else if (currentToolType == ToolType.WidgetEdit)
                         {
@@ -2274,11 +2272,14 @@ namespace ComPDFKit.Tool
                         }
                         else
                         {
-                            viewerTool.CleanEditAnnot();
-                            viewerTool.DrawStartSelectedRect();
-                            if (currentToolType == ToolType.WidgetEdit)
+                            if(currentToolType != ToolType.Viewer)
                             {
-                                viewerTool.MoveDrawWidget(true);
+                                viewerTool.CleanEditAnnot();
+                                viewerTool.DrawStartSelectedRect();
+                                if (currentToolType == ToolType.WidgetEdit)
+                                {
+                                    viewerTool.MoveDrawWidget(true);
+                                }
                             }
                         }
                     }
@@ -2347,7 +2348,7 @@ namespace ComPDFKit.Tool
 
                             EditAreaObject editAreaObject = viewerTool.GetEditAreaObjectForRect(viewerTool.GetLastSelectedRect());
                             if (pointControlType != PointControlType.None &&
-                                (editAreaObject.cPDFEditArea.Type == CPDFEditType.EditImage || pointControlType != PointControlType.Body))
+                                (editAreaObject.cPDFEditArea.Type != CPDFEditType.EditText || pointControlType != PointControlType.Body))
                             {
                                 switch (pointControlType)
                                 {
@@ -2432,5 +2433,19 @@ namespace ComPDFKit.Tool
 
             MouseRightButtonDownHandler?.Invoke(sender, e);
         }
+
+        private Rect RotateRect90(Rect rect)
+        {
+            double centerX = rect.Left + rect.Width / 2;
+            double centerY = rect.Top + rect.Height / 2;
+
+            double newWidth = rect.Height;
+            double newHeight = rect.Width;
+
+            double newLeft = centerX - newWidth / 2.0;
+            double newTop = centerY - newHeight / 2.0;
+
+            return new Rect(newLeft, newTop, newWidth, newHeight);
+        }
     }
 }

+ 26 - 26
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.Annot.cs

@@ -10,8 +10,6 @@ using ComPDFKitViewer.Layer;
 using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 using System.Windows.Input;
 using System.Windows;
 using ComPDFKit.Import;
@@ -20,12 +18,9 @@ using System.Windows.Controls;
 using System.Windows.Media;
 using static ComPDFKit.PDFAnnotation.CTextAttribute.CFontNameHelper;
 using ComPDFKitViewer.Helper;
-using Microsoft.SqlServer.Server;
 using ComPDFKit.Tool.Help;
-using System.Xml.Linq;
 using ComPDFKit.Tool.SettingParam;
 using ComPDFKit.Tool.UndoManger;
-using System.Windows.Controls.Primitives;
 using ComPDFKit.Measure;
 using System.Dynamic;
 
@@ -53,13 +48,14 @@ namespace ComPDFKit.Tool
         BaseAnnot caheMoveAnnot;
         internal BaseAnnot cacheHitTestAnnot;
         bool isCacheRedaction = false;
-        int createAnnotTag = -1;
         int selectedPageIndex = -1;
         int selectedAnnotIndex = -1;
         bool canSave = true;
         bool isHitTestLink = false;
         bool isHitTestRedact = false;
+
         public event EventHandler<MeasureEventArgs> MeasureChanged;
+        internal int CreateAnnotTag { get; private set; } = -1;
 
         public void InvokeMeasureChangeEvent(object sender, MeasureEventArgs e)
         {
@@ -127,7 +123,7 @@ namespace ComPDFKit.Tool
 
         protected bool AnnotHitTest()
         {
-            BaseAnnot baseAnnot = PDFViewer.AnnotHitTest(true);
+            BaseAnnot baseAnnot = PDFViewer.AnnotHitTest();
             if (baseAnnot != null)
             {
                 if ((baseAnnot as BaseWidget) != null)
@@ -135,11 +131,15 @@ namespace ComPDFKit.Tool
                     cacheHitTestAnnot = null;
                     return false;
                 }
+
                 cacheHitTestAnnot = baseAnnot;
                 return true;
             }
-            cacheHitTestAnnot = baseAnnot;
-            return false;
+            else
+            {
+                cacheHitTestAnnot = null;
+                return false;
+            }
         }
 
         public void SelectedAnnotForIndex(int pageIndex, int annotIndex)
@@ -166,7 +166,7 @@ namespace ComPDFKit.Tool
             CreateAnnotTool createAnnotTool = new CreateAnnotTool(GetMeasureSetting(), GetDefaultDrawParam(), GetDefaultSettingParam());
             int annotViewindex = PDFViewer.GetMaxViewIndex();
             PDFViewer.InsertView(annotViewindex, createAnnotTool);
-            createAnnotTag = createAnnotTool.GetResTag();
+            CreateAnnotTag = createAnnotTool.GetResTag();
             createAnnotTool.UpdateAnnotHandler += CreateAnnotTool_UpdateAnnotHandler;
             createAnnotTool.CreateFreetextCanceled += CreateAnnotTool_CreateFreetextCanceled;
             createAnnotTool.MeasureChanged += CreateAnnotTool_MeasureChanged;
@@ -206,7 +206,7 @@ namespace ComPDFKit.Tool
             {
                 return;
             }
-            BaseLayer baseLayer = PDFViewer.GetViewForTag(createAnnotTag);
+            BaseLayer baseLayer = PDFViewer.GetViewForTag(CreateAnnotTag);
             (baseLayer as CreateAnnotTool).SetIsProportionalScaling(isProportionalScaling);
         }
 
@@ -216,7 +216,7 @@ namespace ComPDFKit.Tool
             {
                 return 0;
             }
-            BaseLayer baseLayer = PDFViewer.GetViewForTag(createAnnotTag);
+            BaseLayer baseLayer = PDFViewer.GetViewForTag(CreateAnnotTag);
             return (baseLayer as CreateAnnotTool).GetMoveLength();
         }
 
@@ -228,7 +228,7 @@ namespace ComPDFKit.Tool
             }
 
             Point point = Mouse.GetPosition(this);
-            BaseLayer baseLayer = PDFViewer.GetViewForTag(createAnnotTag);
+            BaseLayer baseLayer = PDFViewer.GetViewForTag(CreateAnnotTag);
             PDFViewer.GetPointPageInfo(point, out int index, out Rect paintRect, out Rect pageBound);
             if (index < 0)
             {
@@ -240,7 +240,7 @@ namespace ComPDFKit.Tool
             {
                 DefaultSettingParam defaultSettingParam = GetDefaultSettingParam();
                 StampParam stampParam = defaultSettingParam.StampParamDef;
-                stampParam.Rotation = cPDFPage.Rotation;
+                stampParam.PageRotation = cPDFPage.Rotation;
                 defaultSettingParam.SetAnnotParam(stampParam);
             }
             Point cropPoint = new Point();
@@ -271,7 +271,7 @@ namespace ComPDFKit.Tool
                 return;
             }
             Point point = Mouse.GetPosition(this);
-            BaseLayer baseLayer = PDFViewer.GetViewForTag(createAnnotTag);
+            BaseLayer baseLayer = PDFViewer.GetViewForTag(CreateAnnotTag);
             PDFViewer.GetPointPageInfo(point, out int index, out Rect paintRect, out Rect pageBound);
             if (index < 0)
             {
@@ -309,7 +309,7 @@ namespace ComPDFKit.Tool
                 return;
             }
             Point point = Mouse.GetPosition(this);
-            BaseLayer baseLayer = PDFViewer.GetViewForTag(createAnnotTag);
+            BaseLayer baseLayer = PDFViewer.GetViewForTag(CreateAnnotTag);
             (baseLayer as CreateAnnotTool).MoveDraw(point, PDFViewer.GetZoom());
         }
 
@@ -320,7 +320,7 @@ namespace ComPDFKit.Tool
                 return;
             }
             Point point = Mouse.GetPosition(this);
-            BaseLayer baseLayer = PDFViewer.GetViewForTag(createAnnotTag);
+            BaseLayer baseLayer = PDFViewer.GetViewForTag(CreateAnnotTag);
             (baseLayer as CreateAnnotTool).CreateTextBox();
         }
 
@@ -330,7 +330,7 @@ namespace ComPDFKit.Tool
             {
                 return new Rect();
             }
-            BaseLayer baseLayer = PDFViewer.GetViewForTag(createAnnotTag);
+            BaseLayer baseLayer = PDFViewer.GetViewForTag(CreateAnnotTag);
             return (baseLayer as CreateAnnotTool).EndDraw();
         }
 
@@ -539,25 +539,25 @@ namespace ComPDFKit.Tool
 
         public Point GetStartPoint()
         {
-            BaseLayer baseLayer = PDFViewer.GetViewForTag(createAnnotTag);
+            BaseLayer baseLayer = PDFViewer.GetViewForTag(CreateAnnotTag);
             return (baseLayer as CreateAnnotTool).GetStartPoint();
         }
 
         public Point GetEndPoint()
         {
-            BaseLayer baseLayer = PDFViewer.GetViewForTag(createAnnotTag);
+            BaseLayer baseLayer = PDFViewer.GetViewForTag(CreateAnnotTag);
             return (baseLayer as CreateAnnotTool).GetEndPoint();
         }
 
         public List<Point> GetInkDrawPoints()
         {
-            BaseLayer baseLayer = PDFViewer.GetViewForTag(createAnnotTag);
+            BaseLayer baseLayer = PDFViewer.GetViewForTag(CreateAnnotTag);
             return (baseLayer as CreateAnnotTool).GetInkDrawPoints();
         }
 
         public List<Point> GetMeasureDrawPoints()
         {
-            BaseLayer baseLayer = PDFViewer.GetViewForTag(createAnnotTag);
+            BaseLayer baseLayer = PDFViewer.GetViewForTag(CreateAnnotTag);
             return (baseLayer as CreateAnnotTool).GetMeasureDrawPoints();
         }
 
@@ -568,7 +568,7 @@ namespace ComPDFKit.Tool
                 return new Rect();
             }
             Point point = Mouse.GetPosition(this);
-            BaseLayer baseLayer = PDFViewer.GetViewForTag(createAnnotTag);
+            BaseLayer baseLayer = PDFViewer.GetViewForTag(CreateAnnotTag);
             return (baseLayer as CreateAnnotTool).GetMaxRect();
         }
 
@@ -579,7 +579,7 @@ namespace ComPDFKit.Tool
                 return;
             }
             Point point = Mouse.GetPosition(this);
-            BaseLayer baseLayer = PDFViewer.GetViewForTag(createAnnotTag);
+            BaseLayer baseLayer = PDFViewer.GetViewForTag(CreateAnnotTag);
             (baseLayer as CreateAnnotTool).ClearDraw();
         }
 
@@ -809,7 +809,7 @@ namespace ComPDFKit.Tool
                         }
                     };
 
-                    BaseLayer createAnnotTool = PDFViewer?.GetView(createAnnotTag) as CreateAnnotTool;
+                    BaseLayer createAnnotTool = PDFViewer?.GetView(CreateAnnotTag) as CreateAnnotTool;
                     if (createAnnotTool != null)
                     {
                         createAnnotTool.Children.Add(textBorder);
@@ -932,7 +932,7 @@ namespace ComPDFKit.Tool
             {
                 return;
             }
-            BaseLayer removeLayer = PDFViewer?.GetView(createAnnotTag) as CreateAnnotTool;
+            BaseLayer removeLayer = PDFViewer?.GetView(CreateAnnotTag) as CreateAnnotTool;
             removeLayer.Children.Remove(textBorder);
         }
 

+ 4 - 4
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.AnnotEdit.cs

@@ -74,12 +74,12 @@ namespace ComPDFKit.Tool
             AnnotEdit annotEdit = CommonHelper.FindVisualChild<AnnotEdit>(baseLayer as CustomizeLayer);
             if (annotEdit != null)
             {
-                annotEdit.Draw();
                 annotEdit.OnMouseLeftButtonUp(point);
+                annotEdit.Draw();
             }
         }
 
-        public void CleanEditAnnot()
+        public void CleanEditAnnot(bool isDrawEditAnnot = false)
         {
             Point point = Mouse.GetPosition(this);
             BaseLayer baseLayer = PDFViewer.GetViewForTag(annotEditViewTag);
@@ -87,9 +87,10 @@ namespace ComPDFKit.Tool
             if (annotEdit != null)  
             {
                 annotEdit.ClearDraw();
-                IsDrawEditAnnot = false;
+                IsDrawEditAnnot = isDrawEditAnnot;
             }
         }
+  
 
         internal void DrawEditAnnotLayer()
         {
@@ -108,7 +109,6 @@ namespace ComPDFKit.Tool
         private bool DrawEditAnnotDownEvent()
         {
             BaseLayer baseLayer = PDFViewer.GetViewForTag(annotEditViewTag);
-
             AnnotEdit selectedRect = CommonHelper.FindVisualChild<AnnotEdit>(baseLayer as CustomizeLayer);
             if (selectedRect != null)
             {

+ 136 - 4
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.Command.cs

@@ -294,6 +294,12 @@ namespace ComPDFKit.Tool
                             e.CanExecute = true;
                             break;
                         }
+
+                        if (checkItem.EditType == CPDFEditType.EditPath && checkItem.EditAreaCopied)
+                        {
+                            e.CanExecute = true;
+                            break;
+                        }
                     }
                     try
                     {
@@ -474,6 +480,7 @@ namespace ComPDFKit.Tool
                         commandData.PDFRect = DataConversionForWPF.CRectConversionForRect(currentEditAreaObject.cPDFEditArea.GetFrame());
                         lastPDFEditArgsList.Add(commandData);
                     }
+
                     if (currentEditAreaObject.cPDFEditArea.Type == CPDFEditType.EditImage)
                     {
                         editType = CPDFEditType.EditImage;
@@ -489,6 +496,22 @@ namespace ComPDFKit.Tool
                             lastPDFEditArgsList.Add(commandData);
                         }
                     }
+
+                    if (currentEditAreaObject.cPDFEditArea.Type == CPDFEditType.EditPath)
+                    {
+                        editType = CPDFEditType.EditPath;
+                        CPDFEditPage editPage = currentEditAreaObject.cPDFEditPage;
+                        commandData.PDFRect = DataConversionForWPF.CRectConversionForRect(currentEditAreaObject.cPDFEditArea.GetFrame());
+                        commandData.EditAreaCopied = editPage.CopyEditArea(currentEditAreaObject.cPDFEditArea);
+                        commandData.EditType = CPDFEditType.EditPath;
+                        if (commandData.EditAreaCopied)
+                        {
+                            List<CPDFCopyEditArea> copyList = editPage.GetCopyEditAreaList();
+                            commandData.CopyArea = copyList[copyList.Count - 1];
+                            commandData.EditPage = editPage;
+                            lastPDFEditArgsList.Add(commandData);
+                        }
+                    }
                 }
                 else
                 {
@@ -535,6 +558,7 @@ namespace ComPDFKit.Tool
                                     commandData.PDFRect = DataConversionForWPF.CRectConversionForRect(editAreaObject.cPDFEditArea.GetFrame());
                                     lastPDFEditArgsList.Add(commandData);
                                 }
+
                                 if (editAreaObject.cPDFEditArea.Type == CPDFEditType.EditImage)
                                 {
                                     editType = CPDFEditType.EditImage;
@@ -550,6 +574,22 @@ namespace ComPDFKit.Tool
                                         lastPDFEditArgsList.Add(commandData);
                                     }
                                 }
+
+                                if (editAreaObject.cPDFEditArea.Type == CPDFEditType.EditPath)
+                                {
+                                    editType = CPDFEditType.EditPath;
+                                    CPDFEditPage editPage = editAreaObject.cPDFEditPage;
+                                    commandData.PDFRect = DataConversionForWPF.CRectConversionForRect(editAreaObject.cPDFEditArea.GetFrame());
+                                    commandData.EditAreaCopied = editPage.CopyEditArea(editAreaObject.cPDFEditArea);
+                                    commandData.EditType = CPDFEditType.EditPath;
+                                    if (commandData.EditAreaCopied)
+                                    {
+                                        List<CPDFCopyEditArea> copyList = editPage.GetCopyEditAreaList();
+                                        commandData.CopyArea = copyList[copyList.Count - 1];
+                                        commandData.EditPage = editPage;
+                                        lastPDFEditArgsList.Add(commandData);
+                                    }
+                                }
                             }
                         } 
                     }
@@ -592,6 +632,12 @@ namespace ComPDFKit.Tool
                     RemoveImageBlock();
                 }
 
+                if (currentEditAreaObject.cPDFEditArea.Type == CPDFEditType.EditPath)
+                {
+                    editType = CPDFEditType.EditPath;
+                    RemovePathBlock();
+                }
+
                 if (PDFViewer != null && PDFViewer.UndoManager != null)
                 {
                     PDFViewer.UndoManager.AddHistory(groupHistory);
@@ -635,6 +681,12 @@ namespace ComPDFKit.Tool
                                 editType = CPDFEditType.EditImage;
                                 RemoveImageBlock(editareaobject);
                             }
+
+                            if (editareaobject.cPDFEditArea.Type == CPDFEditType.EditPath)
+                            {
+                                editType = CPDFEditType.EditPath;
+                                RemovePathBlock(editareaobject);
+                            }
                         }
 
                         if (PDFViewer != null && PDFViewer.UndoManager != null)
@@ -847,6 +899,7 @@ namespace ComPDFKit.Tool
                         }
                     }
                 }
+
                 if (commandData.EditType == CPDFEditType.EditImage)
                 {
                     editType = CPDFEditType.EditImage;
@@ -854,7 +907,6 @@ namespace ComPDFKit.Tool
                     if (commandData.EditAreaCopied)
                     {
                         commandData.CopyArea?.PasteEditArea(editPage, new CPoint((float)offsetRect.Left, (float)offsetRect.Top));
-
                         editHistory.EditPage = editPage;
                         editHistory.PageIndex = pageIndex;
                         CPDFViewer pdfViewer = GetCPDFViewer();
@@ -903,6 +955,25 @@ namespace ComPDFKit.Tool
                     }
                 }
 
+                if (commandData.EditType == CPDFEditType.EditPath)
+                {
+                    editType = CPDFEditType.EditPath;
+                    PDFEditHistory editHistory = new PDFEditHistory();
+                    if (commandData.EditAreaCopied)
+                    {
+                        commandData.CopyArea?.PasteEditArea(editPage, new CPoint((float)offsetRect.Left, (float)offsetRect.Top));
+                        editHistory.EditPage = editPage;
+                        editHistory.PageIndex = pageIndex;
+                        CPDFViewer pdfViewer = GetCPDFViewer();
+                        if (pdfViewer != null && pdfViewer.UndoManager != null)
+                        {
+                            pdfViewer.UndoManager.AddHistory(editHistory);
+                        }
+
+                        SelectedEditAreaForIndex(pageIndex, editPage.GetEditAreaList().Count - 1, false);
+                    }
+                }
+
                 editPage.EndEdit();
             }
         }
@@ -1477,8 +1548,67 @@ namespace ComPDFKit.Tool
                             (annotHistory as CircleAnnotHistory).CurrentParam = (CircleParam)annotParam;
                         }
                         break;
+
                     case C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON:
+                        {
+                            CPDFDocument cPDFDocument = PDFViewer.GetDocument();
+                            Rect rect;
+                            annotHistory = new PolygonMeasureAnnotHistory();
+                            annotHistory.PDFDoc = cPDFDocument;
+                            int index = -1;
+                            if (point.Equals(new Point(-1, -1)))
+                            {
+                                index = item.PageIndex;
+                                rect = new Rect(
+                                    (item.ClientRect.left + 25),
+                                    (item.ClientRect.top + 25),
+                                    item.ClientRect.width(),
+                                    item.ClientRect.height()
+                                );
+                            }
+                            else
+                            {
+                                PDFViewer.GetPointPageInfo(point, out index, out Rect paintRect, out var pageBound);
+                                CRect cRect = item.ClientRect;
+                                Point zoomPoint = new Point((point.X - pageBound.X) / currentZoom, (point.Y - pageBound.Y) / currentZoom);
+                                Point pdfPoint = DpiHelper.StandardPointToPDFPoint(zoomPoint);
+                                rect = new Rect(
+                                    (pdfPoint.X - cRect.width() / 2),
+                                    (pdfPoint.Y - cRect.height() / 2),
+                                    cRect.width(),
+                                    cRect.height()
+                                );
+                            }
+
+                            CRect setRect = DataConversionForWPF.RectConversionForCRect(rect);
+                            PolygonMeasureParam newPolygonParam = new PolygonMeasureParam();
+                            item.CopyTo(newPolygonParam);
+                            if(newPolygonParam.SavePoints != null && newPolygonParam.SavePoints.Count>0)
+                            {
+                                float offsetX = setRect.left - item.ClientRect.left;
+                                float offsetY = setRect.top - item.ClientRect.top;
+                                List<CPoint> arrangeList = new List<CPoint>();
+                                foreach (CPoint addPoint in newPolygonParam.SavePoints)
+                                {
+                                    arrangeList.Add(new CPoint(addPoint.x + offsetX, addPoint.y + offsetY));
+                                }
+
+                                newPolygonParam.SavePoints = arrangeList;
+                                newPolygonParam.ClientRect = setRect;
+                            }
+
+                            CPDFPage cPDFPage = cPDFDocument.PageAtIndex(index);
+                            if (cPDFPage == null)
+                                return;
+
+                            CPDFAnnotation cPDFAnnotation = cPDFPage.CreateAnnot(newPolygonParam.CurrentType);
+                            CreateDefaultAnnot(cPDFAnnotation, newPolygonParam.CurrentType, newPolygonParam);
+                            cPDFAnnotation.UpdateAp();
+                            AnnotParam annotParam = ParamConverter.AnnotConverter(cPDFDocument, cPDFAnnotation);
+                            (annotHistory as PolygonMeasureAnnotHistory).CurrentParam = (PolygonMeasureParam)annotParam;
+                        }
                         break;
+
                     case C_ANNOTATION_TYPE.C_ANNOTATION_POLYLINE:
                         break;
                     case C_ANNOTATION_TYPE.C_ANNOTATION_STAMP:
@@ -1501,7 +1631,7 @@ namespace ComPDFKit.Tool
                             else
                             {
                                 PDFViewer.GetPointPageInfo(point, out index, out Rect paintRect, out var pageBound);
-                                CRect cRect = item.ClientRect;
+                                CRect cRect = (item as StampParam).SourceRect;
                                 Point zoomPoint = new Point((point.X - pageBound.X) / currentZoom, (point.Y - pageBound.Y) / currentZoom);
                                 Point pdfPoint = DpiHelper.StandardPointToPDFPoint(zoomPoint);
                                 rect = new Rect(
@@ -1518,8 +1648,9 @@ namespace ComPDFKit.Tool
                                 return;
 
                             CPDFAnnotation cPDFAnnotation = cPDFPage.CreateAnnot(item.CurrentType);
+                            (cPDFAnnotation as CPDFStampAnnotation).SetSourceRect(setRect);
+                            //cPDFAnnotation.SetRect(setRect);
                             CreateDefaultAnnot(cPDFAnnotation, item.CurrentType, item);
-                            cPDFAnnotation.SetRect(setRect);
                             cPDFAnnotation.UpdateAp();
                             AnnotParam annotParam = ParamConverter.AnnotConverter(cPDFDocument, cPDFAnnotation);
                             (annotHistory as StampAnnotHistory).CurrentParam = (StampParam)annotParam;
@@ -1637,8 +1768,8 @@ namespace ComPDFKit.Tool
                 {
                     return;
                 }
-                AnnotParam annotParam = null;
 
+                AnnotParam annotParam = null;
                 if (cacheHitTestAnnot is BaseWidget)
                 {
                     annotParam = ParamConverter.WidgetConverter(PDFViewer.GetDocument(), cacheHitTestAnnot.GetAnnotData().Annot);
@@ -1647,6 +1778,7 @@ namespace ComPDFKit.Tool
                 {
                     annotParam = ParamConverter.AnnotConverter(PDFViewer.GetDocument(), cacheHitTestAnnot.GetAnnotData().Annot);
                 }
+
                 if (annotParam != null)
                 {
                     notifyData = new ExpandoObject();

+ 60 - 50
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.DataMethod.cs

@@ -4,9 +4,6 @@ using ComPDFKit.PDFDocument.Action;
 using ComPDFKit.PDFDocument;
 using ComPDFKit.Tool.SettingParam;
 using ComPDFKitViewer;
-using System;
-using System.Collections.Generic;
-using System.Linq;
 using static ComPDFKit.PDFAnnotation.CTextAttribute.CFontNameHelper;
 using static ComPDFKit.PDFAnnotation.CTextAttribute;
 using ComPDFKit.Tool.Help;
@@ -27,6 +24,9 @@ namespace ComPDFKit.Tool
 
         public void CreateDefaultAnnot(CPDFAnnotation cPDFAnnotation, C_ANNOTATION_TYPE annotType, AnnotParam annotParam)
         {
+            if (cPDFAnnotation == null || !cPDFAnnotation.IsValid())
+                return;
+
             switch (annotType)
             {
                 case C_ANNOTATION_TYPE.C_ANNOTATION_NONE:
@@ -65,7 +65,6 @@ namespace ComPDFKit.Tool
                         {
                             DefaultLineAnnot(cPDFAnnotation, annotParam);
                         }
-
                     }
                     break;
                 case C_ANNOTATION_TYPE.C_ANNOTATION_SQUARE:
@@ -183,7 +182,7 @@ namespace ComPDFKit.Tool
             }
 
             TextAnnotation.SetColor(StickyNoteParamDef.StickyNoteColor);
-            if(string.IsNullOrEmpty(StickyNoteParamDef.IconName)==false)
+            if (string.IsNullOrEmpty(StickyNoteParamDef.IconName) == false)
             {
                 TextAnnotation.SetIconName(StickyNoteParamDef.IconName);
             }
@@ -266,9 +265,8 @@ namespace ComPDFKit.Tool
                 freeTextAnnotation.SetBgColor(FreeTextParam.BgColor);
             }
 
-            if(FreeTextParam.Dash!=null && FreeTextParam.Dash.Length>0)
+            if (FreeTextParam.Dash != null && FreeTextParam.Dash.Length > 0)
             {
-                //补充保存虚线样式
                 freeTextAnnotation.SetBorderStyle(C_BORDER_STYLE.BS_DASHDED, FreeTextParam.Dash);
             }
 
@@ -535,8 +533,8 @@ namespace ComPDFKit.Tool
 
         private void DefaultStampAnnot(CPDFAnnotation cPDFAnnotation, AnnotParam annotParam)
         {
-            CPDFStampAnnotation strikeoutAnnotation = (cPDFAnnotation as CPDFStampAnnotation);
-            if (strikeoutAnnotation == null)
+            CPDFStampAnnotation stampAnnot = (cPDFAnnotation as CPDFStampAnnotation);
+            if (stampAnnot == null)
             {
                 return;
             }
@@ -545,7 +543,6 @@ namespace ComPDFKit.Tool
             if (annotParam == null)
             {
                 DefaultSettingParam defaultSettingParam = GetDefaultSettingParam();
-
                 stampParam = defaultSettingParam.StampParamDef;
             }
             else
@@ -562,7 +559,8 @@ namespace ComPDFKit.Tool
                         {
                             stampText = string.Empty;
                         }
-                        strikeoutAnnotation.SetStandardStamp(stampText, stampParam.Rotation);
+
+                        stampAnnot.SetStandardStamp(stampText, stampParam.PageRotation);
                     }
                     break;
                 case C_STAMP_TYPE.IMAGE_STAMP:
@@ -574,12 +572,12 @@ namespace ComPDFKit.Tool
 
                         if (imageData != null && imageWidth > 0 && imageHeight > 0)
                         {
-                            strikeoutAnnotation.SetRect(new CRect(0, imageHeight, imageWidth, 0));
-                            strikeoutAnnotation.SetImageStamp(
+                            stampAnnot.SetRect(new CRect(0, imageHeight, imageWidth, 0));
+                            stampAnnot.SetImageStamp(
                                 imageData,
                                 imageWidth,
                                 imageHeight,
-                                stampParam.Rotation);
+                                stampParam.PageRotation);
                         }
                     }
                     break;
@@ -595,12 +593,12 @@ namespace ComPDFKit.Tool
                         {
                             stampText = string.Empty;
                         }
-                        strikeoutAnnotation.SetTextStamp(
+                        stampAnnot.SetTextStamp(
                             stampText,
                             dateText,
                             stampParam.TextStampShape,
                             stampParam.TextStampColor,
-                            stampParam.Rotation);
+                            stampParam.PageRotation);
                     }
                     break;
                 default:
@@ -637,9 +635,9 @@ namespace ComPDFKit.Tool
             InkAnnotation.SetThickness((float)inkParam.Thickness);
             CPDFInkAnnotation inkAnnot = cPDFAnnotation as CPDFInkAnnotation;
             inkAnnot.SetInkPath(inkParam.InkPath);
-            if(inkParam.Dash!=null && inkParam.Dash.Length>0)
+            if (inkParam.Dash != null && inkParam.Dash.Length > 0)
             {
-                inkAnnot.SetBorderStyle(C_BORDER_STYLE.BS_DASHDED,inkParam.Dash);
+                inkAnnot.SetBorderStyle(C_BORDER_STYLE.BS_DASHDED, inkParam.Dash);
             }
             else
             {
@@ -728,7 +726,6 @@ namespace ComPDFKit.Tool
             textAttr.FontSize = (float)redactParam.FontSize;
             textAttr.FontName = redactParam.FontName;
             redactAnnotation.SetTextAttribute(textAttr);
-
             DefaultAnnot(cPDFAnnotation, redactParam);
         }
 
@@ -798,68 +795,81 @@ namespace ComPDFKit.Tool
         private void DefaultPolygonMeasureAnnot(CPDFAnnotation cPDFAnnotation, AnnotParam annotParam)
         {
             CPDFPolygonAnnotation PolyAnnotation = (cPDFAnnotation as CPDFPolygonAnnotation);
+            bool IsOpenMeasure = true;
             if (PolyAnnotation == null)
             {
                 return;
             }
-            if (!PolyAnnotation.IsMeasured() && annotParam != null)
-            {
-                return;
-            }
-            PolygonMeasureParam MeasureParam;
+
+            PolygonMeasureParam polyonMeasureParam;
             if (annotParam == null)
             {
                 DefaultSettingParam defaultSettingParam = GetDefaultSettingParam();
-
-                MeasureParam = defaultSettingParam.PolygonMeasureParamDef;
+                polyonMeasureParam = defaultSettingParam.PolygonMeasureParamDef;
+                IsOpenMeasure = defaultSettingParam.IsOpenMeasure;
             }
             else
             {
-                MeasureParam = annotParam as PolygonMeasureParam;
+                polyonMeasureParam = annotParam as PolygonMeasureParam;
+                IsOpenMeasure = defaultSettingParam.IsOpenMeasure; 
             }
 
-            if (MeasureParam.LineColor != null)
+            if (polyonMeasureParam.LineColor != null)
             {
-                PolyAnnotation.SetLineColor(MeasureParam.LineColor);
+                PolyAnnotation.SetLineColor(polyonMeasureParam.LineColor);
             }
-            PolyAnnotation.SetLineWidth((float)MeasureParam.LineWidth);
 
-            if (MeasureParam.LineDash != null)
+            PolyAnnotation.SetLineWidth((float)polyonMeasureParam.LineWidth);
+            if (polyonMeasureParam.LineDash != null)
             {
-                if (MeasureParam.LineDash.Length == 0)
+                if (polyonMeasureParam.LineDash.Length == 0)
                 {
                     PolyAnnotation.SetBorderStyle(C_BORDER_STYLE.BS_SOLID, new float[0]);
                 }
                 else
                 {
-                    PolyAnnotation.SetBorderStyle(C_BORDER_STYLE.BS_DASHDED, MeasureParam.LineDash);
+                    PolyAnnotation.SetBorderStyle(C_BORDER_STYLE.BS_DASHDED, polyonMeasureParam.LineDash);
                 }
             }
 
-            if (MeasureParam.HasFillColor && MeasureParam.FillColor != null && MeasureParam.FillColor.Length == 3)
+            if (polyonMeasureParam.HasFillColor && polyonMeasureParam.FillColor != null && polyonMeasureParam.FillColor.Length == 3)
             {
-                PolyAnnotation.SetBgColor(MeasureParam.FillColor);
+                PolyAnnotation.SetBgColor(polyonMeasureParam.FillColor);
             }
 
-            CTextAttribute textAttribute = new CTextAttribute();
-            textAttribute.FontColor = MeasureParam.FontColor;
-            textAttribute.FontSize = (float)MeasureParam.FontSize;
-            textAttribute.FontName = CFontNameHelper.ObtainFontName(CFontNameHelper.GetFontType(MeasureParam.FontName),
-                        MeasureParam.IsBold,
-                        MeasureParam.IsItalic);
-            PolyAnnotation.SetTextAttribute(textAttribute);
-            if (MeasureParam.measureInfo != null)
+            if(polyonMeasureParam.BorderEffector != null)
             {
-                CPDFAreaMeasure polygonMeasure = PolyAnnotation.GetAreaMeasure();
-                if (polygonMeasure != null)
+                PolyAnnotation.SetAnnotBorderEffector(polyonMeasureParam.BorderEffector);
+            }
+
+            if (polyonMeasureParam.SavePoints != null && polyonMeasureParam.SavePoints.Count>0)
+            {
+                PolyAnnotation.SetPoints(polyonMeasureParam.SavePoints);
+            }
+
+            if (IsOpenMeasure)
+            {
+                CTextAttribute textAttribute = new CTextAttribute();
+                textAttribute.FontColor = polyonMeasureParam.FontColor;
+                textAttribute.FontSize = (float)polyonMeasureParam.FontSize;
+                textAttribute.FontName = CFontNameHelper.ObtainFontName(CFontNameHelper.GetFontType(polyonMeasureParam.FontName),
+                            polyonMeasureParam.IsBold,
+                            polyonMeasureParam.IsItalic);
+                PolyAnnotation.SetTextAttribute(textAttribute);
+                if (polyonMeasureParam.measureInfo != null)
                 {
-                    polygonMeasure.SetMeasureInfo(MeasureParam.measureInfo);
-                    polygonMeasure.SetMeasureScale(MeasureParam.measureInfo.RulerBase, MeasureParam.measureInfo.RulerBaseUnit,
-                                                   MeasureParam.measureInfo.RulerTranslate, MeasureParam.measureInfo.RulerTranslateUnit);
-                    polygonMeasure.UpdateAnnotMeasure();
+                    CPDFAreaMeasure polygonMeasure = PolyAnnotation.GetAreaMeasure();
+                    if (polygonMeasure != null)
+                    {
+                        polygonMeasure.SetMeasureInfo(polyonMeasureParam.measureInfo);
+                        polygonMeasure.SetMeasureScale(polyonMeasureParam.measureInfo.RulerBase, polyonMeasureParam.measureInfo.RulerBaseUnit,
+                                                       polyonMeasureParam.measureInfo.RulerTranslate, polyonMeasureParam.measureInfo.RulerTranslateUnit);
+                        polygonMeasure.UpdateAnnotMeasure();
+                    }
                 }
             }
-            DefaultAnnot(cPDFAnnotation, MeasureParam);
+
+            DefaultAnnot(cPDFAnnotation, polyonMeasureParam);
         }
 
         private void DefaultPolyLineMeasureAnnot(CPDFAnnotation cPDFAnnotation, AnnotParam annotParam)

+ 2 - 2
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.FindReplace.cs

@@ -102,7 +102,7 @@ namespace ComPDFKit.Tool
             // Start searching from the currently displayed page
             CPDFPage pdfPage = GetCPDFViewer().GetDocument().PageAtIndex(nextPageIndex);
             findSelectionEditPage = pdfPage.GetEditPage();
-            findSelectionEditPage.BeginEdit(CPDFEditType.EditText | CPDFEditType.EditImage);
+            findSelectionEditPage.BeginEdit(CPDFEditType.EditText | CPDFEditType.EditImage | CPDFEditType.EditPath);
 
             // If the passed value is null, it will cause the program to freeze
             if (string.IsNullOrEmpty(findText))
@@ -334,7 +334,7 @@ namespace ComPDFKit.Tool
             {
                 CPDFPage page = PDFViewer.GetDocument().PageAtIndex(pageIndex);
                 CPDFEditPage editPage = page.GetEditPage();
-                editPage.BeginEdit(CPDFEditType.EditText | CPDFEditType.EditImage);
+                editPage.BeginEdit(CPDFEditType.EditText | CPDFEditType.EditImage | CPDFEditType.EditPath);
                 editPage.FindText(findText, options);
                 List<CPDFEditTextFindSelection> editTextFindSelectionList = editPage.GetTextFindSelectionList();
 

+ 9 - 7
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.MultiSelectedRect.cs

@@ -1,4 +1,5 @@
-using ComPDFKit.Tool.DrawTool;
+using ComPDFKit.PDFPage.Edit;
+using ComPDFKit.Tool.DrawTool;
 using ComPDFKit.Tool.Help;
 using ComPDFKit.Viewer.Layer;
 using System;
@@ -235,6 +236,13 @@ namespace ComPDFKit.Tool
             MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(MultiSelectedRectViewTag));
             if (multiSelectedRect != null)
             {
+                if(editAreaList.Count != 0)
+                {
+                    cachePathList.Clear();
+                    cachePathList = new List<CPDFEditPathArea>();
+                    GetDrawPathList(Mouse.GetPosition(this));
+                }
+
                 multiSelectedRect.Children.Clear();
                 multiSelectedRect.CleanMulitSelectedRect();
                 editAreaMultiIndex.Clear();
@@ -246,7 +254,6 @@ namespace ComPDFKit.Tool
         public void DrawStartSelectedMultiRect()
         {
             MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(MultiSelectedRectViewTag));
-
             if (multiSelectedRect != null)
             {
                 Point point = Mouse.GetPosition(this);
@@ -258,7 +265,6 @@ namespace ComPDFKit.Tool
         public void DrawMoveSelectedMultiRect()
         {
             MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(MultiSelectedRectViewTag));
-
             if (multiSelectedRect != null&& multiSelectedRect.Children.Count>0)
             {
                 Point point = Mouse.GetPosition(this);
@@ -269,7 +275,6 @@ namespace ComPDFKit.Tool
         public void DrawEndSelectedMultiRect()
         {
             MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(MultiSelectedRectViewTag));
-
             if (multiSelectedRect != null)
             {
                 Point point = Mouse.GetPosition(this);
@@ -285,9 +290,6 @@ namespace ComPDFKit.Tool
             {
                 multiSelectedRect.ClearDraw();
                 multiSelectedRect.CleanMulitSelectedRect();
-
-                Point point = Mouse.GetPosition(this);
-
                 switch (multiSelectedRect.GetSelectedType())
                 {
                     case SelectedType.Annot:

+ 1 - 1
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.PageSelected.cs

@@ -213,7 +213,7 @@ namespace ComPDFKit.Tool
             if (pageSelectedRect != null)
             {
                 Point point = Mouse.GetPosition(this);
-                BaseLayer baseLayer = PDFViewer.GetViewForTag(createAnnotTag);
+                BaseLayer baseLayer = PDFViewer.GetViewForTag(CreateAnnotTag);
                 PDFViewer.GetPointPageInfo(point, out int index, out Rect paintRect, out Rect pageBound);
                 if (index < 0)
                 {

+ 2 - 2
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.SelectedRect.cs

@@ -155,7 +155,7 @@ namespace ComPDFKit.Tool
             SelectedRect selectedRect = CommonHelper.FindVisualChild<SelectedRect>(baseLayer as CustomizeLayer);
             if (selectedRect != null)
             {
-                selectedRect.SetAnnotData(selectData);
+                selectedRect.SetAnnotData(selectData,PDFViewer);
             }
         }
 
@@ -171,7 +171,7 @@ namespace ComPDFKit.Tool
                 }
                 else
                 {
-                    selectedRect.SetAnnotData(annotData);
+                    selectedRect.SetAnnotData(annotData, PDFViewer);
                 }
             }
         }

+ 295 - 112
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.TextEdit.cs

@@ -13,7 +13,6 @@ using ComPDFKitViewer.Helper;
 using ComPDFKitViewer.Layer;
 using System;
 using System.Collections.Generic;
-using System.Diagnostics;
 using System.Linq;
 using System.Text;
 using System.Threading;
@@ -112,7 +111,7 @@ namespace ComPDFKit.Tool
         private int selectedEditAreaIndex = -1;
         private bool selectAllCharsForLine = false;
         private CPoint rawHitPos;
-        private CPDFEditType contentEditType = CPDFEditType.EditText | CPDFEditType.EditImage;
+        private CPDFEditType contentEditType = CPDFEditType.EditText | CPDFEditType.EditImage | CPDFEditType.EditPath;
 
         /// <summary>
         /// Save Current Crop Box
@@ -151,6 +150,10 @@ namespace ComPDFKit.Tool
 
         private List<SelectedRect> text = new List<SelectedRect>();
 
+        private List<SelectedRect> path = new List<SelectedRect>();
+
+        private List<CPDFEditPathArea> cachePathList = new List<CPDFEditPathArea>();
+
         protected List<PointControlType> ignoreTextPoints { get; set; } = new List<PointControlType>();
 
         protected List<PointControlType> ignoreImagePoints { get; set; } = new List<PointControlType>();
@@ -234,6 +237,11 @@ namespace ComPDFKit.Tool
             selectedEditPageIndex = pageIndex;
             selectedEditAreaIndex = editAreaIndex;
             this.drawCaret = drawCaret;
+            //if ((pageIndex < 0 || editAreaIndex < 0) && cachePathList.Count != 0)
+            //{
+            //    cachePathList.Clear();
+            //    cachePathList = new List<CPDFEditPathArea>();
+            //}
         }
 
         /// <summary>
@@ -384,18 +392,21 @@ namespace ComPDFKit.Tool
             hitTestRects.Clear();
             image.Clear();
             text.Clear();
-            BaseLayer customizeLayer = PDFViewer.GetViewForTag(textEditTag);
+            path.Clear();
 
+            BaseLayer customizeLayer = PDFViewer.GetViewForTag(textEditTag);
             customizeLayer.Children.Clear();
             operateChildrenIndex = -1;
             CaretVisual caretVisual = new CaretVisual(GetDefaultDrawParam());
             customizeLayer.Children.Add(caretVisual);
 
-            currentZoom = currentRenderFrame.ZoomFactor;
-
+            MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(MultiSelectedRectViewTag));
             foreach (RenderData item in currentRenderFrame.GetRenderDatas())
             {
                 if (item.CPDFEditPageObj == null)
+                    continue;
+
+                foreach (CPDFEditArea editArea in item.CPDFEditPageObj.GetEditAreaList().AsEnumerable().Reverse())
                 {
                     continue;
                 }
@@ -406,14 +417,15 @@ namespace ComPDFKit.Tool
                     selectedRect.SetDrawMoveType(DrawMoveType.kReferenceLine);
                     customizeLayer.Children.Add(selectedRect);
 
-                    Rect TextBlock = DataConversionForWPF.CRectConversionForRect(editArea.GetFrame());
+                    Rect editAreaRect = new Rect();
                     if (editArea.Type == CPDFEditType.EditImage)
                     {
                         if ((contentEditType & CPDFEditType.EditImage) != CPDFEditType.EditImage)
                         {
                             continue;
                         }
-                        TextBlock = DataConversionForWPF.CRectConversionForRect((editArea as CPDFEditImageArea).GetClipRect());
+
+                        editAreaRect = DataConversionForWPF.CRectConversionForRect((editArea as CPDFEditImageArea).GetClipRect());
                     }
                     else if (editArea.Type == CPDFEditType.EditText)
                     {
@@ -421,24 +433,51 @@ namespace ComPDFKit.Tool
                         {
                             continue;
                         }
+
+                        editAreaRect = DataConversionForWPF.CRectConversionForRect(editArea.GetFrame());
+                    }
+                    else if (editArea.Type == CPDFEditType.EditPath)
+                    {
+                        if ((contentEditType & CPDFEditType.EditPath) != CPDFEditType.EditPath)
+                        {
+                            continue;
+                        }
+
+                        editAreaRect = DataConversionForWPF.CRectConversionForRect((editArea as CPDFEditPathArea).GetClipRect());
                     }
-                    Rect rect = TextBlock;
 
-                    rect.X = (rect.X) * currentRenderFrame.ZoomFactor;
-                    rect.Y = (rect.Y) * currentRenderFrame.ZoomFactor;
-                    rect.Width *= currentRenderFrame.ZoomFactor;
-                    rect.Height *= currentRenderFrame.ZoomFactor;
-                    rect = DpiHelper.PDFRectToStandardRect(rect);
+                    editAreaRect.X = (editAreaRect.X) * currentZoom;
+                    editAreaRect.Y = (editAreaRect.Y) * currentZoom;
+                    editAreaRect.Width *= currentZoom;
+                    editAreaRect.Height *= currentZoom;
+                    editAreaRect = DpiHelper.PDFRectToStandardRect(editAreaRect);
+                    editAreaRect.X += item.PageBound.X;
+                    editAreaRect.Y += item.PageBound.Y;
 
-                    rect.X += item.PageBound.X;
-                    rect.Y += item.PageBound.Y;
+                    if (editArea is CPDFEditPathArea)
+                    {
+                        selectedRect.RectMinHeight = 1;
+                        selectedRect.RectMinWidth = 1;
+                    }
 
-                    //PDF对象设置界面矩形
                     selectedRect.SetRectPadding(5);
-                    selectedRect.SetRect(rect, currentZoom);
+                    selectedRect.SetRect(editAreaRect, currentZoom);
                     selectedRect.SetMaxRect(item.PageBound);
                     selectedRect.SetIgnorePointsAll();
-                    selectedRect.Draw();
+                    if ((editArea is CPDFEditPathArea))
+                    {
+                        if (multiSelectedRect.selectedRects.Count==0)
+                        {
+                            selectedRect.Draw();
+                        }
+
+                        selectedRect.IsPath = true;
+                    }
+                    else
+                    {
+                        selectedRect.Draw();
+                    }
+
                     EditAreaObject editAreaObject = new EditAreaObject();
                     editAreaObject.ControlType = PointControlType.None;
                     editAreaObject.cPDFEditArea = editArea;
@@ -459,13 +498,18 @@ namespace ComPDFKit.Tool
                         case CPDFEditType.EditImage:
                             image.Add(selectedRect);
                             break;
+                        case CPDFEditType.EditPath:
+                            path.Add(selectedRect);
+                            break;
                         default:
                             break;
                     }
                 }
             }
+
             hitTestRects.AddRange(text);
             hitTestRects.AddRange(image);
+            hitTestRects.AddRange(path);
         }
 
         public void DrawStartTextEdit(SelectedRect selectedRect, EditAreaObject editAreaObject)
@@ -759,6 +803,35 @@ namespace ComPDFKit.Tool
             return multiSelectedRect;
         }
 
+        private void GetDrawPathList(Point point)
+        {
+            if ((contentEditType & CPDFEditType.EditPath) != CPDFEditType.EditPath)
+                return;
+
+            PDFViewer.GetePointToPage(point, out RenderData renderData, out Point pagePoint);
+            pagePoint = new Point(pagePoint.X / currentZoom, pagePoint.Y / currentZoom);
+            if (renderData == null || renderData.CPDFEditPageObj == null)
+                return;
+
+            foreach (CPDFEditArea editArea in renderData.CPDFEditPageObj.GetEditAreaList())
+            {
+                if (editArea is CPDFEditPathArea)
+                {
+                    CPDFEditPathArea pathArea = editArea as CPDFEditPathArea;
+                    Rect rect = DataConversionForWPF.CRectConversionForRect(pathArea.GetClipRect());
+                    rect = DpiHelper.PDFRectToStandardRect(rect);
+                    if (rect.Contains(pagePoint))
+                    {
+                        if (cachePathList.Contains(pathArea) == false)
+                        {
+                            cachePathList.Add(pathArea);
+                            return;
+                        }
+                    }
+                }
+            }
+        }
+
         /// <summary>
         /// Select
         /// </summary>
@@ -773,6 +846,7 @@ namespace ComPDFKit.Tool
             SetPastePoint(new Point(-1, -1));
             SelectedEditAreaForIndex(-1, -1);
             Point point = Mouse.GetPosition(this);
+            //GetDrawPathList(point);
             CaretVisual caretVisual = CommonHelper.FindVisualChild<CaretVisual>(PDFViewer.GetViewForTag(textEditTag));
 
             EditAreaObject editAreaObject = null;
@@ -787,17 +861,17 @@ namespace ComPDFKit.Tool
             }
 
             //Prioritize the selected status
-            List<SelectedRect> checkList = new List<SelectedRect>();
-            if (hitTestRects != null && hitTestRects.Count > 0)
-            {
-                List<SelectedRect> checkedList = hitTestRects.AsEnumerable().Where(x => x.GetIsSelected() == true).ToList();
-                List<SelectedRect> unCheckList = hitTestRects.AsEnumerable().Where(x => x.GetIsSelected() == false).ToList();
+            //List<SelectedRect> checkList = new List<SelectedRect>();
+            //if (hitTestRects != null && hitTestRects.Count > 0)
+            //{
+            //    List<SelectedRect> checkedList = hitTestRects.AsEnumerable().Where(x => x.GetIsSelected() == true).ToList();
+            //    List<SelectedRect> unCheckList = hitTestRects.AsEnumerable().Where(x => x.GetIsSelected() == false).ToList();
 
-                checkList.AddRange(checkedList);
-                checkList.AddRange(unCheckList);
-            }
+            //    checkList.AddRange(checkedList);
+            //    checkList.AddRange(unCheckList);
+            //}
 
-            foreach (SelectedRect rect in checkList)
+            foreach (SelectedRect rect in hitTestRects)
             {
                 rect.SetIsHover(false);
                 rect.SetIsSelected(false);
@@ -808,9 +882,9 @@ namespace ComPDFKit.Tool
                 }
                 else
                 {
-
                     pointControlType = rect.GetHitControlIndex(point);
                 }
+
                 editArea.TryGetValue(rect, out EditAreaObject editObject);
                 if (pointControlType != PointControlType.None)
                 {
@@ -954,7 +1028,6 @@ namespace ComPDFKit.Tool
                     lastSelectedRect.Draw();
                 }
 
-
                 if (editAreaObject.cPDFEditArea is CPDFEditTextArea)
                 {
                     string chars = (editAreaObject.cPDFEditArea as CPDFEditTextArea).GetAllChars();
@@ -966,16 +1039,27 @@ namespace ComPDFKit.Tool
                         lastSelectedRect.ClearDraw();
                     }
                 }
+
                 lastSelectedRect.DataChanged -= LastSelectedRect_DataChanged;
                 if (lastSelectedRect.GetCurrentDrawPointType() != DrawPointType.Crop)
                 {
                     lastSelectedRect = null;
                 }
+
+                //cachePathList.Clear();
+                //cachePathList = new List<CPDFEditPathArea>();
+                //GetDrawPathList(point);
             }
+
+            if(editAreaList.Count == 0)
+            {
+                cachePathList.Clear();
+                cachePathList = new List<CPDFEditPathArea>();
+                GetDrawPathList(point);
+            }
+
             caretVisual?.StopTimer();
             caretVisual?.CleanDraw();
-
-            return;
         }
 
         /// <summary>
@@ -1009,6 +1093,7 @@ namespace ComPDFKit.Tool
                     }
                 }
             }
+
             return false;
         }
 
@@ -1060,7 +1145,6 @@ namespace ComPDFKit.Tool
 
                 keyValuePairs.Add(currentEditAreaObject.PageIndex, OldRect);
                 DrawUpdateText(keyValuePairs, currentEditAreaObject.PageBound);
-
                 UpdateSelectRect(editAreaObject.cPDFEditArea);
 
                 // Move the moved selected box to the top layer of the selected logic
@@ -1074,10 +1158,19 @@ namespace ComPDFKit.Tool
                         image.Remove(selectedRect);
                         image.Insert(0, selectedRect);
                         break;
+                    case CPDFEditType.EditPath:
+                        path.Remove(selectedRect);
+                        path.Insert(0, selectedRect);
+                        break;
+
+                    default:
+                        break;
                 }
+
                 hitTestRects.Clear();
                 hitTestRects.AddRange(text);
                 hitTestRects.AddRange(image);
+                hitTestRects.AddRange(path);
             }
         }
 
@@ -1279,6 +1372,7 @@ namespace ComPDFKit.Tool
                     {
                         continue;
                     }
+
                     if (editAreaObject.cPDFEditArea is CPDFEditTextArea)
                     {
                         CPDFEditPage editPage = editAreaObject.cPDFEditPage;
@@ -1289,7 +1383,6 @@ namespace ComPDFKit.Tool
                         Rect.ClearDraw();
                     }
                 }
-                SelectedEditAreaForIndex(-1, -1);
             }
             else
             {
@@ -1298,15 +1391,13 @@ namespace ComPDFKit.Tool
                     if (areaObject.cPDFEditArea is CPDFEditTextArea)
                     {
                         CPDFEditPage editPage = areaObject.cPDFEditPage;
-                        CPDFEditTextArea textArea = areaObject.cPDFEditArea as CPDFEditTextArea;
-                        int index = areaObject.EditAreaIndex;
-                        editPage.RemoveEditArea(index);
+                        editPage.RemoveEditArea(areaObject.EditAreaIndex);
                         editPage.EndEdit();
-
                     }
                 }
-                SelectedEditAreaForIndex(-1, -1);
             }
+
+            SelectedEditAreaForIndex(-1, -1);
         }
 
         /// <summary>
@@ -1324,17 +1415,17 @@ namespace ComPDFKit.Tool
                     {
                         continue;
                     }
+
                     if (editAreaObject.cPDFEditArea is CPDFEditImageArea)
                     {
                         CPDFEditPage editPage = editAreaObject.cPDFEditPage;
-                        CPDFEditImageArea textArea = editAreaObject.cPDFEditArea as CPDFEditImageArea;
-                        int index = editAreaObject.cPDFEditPage.GetEditAreaList().IndexOf(textArea);
+                        CPDFEditImageArea imageArea = editAreaObject.cPDFEditArea as CPDFEditImageArea;
+                        int index = editAreaObject.cPDFEditPage.GetEditAreaList().IndexOf(imageArea);
                         editPage.RemoveEditArea(index);
                         editPage.EndEdit();
                         Rect.ClearDraw();
                     }
                 }
-                SelectedEditAreaForIndex(-1, -1);
             }
             else
             {
@@ -1343,14 +1434,51 @@ namespace ComPDFKit.Tool
                     if (areaObject.cPDFEditArea is CPDFEditImageArea)
                     {
                         CPDFEditPage editPage = areaObject.cPDFEditPage;
-                        CPDFEditImageArea textArea = areaObject.cPDFEditArea as CPDFEditImageArea;
-                        int index = areaObject.EditAreaIndex;
+                        editPage.RemoveEditArea(areaObject.EditAreaIndex);
+                        editPage.EndEdit();
+                    }
+                }
+            }
+
+            SelectedEditAreaForIndex(-1, -1);
+        }
+
+        public void RemovePathBlock(EditAreaObject areaObject = null)
+        {
+            if (currentEditAreaObject != null && currentEditAreaObject.cPDFEditPage != null)
+            {
+                foreach (var Rect in hitTestRects)
+                {
+                    editArea.TryGetValue(Rect, out EditAreaObject editAreaObject);
+                    if (editAreaObject != currentEditAreaObject)
+                    {
+                        continue;
+                    }
+                    if (editAreaObject.cPDFEditArea is CPDFEditPathArea)
+                    {
+                        CPDFEditPage editPage = editAreaObject.cPDFEditPage;
+                        CPDFEditPathArea pathArea = editAreaObject.cPDFEditArea as CPDFEditPathArea;
+                        int index = editAreaObject.cPDFEditPage.GetEditAreaList().IndexOf(pathArea);
                         editPage.RemoveEditArea(index);
                         editPage.EndEdit();
+                        Rect.ClearDraw();
+                    }
+                }
+            }
+            else
+            {
+                if (areaObject != null && areaObject.cPDFEditPage != null)
+                {
+                    if (areaObject.cPDFEditArea is CPDFEditPathArea)
+                    {
+                        CPDFEditPage editPage = areaObject.cPDFEditPage;
+                        editPage.RemoveEditArea(areaObject.EditAreaIndex);
+                        editPage.EndEdit();
                     }
                 }
-                SelectedEditAreaForIndex(-1, -1);
             }
+
+            SelectedEditAreaForIndex(-1, -1);
         }
 
         public void CleanEditView()
@@ -1580,20 +1708,35 @@ namespace ComPDFKit.Tool
                 }
 
                 //Prioritize the selected status
-                List<SelectedRect> checkList = new List<SelectedRect>();
-                if (hitTestRects != null && hitTestRects.Count > 0)
-                {
-                    List<SelectedRect> checkedList = hitTestRects.AsEnumerable().Where(x => x.GetIsSelected() == true).ToList();
-                    List<SelectedRect> unCheckList = hitTestRects.AsEnumerable().Where(x => x.GetIsSelected() == false).ToList();
-
-                    checkList.AddRange(checkedList);
-                    checkList.AddRange(unCheckList);
+                //List<SelectedRect> checkList = new List<SelectedRect>();
+                //if (hitTestRects != null && hitTestRects.Count > 0)
+                //{
+                //    List<SelectedRect> checkedList = hitTestRects.AsEnumerable().Where(x => x.GetIsSelected() == true).ToList();
+                //    List<SelectedRect> unCheckList = hitTestRects.AsEnumerable().Where(x => x.GetIsSelected() == false).ToList();
+
+                //    checkList.AddRange(checkedList);
+                //    checkList.AddRange(unCheckList);
+                //}
+
+                //Multiple selection of mouse styles
+                MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(MultiSelectedRectViewTag));
+                if (multiSelectedRect != null && multiSelectedRect.selectedRects.Count > 0)
+                {
+                    PointControlType pointMultiControlType = multiSelectedRect.GetHitControlIndex(point);
+                    if (pointMultiControlType != PointControlType.None)
+                    {
+                        cursor = GetCursors(pointMultiControlType, true);
+                        return cursor;
+                    }
                 }
 
-                foreach (SelectedRect rect in checkList)
+                foreach (SelectedRect rect in hitTestRects)
                 {
-                    PointControlType pointControlType = rect.GetHitControlIndex(point, false);
-                    MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(MultiSelectedRectViewTag));
+                    if (multiSelectedRect != null && multiSelectedRect.selectedRects.Contains(rect))
+                    {
+                        continue;
+                    }
+
                     if (GetIsCropMode())
                     {
                         PointControlType pointCropControlType = rect.GetHitCropControlIndex(point, false);
@@ -1605,16 +1748,11 @@ namespace ComPDFKit.Tool
                     }
                     else
                     {
-                        //Multiple selection of mouse styles
-                        if (multiSelectedRect != null && multiSelectedRect.Children.Count > 0)
-                        {
-                            PointControlType pointMultiControlType = multiSelectedRect.GetHitControlIndex(Mouse.GetPosition(this));
-                            cursor = GetCursors(pointMultiControlType, true);
-                        }
+                        PointControlType pointControlType = rect.GetHitControlIndex(point, false);
                         if (pointControlType != PointControlType.None)
                         {
                             EditAreaObject editAreaObject = GetEditAreaObjectForRect(rect);
-                            if (editAreaObject.cPDFEditArea.Type == CPDFEditType.EditImage)
+                            if (editAreaObject.cPDFEditArea.Type == CPDFEditType.EditImage || editAreaObject.cPDFEditArea.Type == CPDFEditType.EditPath)
                             {
                                 //image hover
                                 if (selectedRect1 == null)
@@ -1678,7 +1816,7 @@ namespace ComPDFKit.Tool
             return cursor;
         }
 
-        private Cursor GetCursors(PointControlType controlType, bool isImage)
+        private Cursor GetCursors(PointControlType controlType, bool notText)
         {
             switch (controlType)
             {
@@ -1699,7 +1837,7 @@ namespace ComPDFKit.Tool
                     return Cursors.SizeNS;
 
                 case PointControlType.Body:
-                    if (isImage)
+                    if (notText)
                     {
                         return Cursors.SizeAll;
                     }
@@ -1874,17 +2012,32 @@ namespace ComPDFKit.Tool
                     selectedRect = item.Key;
                 }
             }
+
             if (selectedRect != null)
             {
                 Rect maxrect = selectedRect.GetMaxRect();
-                Rect rect = DataConversionForWPF.CRectConversionForRect(editArea.GetFrame());
-                if (editArea.Type == CPDFEditType.EditImage)
+                Rect rect = new Rect();
+                if (editArea.Type == CPDFEditType.EditText)
+                {
+                    if ((contentEditType & CPDFEditType.EditText) == CPDFEditType.EditText)
+                    {
+                        rect = DataConversionForWPF.CRectConversionForRect(editArea.GetFrame());
+                    }
+                }
+                else if (editArea.Type == CPDFEditType.EditImage)
                 {
                     if ((contentEditType & CPDFEditType.EditImage) == CPDFEditType.EditImage)
                     {
                         rect = DataConversionForWPF.CRectConversionForRect((editArea as CPDFEditImageArea).GetClipRect());
                     }
                 }
+                else if (editArea.Type == CPDFEditType.EditPath)
+                {
+                    if ((contentEditType & CPDFEditType.EditPath) == CPDFEditType.EditPath)
+                    {
+                        rect = DataConversionForWPF.CRectConversionForRect((editArea as CPDFEditPathArea).GetClipRect());
+                    }
+                }
 
                 rect.X = (rect.X) * currentZoom;
                 rect.Y = (rect.Y) * currentZoom;
@@ -2003,7 +2156,6 @@ namespace ComPDFKit.Tool
             caretVisual.StopCaret();
         }
 
-
         /// <summary>
         /// Jump cursor to a specific position in a text area.
         /// </summary>
@@ -2174,61 +2326,90 @@ namespace ComPDFKit.Tool
         /// <param name="rectFrameSelect"></param>
         public void FrameSelectAddRect(Rect rectFrameSelect)
         {
-            if (rectFrameSelect.Width == 0 || rectFrameSelect.Height == 0)
-            {
-                return;
-            }
-            if (PDFViewer.CurrentRenderFrame == null)
-            {
+            if (rectFrameSelect.Width == 0 || rectFrameSelect.Height == 0 || PDFViewer.CurrentRenderFrame == null)
                 return;
-            }
+
             RenderFrame currentRenderFrame = PDFViewer.CurrentRenderFrame;
             BaseLayer customizeLayer = PDFViewer.GetViewForTag(textEditTag);
-
             customizeLayer.Children.Clear();
             CaretVisual caretVisual = new CaretVisual(GetDefaultDrawParam());
             customizeLayer.Children.Add(caretVisual);
 
-            currentZoom = currentRenderFrame.ZoomFactor;
             MultiSelectedRect multiSelectedRect = CommonHelper.FindVisualChild<MultiSelectedRect>(PDFViewer.GetViewForTag(MultiSelectedRectViewTag));
             foreach (RenderData item in currentRenderFrame.GetRenderDatas())
             {
-                if (item.PageIndex == FrameSelectPageIndex)
+                if (item.PageIndex == FrameSelectPageIndex && item.CPDFEditPageObj != null)
                 {
-                    if (item.CPDFEditPageObj == null)
-                    {
-                        continue;
-                    }
                     foreach (CPDFEditArea editArea in item.CPDFEditPageObj.GetEditAreaList())
                     {
-                        Rect TextBlock = DataConversionForWPF.CRectConversionForRect(editArea.GetFrame());
+                        Rect editAreaRect = new Rect();
                         if (editArea.Type == CPDFEditType.EditImage)
                         {
                             if ((contentEditType & CPDFEditType.EditImage) != CPDFEditType.EditImage)
-                            {
                                 continue;
-                            }
-                            TextBlock = DataConversionForWPF.CRectConversionForRect((editArea as CPDFEditImageArea).GetClipRect());
+
+                            editAreaRect = DataConversionForWPF.CRectConversionForRect((editArea as CPDFEditImageArea).GetClipRect());
                         }
                         else if (editArea.Type == CPDFEditType.EditText)
                         {
                             if ((contentEditType & CPDFEditType.EditText) != CPDFEditType.EditText)
-                            {
                                 continue;
-                            }
+
+                            editAreaRect = DataConversionForWPF.CRectConversionForRect(editArea.GetFrame());
+                        }
+                        else if (editArea.Type == CPDFEditType.EditPath)
+                        {
+                            if ((contentEditType & CPDFEditType.EditPath) != CPDFEditType.EditPath)
+                                continue;
+
+                            editAreaRect = DataConversionForWPF.CRectConversionForRect((editArea as CPDFEditPathArea).GetClipRect());
                         }
-                        Rect rect = TextBlock;
-                        if (rectFrameSelect.IntersectsWith(rect))
+
+                        if (rectFrameSelect.IntersectsWith(editAreaRect))
                         {
-                            SelectedRect selectedRects = GetSelectedRectForEditAreaObject(editArea);
+                            SelectedRect editAreaSelectedRect = GetSelectedRectForEditAreaObject(editArea);
+                            if (editAreaSelectedRect == null && editArea is CPDFEditPathArea)
+                            {
+                                cachePathList.Add(editArea as CPDFEditPathArea);
+
+                                editAreaRect.X = (editAreaRect.X) * currentZoom;
+                                editAreaRect.Y = (editAreaRect.Y) * currentZoom;
+                                editAreaRect.Width *= currentZoom;
+                                editAreaRect.Height *= currentZoom;
+                                editAreaRect = DpiHelper.PDFRectToStandardRect(editAreaRect);
+                                editAreaRect.X += item.PageBound.X;
+                                editAreaRect.Y += item.PageBound.Y;
+
+                                editAreaSelectedRect = new SelectedRect(GetDefaultDrawParam(), SelectedType.PDFEdit);
+                                editAreaSelectedRect.SetEditPen(editPen, editHoverPen);
+                                editAreaSelectedRect.SetDrawMoveType(DrawMoveType.kReferenceLine);
+                                customizeLayer.Children.Add(editAreaSelectedRect);
+
+                                editAreaSelectedRect.SetRectPadding(5);
+                                editAreaSelectedRect.SetRect(editAreaRect, currentZoom);
+                                editAreaSelectedRect.SetMaxRect(item.PageBound);
+                                editAreaSelectedRect.SetIgnorePointsAll();
+
+                                EditAreaObject editAreaObjects = new EditAreaObject();
+                                editAreaObjects.ControlType = PointControlType.None;
+                                editAreaObjects.cPDFEditArea = editArea;
+                                editAreaObjects.cPDFEditPage = item.CPDFEditPageObj;
+                                editAreaObjects.PageIndex = item.PageIndex;
+                                editAreaObjects.EditAreaIndex = item.CPDFEditPageObj.GetEditAreaList().IndexOf(editArea);
+                                editAreaObjects.PageBound = item.PageBound;
+                                editAreaObjects.PaintRect = item.PaintRect;
+
+                                this.editArea.Add(editAreaSelectedRect, editAreaObjects);
+                            }
+
                             SelectedRect selectedRect = new SelectedRect(GetDefaultDrawParam(), SelectedType.PDFEdit);
                             selectedRect.SetEditPen(editPen, editHoverPen);
                             multiSelectedRect.SetSelectedType(SelectedType.PDFEdit);
                             selectedRect.SetDrawMoveType(DrawMoveType.kReferenceLine);
-                            selectedRect.SetRect(selectedRects.GetRect(), currentZoom);
-                            selectedRect.SetMaxRect(selectedRects.GetMaxRect());
-                            EditAreaObject editAreaObject = null;
+                            selectedRect.SetRect(editAreaSelectedRect.GetRect(), currentZoom);
+                            selectedRect.SetMaxRect(editAreaSelectedRect.GetMaxRect());
 
+                            EditAreaObject editAreaObject = null;
                             foreach (var eitem in this.editArea)
                             {
                                 if (eitem.Value.cPDFEditArea == editArea)
@@ -2237,36 +2418,38 @@ namespace ComPDFKit.Tool
                                     break;
                                 }
                             }
+
                             int pageIndex = editAreaObject.PageIndex;
                             if (multiPage != pageIndex && editAreaList.Count > 0)
                             {
                                 foreach (int itemIndex in editAreaMultiIndex)
                                 {
-                                    SelectedRect OldRect = GetEditAreaForIndex(multiPage, itemIndex);
-                                    if (OldRect != null)
-                                    {
-                                        OldRect.Draw();
-                                    }
+                                    SelectedRect oldRect = GetEditAreaForIndex(multiPage, itemIndex);
+                                    oldRect?.Draw();
                                 }
+
                                 editAreaMultiIndex.Clear();
                                 multiSelectedRect.ClearDraw();
                                 multiSelectedRect.CleanMulitSelectedRect();
-                                multiPage = pageIndex;
                             }
-                            multiPage = editAreaObject.PageIndex;
+
+                            multiPage = pageIndex;
                             editAreaMultiIndex.Add(editAreaObject.EditAreaIndex);
                             editAreaList.Add(selectedRect, editAreaObject);
                             multiSelectedRect.Children.Add(selectedRect);
                             multiSelectedRect.SetMulitSelectedRect(selectedRect, editAreaObject.PageIndex, editAreaObject.EditAreaIndex);
 
-                            multiSelectedRect.SetRect(selectedRects.GetRect());
-                            multiSelectedRect.SetMaxRect(selectedRects.GetMaxRect());
-                            multiSelectedRect.Draw();
+                            multiSelectedRect.SetRect(editAreaSelectedRect.GetRect());
+                            multiSelectedRect.SetMaxRect(editAreaSelectedRect.GetMaxRect());
+                            //multiSelectedRect.Draw();
                         }
                     }
                 }
             }
-            PDFViewer.UpdateRenderFrame();
+
+            //PDFViewer.UpdateRenderFrame();
+            SetEditTextRect(PDFViewer.CurrentRenderFrame);
+            ReDrawSelectedMultiRect();
         }
 
         #endregion
@@ -2362,7 +2545,7 @@ namespace ComPDFKit.Tool
             CPDFDocument cPDFDocument = GetCPDFViewer().GetDocument();
             CPDFPage cPDFPage = cPDFDocument.PageAtIndex(multiPage);
             CPDFEditPage cPDFEditPage = cPDFPage.GetEditPage();
-            cPDFEditPage.BeginEdit(CPDFEditType.EditText | CPDFEditType.EditImage);
+            cPDFEditPage.BeginEdit(CPDFEditType.EditText | CPDFEditType.EditImage | CPDFEditType.EditPath);
             foreach (SelectedRect checkItem in MultiSelectEditList.GetMulitSelectList())
             {
                 SelectedRect item = checkItem;
@@ -2422,7 +2605,7 @@ namespace ComPDFKit.Tool
             CPDFDocument cPDFDocument = GetCPDFViewer().GetDocument();
             CPDFPage cPDFPage = cPDFDocument.PageAtIndex(multiPage);
             CPDFEditPage cPDFEditPage = cPDFPage.GetEditPage();
-            cPDFEditPage.BeginEdit(CPDFEditType.EditText | CPDFEditType.EditImage);
+            cPDFEditPage.BeginEdit(CPDFEditType.EditText | CPDFEditType.EditImage | CPDFEditType.EditPath);
             foreach (SelectedRect checkItem in MultiSelectEditList.GetMulitSelectList())
             {
                 SelectedRect item = checkItem;
@@ -2495,7 +2678,7 @@ namespace ComPDFKit.Tool
             CPDFDocument cPDFDocument = GetCPDFViewer().GetDocument();
             CPDFPage cPDFPage = cPDFDocument.PageAtIndex(multiPage);
             CPDFEditPage cPDFEditPage = cPDFPage.GetEditPage();
-            cPDFEditPage.BeginEdit(CPDFEditType.EditText | CPDFEditType.EditImage);
+            cPDFEditPage.BeginEdit(CPDFEditType.EditText | CPDFEditType.EditImage | CPDFEditType.EditPath);
             foreach (SelectedRect checkItem in MultiSelectEditList.GetMulitSelectList())
             {
                 SelectedRect item = checkItem;
@@ -2570,7 +2753,7 @@ namespace ComPDFKit.Tool
             CPDFDocument cPDFDocument = GetCPDFViewer().GetDocument();
             CPDFPage cPDFPage = cPDFDocument.PageAtIndex(multiPage);
             CPDFEditPage cPDFEditPage = cPDFPage.GetEditPage();
-            cPDFEditPage.BeginEdit(CPDFEditType.EditText | CPDFEditType.EditImage);
+            cPDFEditPage.BeginEdit(CPDFEditType.EditText | CPDFEditType.EditImage | CPDFEditType.EditPath);
             foreach (SelectedRect checkItem in MultiSelectEditList.GetMulitSelectList())
             {
                 SelectedRect item = checkItem;
@@ -2630,7 +2813,7 @@ namespace ComPDFKit.Tool
             CPDFDocument cPDFDocument = GetCPDFViewer().GetDocument();
             CPDFPage cPDFPage = cPDFDocument.PageAtIndex(multiPage);
             CPDFEditPage cPDFEditPage = cPDFPage.GetEditPage();
-            cPDFEditPage.BeginEdit(CPDFEditType.EditText | CPDFEditType.EditImage);
+            cPDFEditPage.BeginEdit(CPDFEditType.EditText | CPDFEditType.EditImage | CPDFEditType.EditPath);
             foreach (SelectedRect checkItem in MultiSelectEditList.GetMulitSelectList())
             {
                 SelectedRect item = checkItem;
@@ -2687,7 +2870,7 @@ namespace ComPDFKit.Tool
             CPDFDocument cPDFDocument = GetCPDFViewer().GetDocument();
             CPDFPage cPDFPage = cPDFDocument.PageAtIndex(multiPage);
             CPDFEditPage cPDFEditPage = cPDFPage.GetEditPage();
-            cPDFEditPage.BeginEdit(CPDFEditType.EditText | CPDFEditType.EditImage);
+            cPDFEditPage.BeginEdit(CPDFEditType.EditText | CPDFEditType.EditImage | CPDFEditType.EditPath);
             foreach (SelectedRect checkItem in MultiSelectEditList.GetMulitSelectList())
             {
                 SelectedRect item = checkItem;
@@ -2746,7 +2929,7 @@ namespace ComPDFKit.Tool
             CPDFDocument cPDFDocument = GetCPDFViewer().GetDocument();
             CPDFPage cPDFPage = cPDFDocument.PageAtIndex(multiPage);
             CPDFEditPage cPDFEditPage = cPDFPage.GetEditPage();
-            cPDFEditPage.BeginEdit(CPDFEditType.EditText | CPDFEditType.EditImage);
+            cPDFEditPage.BeginEdit(CPDFEditType.EditText | CPDFEditType.EditImage | CPDFEditType.EditPath);
             foreach (SelectedRect item in MultiSelectEditList.GetMulitSelectList())
             {
                 Rect rect = item.GetRect();
@@ -2809,7 +2992,7 @@ namespace ComPDFKit.Tool
             CPDFDocument cPDFDocument = GetCPDFViewer().GetDocument();
             CPDFPage cPDFPage = cPDFDocument.PageAtIndex(multiPage);
             CPDFEditPage cPDFEditPage = cPDFPage.GetEditPage();
-            cPDFEditPage.BeginEdit(CPDFEditType.EditText | CPDFEditType.EditImage);
+            cPDFEditPage.BeginEdit(CPDFEditType.EditText | CPDFEditType.EditImage | CPDFEditType.EditPath);
             foreach (SelectedRect item in MultiSelectEditList.GetMulitSelectList())
             {
                 Rect rect = item.GetRect();

+ 22 - 13
Demo/Examples/ComPDFKit.Tool/CPDFViewerTool.xaml.cs

@@ -1,5 +1,4 @@
-using ComPDFKit.Import;
-using ComPDFKit.PDFAnnotation;
+using ComPDFKit.PDFAnnotation;
 using ComPDFKit.PDFDocument;
 using ComPDFKit.PDFDocument.Action;
 using ComPDFKit.PDFPage;
@@ -49,6 +48,7 @@ namespace ComPDFKit.Tool
         Widget,
         TextEdit,
         ImageEdit,
+        PathEdit,
         ImageSelect,
         MultiTextEdit,
         SelectedPageRect,
@@ -157,12 +157,10 @@ namespace ComPDFKit.Tool
         /// <param name="isContinueCreateTextEdit"></param>
         public void SetContinueCreateTextEdit(bool isContinueCreateTextEdit)
         {
-
             this.isContinueCreateTextEdit = isContinueCreateTextEdit;
             CanAddTextEdit = true;
         }
-
-
+        
         /// <summary>
         ///  Does it support multiple selection
         /// </summary>
@@ -337,7 +335,6 @@ namespace ComPDFKit.Tool
         {
             if (isContinueCreateTextEdit)
             {
-
                 if (lastSelectedRect != null)
                 {
                     CanAddTextEdit = false;
@@ -348,7 +345,7 @@ namespace ComPDFKit.Tool
                 }
             }
 
-            if (PDFViewer == null || PDFViewer.CurrentRenderFrame == null)
+            if (PDFViewer == null || PDFViewer.CurrentRenderFrame == null || PDFViewer.IsRendering)
             {
                 return;
             }
@@ -483,6 +480,10 @@ namespace ComPDFKit.Tool
             }
             else if ((currentModel == ToolType.Pan || currentModel == ToolType.Viewer))
             {
+                if (AnnotHitTest() && cacheHitTestAnnot.CurrentType == C_ANNOTATION_TYPE.C_ANNOTATION_LINK)
+                {
+                    LinkAnnotAction(cacheHitTestAnnot);
+                }
                 if (!IsText() && DrawDownSelectImage(true))
                 {
                     mouseEventObject.hitTestType = MouseHitTestType.ImageSelect;
@@ -617,7 +618,7 @@ namespace ComPDFKit.Tool
 
         protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
         {
-            if (PDFViewer == null || PDFViewer.CurrentRenderFrame == null)
+            if (PDFViewer == null || PDFViewer.CurrentRenderFrame == null || PDFViewer.IsRendering)
             {
                 return;
             }
@@ -654,11 +655,11 @@ namespace ComPDFKit.Tool
                         {
                             if (IsMoved && areaSelectAdd == false)
                             {
-                                selectedRect.UpdateAnnotData(cacheHitTestAnnot.GetAnnotData());
+                                selectedRect.SetAnnotData(cacheHitTestAnnot.GetAnnotData(),PDFViewer);
                             }
                             else
                             {
-                                selectedRect.SetAnnotData(cacheHitTestAnnot.GetAnnotData());
+                                selectedRect.SetAnnotData(cacheHitTestAnnot.GetAnnotData(), PDFViewer);
                             }
                             selectedRect.Draw();
                         }
@@ -699,11 +700,10 @@ namespace ComPDFKit.Tool
             IsMoved = false;
         }
 
-        protected override void OnMouseMove(MouseEventArgs e)
+        protected override async void OnMouseMove(MouseEventArgs e)
         {
             IsMoved = e.LeftButton == MouseButtonState.Pressed;
-
-            if (PDFViewer == null || PDFViewer.CurrentRenderFrame == null)
+            if (PDFViewer == null || PDFViewer.CurrentRenderFrame == null || PDFViewer.IsRendering)
             {
                 return;
             }
@@ -843,6 +843,11 @@ namespace ComPDFKit.Tool
 
         protected override void OnMouseRightButtonDown(MouseButtonEventArgs e)
         {
+            if(PDFViewer.IsRendering)
+            {
+                return;
+            }
+
             MouseEventObject mouseEventObject = new MouseEventObject
             {
                 mouseButtonEventArgs = e,
@@ -985,6 +990,9 @@ namespace ComPDFKit.Tool
                             case CPDFEditType.EditImage:
                                 mouseEventObject.hitTestType = MouseHitTestType.ImageEdit;
                                 break;
+                            case CPDFEditType.EditPath:
+                                mouseEventObject.hitTestType = MouseHitTestType.PathEdit;
+                                break;
                             default:
                                 break;
                         }
@@ -1154,6 +1162,7 @@ namespace ComPDFKit.Tool
                     else
                     {
                         SelectedAnnot(null);
+                        CleanEditAnnot(true);
                     }
                 }
                 else if (selectedPageIndex != -1 && selectedAnnotIndex != -1)

+ 8 - 11
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 />
@@ -81,6 +81,12 @@
     <LangVersion>7.3</LangVersion>
   </PropertyGroup>
   <ItemGroup>
+    <Reference Include="ComPDFKit.NET">
+      <HintPath>C:\Users\kdanmobile\Desktop\tool_git\ComPDFKit.NET.dll</HintPath>
+    </Reference>
+    <Reference Include="ComPDFKit.Viewer">
+      <HintPath>C:\Users\kdanmobile\Desktop\tool_git\ComPDFKit.Viewer.dll</HintPath>
+    </Reference>
     <Reference Include="PresentationCore" />
     <Reference Include="PresentationFramework" />
     <Reference Include="System" />
@@ -166,6 +172,7 @@
     <Compile Include="SettingParam\FormParam\PushButtonParam.cs" />
     <Compile Include="SettingParam\FormParam\RadioButtonParam.cs" />
     <Compile Include="SettingParam\FormParam\TextBoxParam.cs" />
+    <Compile Include="SettingParam\PDFEditParam\PathEditParam.cs" />
     <Compile Include="SettingParam\PDFEditParam\ImageEditParam.cs" />
     <Compile Include="SettingParam\PDFEditParam\PDFEditParam.cs" />
     <Compile Include="SettingParam\PDFEditParam\TextEditParam.cs" />
@@ -226,15 +233,5 @@
       <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>

+ 33 - 30
Demo/Examples/ComPDFKit.Tool/DrawTool/AnnotEdit.cs

@@ -4,19 +4,14 @@ using ComPDFKit.PDFAnnotation;
 using ComPDFKit.Tool.SettingParam;
 using ComPDFKit.Viewer.Helper;
 using ComPDFKitViewer;
-using ComPDFKitViewer.Annot;
 using ComPDFKitViewer.Helper;
 using System;
 using System.Collections.Generic;
-using System.Diagnostics;
 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;
 
 namespace ComPDFKit.Tool.DrawTool
 {
@@ -197,17 +192,17 @@ namespace ComPDFKit.Tool.DrawTool
                 case C_ANNOTATION_TYPE.C_ANNOTATION_CIRCLE:
                     break;
                 case C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON:
-                    for (int i = 0; i < (annotData.Annot as CPDFPolygonAnnotation).Points.Count; i++)
-                    {
-                        Point point = DpiHelper.PDFPointToStandardPoint(new Point((annotData.Annot as CPDFPolygonAnnotation).Points[i].x, (annotData.Annot as CPDFPolygonAnnotation).Points[i].y));
-                        point = new Point(
-                            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);
-                    }
-                    if ((annotData.Annot as CPDFPolygonAnnotation).IsMeasured())
                     {
+                        for (int i = 0; i < (annotData.Annot as CPDFPolygonAnnotation).Points.Count; i++)
+                        {
+                            Point point = DpiHelper.PDFPointToStandardPoint(new Point((annotData.Annot as CPDFPolygonAnnotation).Points[i].x, (annotData.Annot as CPDFPolygonAnnotation).Points[i].y));
+                            point = new Point(
+                                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);
+                        }
+
                         CRect rawRect = annotData.Annot.GetRect();
                         Rect rect = DataConversionForWPF.CRectConversionForRect(rawRect);
                         rect = DpiHelper.PDFRectToStandardRect(rect);
@@ -219,18 +214,19 @@ namespace ComPDFKit.Tool.DrawTool
                             );
                     }
                     break;
+
                 case C_ANNOTATION_TYPE.C_ANNOTATION_POLYLINE:
-                    for (int i = 0; i < (annotData.Annot as CPDFPolylineAnnotation).Points.Count; i++)
-                    {
-                        Point point = DpiHelper.PDFPointToStandardPoint(new Point((annotData.Annot as CPDFPolylineAnnotation).Points[i].x, (annotData.Annot as CPDFPolylineAnnotation).Points[i].y));
-                        point = new Point(
-                            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);
-                    }
-                    if ((annotData.Annot as CPDFPolylineAnnotation).IsMeasured())
                     {
+                        for (int i = 0; i < (annotData.Annot as CPDFPolylineAnnotation).Points.Count; i++)
+                        {
+                            Point point = DpiHelper.PDFPointToStandardPoint(new Point((annotData.Annot as CPDFPolylineAnnotation).Points[i].x, (annotData.Annot as CPDFPolylineAnnotation).Points[i].y));
+                            point = new Point(
+                                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);
+                        }
+
                         CRect rawRect = annotData.Annot.GetRect();
                         Rect rect = DataConversionForWPF.CRectConversionForRect(rawRect);
                         rect = DpiHelper.PDFRectToStandardRect(rect);
@@ -242,6 +238,7 @@ namespace ComPDFKit.Tool.DrawTool
                             );
                     }
                     break;
+
                 case C_ANNOTATION_TYPE.C_ANNOTATION_HIGHLIGHT:
                     break;
                 case C_ANNOTATION_TYPE.C_ANNOTATION_UNDERLINE:
@@ -372,7 +369,6 @@ namespace ComPDFKit.Tool.DrawTool
             {
                 Tag = isMouseDown;
                 mouseEndDrawPoint = mousePoint;
-
                 Point newOffset = new Point(
                     mouseEndDrawPoint.X - mouseDownPoint.X,
                     mouseEndDrawPoint.Y - mouseDownPoint.Y
@@ -396,26 +392,30 @@ namespace ComPDFKit.Tool.DrawTool
 
         public virtual void OnMouseLeftButtonUp(Point upPoint)
         {
+            if (annotData == null)
+                return;
+
             isMouseDown = false;
-            Draw();
-            if (annotData!=null&&annotData.AnnotType == C_ANNOTATION_TYPE.C_ANNOTATION_LINE)
+            if (annotData.AnnotType == C_ANNOTATION_TYPE.C_ANNOTATION_LINE)
             {
                 if ((annotData.Annot as CPDFLineAnnotation).IsMeasured())
                 {
                     activePoints.Clear();
-
                     if (moveLeftLine == null)
                     {
                         moveLeftLine = leftLine.ToArray();
                     }
+
                     if (moveRightLine == null)
                     {
                         moveRightLine = rightLine.ToArray();
                     }
+
                     if (moveCrossLine == null)
                     {
                         moveCrossLine = crossLine.ToArray();
                     }
+
                     activePoints.Add(moveLeftLine[0]);
                     activePoints.Add(moveLeftLine[1]);
                     activePoints.Add(moveRightLine[0]);
@@ -424,6 +424,7 @@ namespace ComPDFKit.Tool.DrawTool
                     activePoints.Add(moveCrossLine[1]);
                 }
             }
+   
             moveLeftLine = null;
             moveRightLine = null;
             moveCrossLine = null;
@@ -431,11 +432,13 @@ namespace ComPDFKit.Tool.DrawTool
             {
                 InvokeDataChangEvent(true);
             }
+
             moveOffset = new Point(0, 0);
             mouseDownPoint = new Point();
-
             mouseEndDrawPoint = new Point();
             hitIndex = -1;
+
+            SetAnnotObject(annotData);
         }
 
         /// <summary>

+ 248 - 196
Demo/Examples/ComPDFKit.Tool/DrawTool/CreateAnnotTool.cs

@@ -9,8 +9,6 @@ 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;
@@ -18,19 +16,10 @@ 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 System.Windows.Shapes;
 using static ComPDFKit.PDFAnnotation.CTextAttribute.CFontNameHelper;
-using static ComPDFKit.Tool.Help.ImportWin32;
 
 namespace ComPDFKit.Tool.DrawTool
 {
@@ -303,7 +292,17 @@ namespace ComPDFKit.Tool.DrawTool
                         DPIRect = drawRect = new Rect(mouseEndPoint.X, mouseEndPoint.Y, 32 * zoomFactor, 32 * zoomFactor);
                     }
                 }
-                Rect StandardRect = new Rect(
+
+                if (cPDFAnnotation is CPDFPolylineAnnotation)
+                {
+                    double left = drawPoints.AsEnumerable().Select(x => x.X).Min();
+                    double right = drawPoints.AsEnumerable().Select(x => x.X).Max();
+                    double top = drawPoints.AsEnumerable().Select(x => x.Y).Min();
+                    double bottom = drawPoints.AsEnumerable().Select(x => x.Y).Max();
+                    DPIRect = new Rect(left, top, right - left, bottom - top);
+                }
+
+                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);
                 isDrawAnnot = false;
@@ -317,7 +316,7 @@ namespace ComPDFKit.Tool.DrawTool
                 cPDFAnnotation = null;
                 inkDrawPoints.Clear();
                 drawPoints.Clear();
-                return DpiHelper.StandardRectToPDFRect(StandardRect);
+                return DpiHelper.StandardRectToPDFRect(standardRect);
             }
             return new Rect();
         }
@@ -685,7 +684,7 @@ namespace ComPDFKit.Tool.DrawTool
                 lineSegment.IsSmoothJoin = true;
                 pathFigure.Segments.Add(lineSegment);
             }
-            if(annotLine.Dash!=null && annotLine.Dash.Length>0)
+            if (annotLine.Dash != null && annotLine.Dash.Length > 0)
             {
                 DashStyle dash = new DashStyle();
                 foreach (var offset in annotLine.Dash)
@@ -1044,34 +1043,33 @@ namespace ComPDFKit.Tool.DrawTool
 
                 MeasureChanged?.Invoke(this, measureEvent);
             }
-
         }
 
         private void DrawPolygonMeasure(DrawingContext drawingContext)
         {
-            CPDFPolygonAnnotation polyLine = (cPDFAnnotation as CPDFPolygonAnnotation);
-            byte[] bytes = polyLine.LineColor;
+            CPDFPolygonAnnotation polygonAnnot = (cPDFAnnotation as CPDFPolygonAnnotation);
+            byte[] bytes = polygonAnnot.LineColor;
             Color color = ParamConverter.ConverterByteForColor(bytes);
-            color.A = polyLine.GetTransparency();
-            Pen DrawPen = new Pen(new SolidColorBrush(color), polyLine.GetBorderWidth());
-            Pen EndDrawPen = new Pen(Brushes.Black, polyLine.GetBorderWidth());
+            color.A = polygonAnnot.GetTransparency();
+            Pen DrawPen = new Pen(new SolidColorBrush(color), polygonAnnot.GetBorderWidth());
+            Pen EndDrawPen = new Pen(Brushes.Black, polygonAnnot.GetBorderWidth());
             SolidColorBrush TextBrush = Brushes.Red;
 
-            if (polyLine.IsMeasured())
+            if (polygonAnnot.IsMeasured())
             {
-                CPDFAreaMeasure measureInfo = polyLine.GetAreaMeasure();
+                CPDFAreaMeasure measureInfo = polygonAnnot.GetAreaMeasure();
                 if (measureInfo != null && measureInfo.TextAttribute != null && measureInfo.TextAttribute.FontColor != null && measureInfo.TextAttribute.FontColor.Length >= 3)
                 {
                     byte[] fontColor = measureInfo.TextAttribute.FontColor;
                     TextBrush = new SolidColorBrush(Color.FromRgb(fontColor[0], fontColor[1], fontColor[2]));
                 }
 
-                if (polyLine.Dash != null && polyLine.Dash.Length > 0)
+                if (polygonAnnot.Dash != null && polygonAnnot.Dash.Length > 0)
                 {
                     DashStyle dash = new DashStyle();
-                    foreach (var offset in polyLine.Dash)
+                    foreach (var offset in polygonAnnot.Dash)
                     {
-                        dash.Dashes.Add(offset / polyLine.LineWidth);
+                        dash.Dashes.Add(offset / polygonAnnot.LineWidth);
                     }
                     DrawPen.DashStyle = dash;
                     DrawPen.DashCap = PenLineCap.Flat;
@@ -1085,6 +1083,7 @@ namespace ComPDFKit.Tool.DrawTool
                     mouseEndPoint = CalcAnglePoint(mouseEndPoint, drawPoints[drawPoints.Count - 1], pageBound);
                 }
             }
+
             Point checkPoint = mouseEndPoint;
             checkPoint.X = Math.Max(pageBound.Left, checkPoint.X);
             checkPoint.X = Math.Min(pageBound.Right, checkPoint.X);
@@ -1102,214 +1101,256 @@ namespace ComPDFKit.Tool.DrawTool
                 points.Add(rect.BottomRight);
                 points.Add(rect.TopRight);
             }
+
             if (points.Count > 0)
             {
-                PathGeometry drawPath = new PathGeometry();
-                PathFigure drawFigure = new PathFigure();
-
-                drawFigure.StartPoint = points[0];
-                PolyLineSegment polySegment = new PolyLineSegment();
-
-                for (int i = 1; i < points.Count; i++)
+                CPDFBorderEffector borderEffector = polygonAnnot.GetAnnotBorderEffector();
+                if (borderEffector != null && borderEffector.BorderIntensity != C_BORDER_INTENSITY.C_INTENSITY_ZERO && borderEffector.BorderType != C_BORDER_TYPE.C_BORDER_TYPE_STRAIGHT)
                 {
-                    polySegment.Points.Add(points[i]);
-                }
+                    //Draw the example line connected by the start point and the end point.
+                    if (points.Count == 1)
+                    {
+                        Pen dashedPen = new Pen(Brushes.Gray, 1);
+                        dashedPen.DashStyle = new DashStyle(new double[] { 2, 2 }, 0);
+                        drawingContext?.DrawLine(dashedPen, points[0], checkPoint);
+                    }
 
-                if (defaultSettingParam.IsCreateSquarePolygonMeasure)
-                {
-                    polySegment.Points.Add(points[0]);
+                    double left = drawPoints.AsEnumerable().Select(x => x.X).Min();
+                    double right = drawPoints.AsEnumerable().Select(x => x.X).Max();
+                    double top = drawPoints.AsEnumerable().Select(x => x.Y).Min();
+                    double bottom = drawPoints.AsEnumerable().Select(x => x.Y).Max();
+                    DPIRect = new Rect(left, top, right - left, bottom - top);
+
+                    polygonAnnot.SetAnnotBorderEffector(borderEffector);
+                    drawPoints.Add(checkPoint);
+                    List<Point> measurePoint = new List<Point>();
+                    measurePoint = GetMeasureDrawPoints();
+                    drawPoints.RemoveAt(drawPoints.Count - 1);
+                    List<CPoint> cPoints = new List<CPoint>();
+                    foreach (Point item in measurePoint)
+                    {
+                        cPoints.Add(DataConversionForWPF.PointConversionForCPoint(DpiHelper.StandardPointToPDFPoint(item)));
+                    }
+
+                    polygonAnnot.SetPoints(cPoints);
+                    polygonAnnot.UpdateAp();
+                    cPDFViewer.UpdateAnnotFrame();
                 }
                 else
                 {
-                    //Add the current point during the movement.
-                    polySegment.Points.Add(checkPoint);
-                }
+                    PathGeometry drawPath = new PathGeometry();
+                    PathFigure drawFigure = new PathFigure();
 
-                if (polySegment.Points.Count > 0)
-                {
-                    drawFigure.Segments.Add(polySegment);
-                }
-                if (drawFigure.Segments.Count > 0)
-                {
-                    drawPath.Figures.Add(drawFigure);
-                }
+                    drawFigure.StartPoint = points[0];
+                    PolyLineSegment polySegment = new PolyLineSegment();
 
-                //Draw the line segment.
-                drawingContext?.DrawGeometry(null, DrawPen, drawPath);
+                    for (int i = 1; i < points.Count; i++)
+                    {
+                        polySegment.Points.Add(points[i]);
+                    }
 
-                //Draw the example line connected by the start point and the end point.
-                if (points.Count > 1)
-                {
                     if (defaultSettingParam.IsCreateSquarePolygonMeasure)
                     {
-                        drawingContext?.DrawLine(DrawPen, points[0], polySegment.Points.Last());
+                        polySegment.Points.Add(points[0]);
                     }
                     else
                     {
-                        drawingContext?.DrawLine(EndDrawPen, points[0], polySegment.Points.Last());
+                        //Add the current point during the movement.
+                        polySegment.Points.Add(checkPoint);
                     }
-                }
 
-                //Calculate the length.
-                double totalInch = 0;
-                if (points.Count > 1)
-                {
-                    for (int i = 0; i < points.Count - 1; i++)
+                    if (polySegment.Points.Count > 0)
                     {
-                        totalInch += measureSetting.GetMeasureLength(points[i], points[i + 1], zoomFactor);
+                        drawFigure.Segments.Add(polySegment);
                     }
-                }
-                double currentInch = measureSetting.GetMeasureLength(points[points.Count - 1], checkPoint, zoomFactor);
-                if (defaultSettingParam.IsCreateSquarePolygonMeasure)
-                {
-                    currentInch = measureSetting.GetMeasureLength(points[points.Count - 1], points[0], zoomFactor);
-                }
-                totalInch += currentInch;
-
-                Point closePoint = points[points.Count - 1];
-                Vector movevector = checkPoint - closePoint;
-
-                FormattedText moveText = new FormattedText(
-                    string.Format("{0} {1}", measureSetting.GetPrecisionData(currentInch), measureSetting.RulerTranslateUnit),
-                    CultureInfo.GetCultureInfo("en-us"),
-                    FlowDirection.LeftToRight,
-                    new Typeface("YaHei"),
-                    16,
-                    TextBrush);
 
-                FormattedText totalText = new FormattedText(
-                   string.Format("{0} {1}", measureSetting.GetPrecisionData(totalInch), measureSetting.RulerTranslateUnit),
-                   CultureInfo.GetCultureInfo("en-us"),
-                   FlowDirection.LeftToRight,
-                   new Typeface("YaHei"),
-                   16,
-                 TextBrush);
-
-                //Judge the text display form.
-                if (movevector.Length > moveText.Width + textPadding || defaultSettingParam.IsCreateSquarePolygonMeasure)
-                {
-                    if (checkPoint.X >= closePoint.X)
+                    if (drawFigure.Segments.Count > 0)
                     {
-                        Point linePoint = new Point(closePoint.X + movevector.Length, closePoint.Y);
-                        Point drawPoint = new Point(
-                            linePoint.X - moveText.Width - textPadding,
-                            linePoint.Y - moveText.Height);
-
-                        Vector anglevector = linePoint - closePoint;
+                        drawPath.Figures.Add(drawFigure);
+                    }
 
-                        RotateTransform transform = new RotateTransform();
-                        transform.CenterX = closePoint.X;
-                        transform.CenterY = closePoint.Y;
-                        double angle = Vector.AngleBetween(movevector, anglevector);
-                        transform.Angle = -angle;
+                    //Draw the line segment.
+                    drawingContext?.DrawGeometry(null, DrawPen, drawPath);
 
-                        drawingContext?.PushTransform(transform);
-                        if (!defaultSettingParam.IsCreateSquarePolygonMeasure)
+                    //Draw the example line connected by the start point and the end point.
+                    if (points.Count > 1)
+                    {
+                        if (defaultSettingParam.IsCreateSquarePolygonMeasure)
                         {
-                            drawingContext?.DrawText(moveText, drawPoint);
+                            drawingContext?.DrawLine(DrawPen, points[0], polySegment.Points.Last());
                         }
-                        if (totalInch > currentInch)
+                        else
                         {
-                            drawingContext?.DrawText(totalText, new Point(
-                                drawPoint.X + moveText.Width + textPadding * 2,
-                                drawPoint.Y
-                                ));
+                            drawingContext?.DrawLine(EndDrawPen, points[0], polySegment.Points.Last());
                         }
-                        drawingContext.Pop();
                     }
-                    else
-                    {
-                        Point linePoint = new Point(closePoint.X - movevector.Length, closePoint.Y);
-                        Point drawPoint = new Point(
-                            linePoint.X + textPadding,
-                            linePoint.Y - moveText.Height);
-
-                        Vector anglevector = linePoint - closePoint;
-
-                        RotateTransform transform = new RotateTransform();
-                        transform.CenterX = closePoint.X;
-                        transform.CenterY = closePoint.Y;
-                        double angle = Vector.AngleBetween(movevector, anglevector);
-                        transform.Angle = -angle;
 
-                        drawingContext?.PushTransform(transform);
-                        if (!defaultSettingParam.IsCreateSquarePolygonMeasure)
+                    //Calculate the length.
+                    double totalInch = 0;
+                    if (points.Count > 1)
+                    {
+                        for (int i = 0; i < points.Count - 1; i++)
                         {
-                            drawingContext?.DrawText(moveText, drawPoint);
+                            totalInch += measureSetting.GetMeasureLength(points[i], points[i + 1], zoomFactor);
                         }
-                        if (totalInch > currentInch)
+                    }
+
+                    double currentInch = measureSetting.GetMeasureLength(points[points.Count - 1], checkPoint, zoomFactor);
+                    if (defaultSettingParam.IsCreateSquarePolygonMeasure)
+                    {
+                        currentInch = measureSetting.GetMeasureLength(points[points.Count - 1], points[0], zoomFactor);
+                    }
+
+                    totalInch += currentInch;
+                    Point closePoint = points[points.Count - 1];
+                    Vector movevector = checkPoint - closePoint;
+                    if (polygonAnnot.IsMeasured())
+                    {
+                        FormattedText moveText = new FormattedText(
+                            string.Format("{0} {1}", measureSetting.GetPrecisionData(currentInch), measureSetting.RulerTranslateUnit),
+                            CultureInfo.GetCultureInfo("en-us"),
+                            FlowDirection.LeftToRight,
+                            new Typeface("YaHei"),
+                            16,
+                            TextBrush);
+
+                        FormattedText totalText = new FormattedText(
+                           string.Format("{0} {1}", measureSetting.GetPrecisionData(totalInch), measureSetting.RulerTranslateUnit),
+                           CultureInfo.GetCultureInfo("en-us"),
+                           FlowDirection.LeftToRight,
+                           new Typeface("YaHei"),
+                           16,
+                         TextBrush);
+
+                        //Judge the text display form.
+                        if (movevector.Length > moveText.Width + textPadding || defaultSettingParam.IsCreateSquarePolygonMeasure)
                         {
-                            drawingContext?.DrawText(totalText,
-                                new Point(
-                                drawPoint.X - totalText.Width - textPadding * 2,
-                                drawPoint.Y
-                                ));
+                            if (checkPoint.X >= closePoint.X)
+                            {
+                                Point linePoint = new Point(closePoint.X + movevector.Length, closePoint.Y);
+                                Point drawPoint = new Point(
+                                    linePoint.X - moveText.Width - textPadding,
+                                    linePoint.Y - moveText.Height);
+
+                                Vector anglevector = linePoint - closePoint;
+
+                                RotateTransform transform = new RotateTransform();
+                                transform.CenterX = closePoint.X;
+                                transform.CenterY = closePoint.Y;
+                                double angle = Vector.AngleBetween(movevector, anglevector);
+                                transform.Angle = -angle;
+
+                                drawingContext?.PushTransform(transform);
+                                if (!defaultSettingParam.IsCreateSquarePolygonMeasure)
+                                {
+                                    drawingContext?.DrawText(moveText, drawPoint);
+                                }
+                                if (totalInch > currentInch)
+                                {
+                                    drawingContext?.DrawText(totalText, new Point(
+                                        drawPoint.X + moveText.Width + textPadding * 2,
+                                        drawPoint.Y
+                                        ));
+                                }
+                                drawingContext.Pop();
+                            }
+                            else
+                            {
+                                Point linePoint = new Point(closePoint.X - movevector.Length, closePoint.Y);
+                                Point drawPoint = new Point(
+                                    linePoint.X + textPadding,
+                                    linePoint.Y - moveText.Height);
+
+                                Vector anglevector = linePoint - closePoint;
+                                RotateTransform transform = new RotateTransform();
+                                transform.CenterX = closePoint.X;
+                                transform.CenterY = closePoint.Y;
+                                double angle = Vector.AngleBetween(movevector, anglevector);
+                                transform.Angle = -angle;
+
+                                drawingContext?.PushTransform(transform);
+                                if (!defaultSettingParam.IsCreateSquarePolygonMeasure)
+                                {
+                                    drawingContext?.DrawText(moveText, drawPoint);
+                                }
+                                if (totalInch > currentInch)
+                                {
+                                    drawingContext?.DrawText(totalText,
+                                        new Point(
+                                        drawPoint.X - totalText.Width - textPadding * 2,
+                                        drawPoint.Y
+                                        ));
+                                }
+                                drawingContext.Pop();
+                            }
                         }
-                        drawingContext.Pop();
                     }
-                }
-                double left = drawPoints.AsEnumerable().Select(x => x.X).Min();
-                double right = drawPoints.AsEnumerable().Select(x => x.X).Max();
-                double top = drawPoints.AsEnumerable().Select(x => x.Y).Min();
-                double bottom = drawPoints.AsEnumerable().Select(x => x.Y).Max();
-                DPIRect = new Rect(left, top, right - left, bottom - top);
-                if (defaultSettingParam.IsCreateSquarePolygonMeasure)
-                {
-                    double deleft = points.AsEnumerable().Select(x => x.X).Min();
-                    double deright = points.AsEnumerable().Select(x => x.X).Max();
-                    double detop = points.AsEnumerable().Select(x => x.Y).Min();
-                    double debottom = points.AsEnumerable().Select(x => x.Y).Max();
-
-                    DPIRect = new Rect(deleft, detop, deright - deleft, debottom - detop);
-                }
 
-                MeasureEventArgs measureEvent = new MeasureEventArgs();
-                if (points.Count < 2)
-                {
-                    measureEvent.Angle = 0;
-                }
-                else
-                {
-                    Vector standVector = points[points.Count - 1] - points[points.Count - 2];
-                    Vector endvector = closePoint - checkPoint;
-                    measureEvent.Angle = (int)Math.Abs(Vector.AngleBetween(endvector, standVector));
                     if (defaultSettingParam.IsCreateSquarePolygonMeasure)
                     {
-                        measureEvent.Angle = 90;
+                        double deleft = points.AsEnumerable().Select(x => x.X).Min();
+                        double deright = points.AsEnumerable().Select(x => x.X).Max();
+                        double detop = points.AsEnumerable().Select(x => x.Y).Min();
+                        double debottom = points.AsEnumerable().Select(x => x.Y).Max();
+                        DPIRect = new Rect(deleft, detop, deright - deleft, debottom - detop);
+                    }
+                    else
+                    {
+                        double left = drawPoints.AsEnumerable().Select(x => x.X).Min();
+                        double right = drawPoints.AsEnumerable().Select(x => x.X).Max();
+                        double top = drawPoints.AsEnumerable().Select(x => x.Y).Min();
+                        double bottom = drawPoints.AsEnumerable().Select(x => x.Y).Max();
+                        DPIRect = new Rect(left, top, right - left, bottom - top);
                     }
-                }
-
-                List<Point> pon = new List<Point>();
-                if (!defaultSettingParam.IsCreateSquarePolygonMeasure)
-                {
-                    points.Add(checkPoint);
-                }
-                foreach (Point drawPoint in points)
-                {
-                    Point savePoint = new Point(
-                        (drawPoint.X - pageBound.Left) + cropPoint.X,
-                        (drawPoint.Y - pageBound.Top) + cropPoint.Y);
-                    pon.Add(DpiHelper.StandardPointToPDFPoint(new Point(
-                       (float)drawPoint.X / zoomFactor,
-                        (float)drawPoint.Y / zoomFactor
-                        )));
-                }
 
-                double area = measureSetting.ComputePolygonArea(pon.ToList());
-                double ratio = measureSetting.GetMeasureAreaRatio();
-                double rate = measureSetting.RulerTranslate / measureSetting.RulerBase;
-                double inch = area * ratio * ratio * rate * rate;
+                    MeasureEventArgs measureEvent = new MeasureEventArgs();
+                    if (points.Count < 2)
+                    {
+                        measureEvent.Angle = 0;
+                    }
+                    else
+                    {
+                        Vector standVector = points[points.Count - 1] - points[points.Count - 2];
+                        Vector endvector = closePoint - checkPoint;
+                        measureEvent.Angle = (int)Math.Abs(Vector.AngleBetween(endvector, standVector));
+                        if (defaultSettingParam.IsCreateSquarePolygonMeasure)
+                        {
+                            measureEvent.Angle = 90;
+                        }
+                    }
 
-                measureEvent.RulerTranslateUnit = measureSetting.RulerTranslateUnit;
-                measureEvent.RulerTranslate = measureSetting.RulerTranslate;
-                measureEvent.RulerBase = measureSetting.RulerBase;
-                measureEvent.RulerBaseUnit = measureSetting.RulerBaseUnit;
-                measureEvent.Precision = measureSetting.Precision;
-                measureEvent.Type = CPDFMeasureType.CPDF_AREA_MEASURE;
-                measureEvent.Distance = totalText.Text;
-                measureEvent.Area = string.Format("{0} sq {1}", measureSetting.GetPrecisionData(inch), measureSetting.RulerTranslateUnit);
+                    List<Point> pon = new List<Point>();
+                    if (!defaultSettingParam.IsCreateSquarePolygonMeasure)
+                    {
+                        points.Add(checkPoint);
+                    }
+                    foreach (Point drawPoint in points)
+                    {
+                        Point savePoint = new Point(
+                            (drawPoint.X - pageBound.Left) + cropPoint.X,
+                            (drawPoint.Y - pageBound.Top) + cropPoint.Y);
+                        pon.Add(DpiHelper.StandardPointToPDFPoint(new Point(
+                           (float)drawPoint.X / zoomFactor,
+                            (float)drawPoint.Y / zoomFactor
+                            )));
+                    }
 
-                MeasureChanged?.Invoke(this, measureEvent);
+                    double area = measureSetting.ComputePolygonArea(pon.ToList());
+                    double ratio = measureSetting.GetMeasureAreaRatio();
+                    double rate = measureSetting.RulerTranslate / measureSetting.RulerBase;
+                    double inch = area * ratio * ratio * rate * rate;
+
+                    //measureEvent.RulerTranslateUnit = measureSetting.RulerTranslateUnit;
+                    //measureEvent.RulerTranslate = measureSetting.RulerTranslate;
+                    //measureEvent.RulerBase = measureSetting.RulerBase;
+                    //measureEvent.RulerBaseUnit = measureSetting.RulerBaseUnit;
+                    //measureEvent.Precision = measureSetting.Precision;
+                    //measureEvent.Type = CPDFMeasureType.CPDF_AREA_MEASURE;
+                    //measureEvent.Distance = totalText.Text;
+                    //  measureEvent.Area = string.Format("{0} sq {1}", measureSetting.GetPrecisionData(inch), measureSetting.RulerTranslateUnit);
+
+                    MeasureChanged?.Invoke(this, measureEvent);
+                }
             }
         }
 
@@ -1515,7 +1556,7 @@ namespace ComPDFKit.Tool.DrawTool
                         {
                             dashCollection.Add(num);
                         }
-                        textBorder?.DrawDashBorder(true, drawWidth,rawWidth, dashCollection);
+                        textBorder?.DrawDashBorder(true, drawWidth, rawWidth, dashCollection);
                     }
 
                     textui.BorderThickness = new Thickness(0);
@@ -1562,7 +1603,7 @@ namespace ComPDFKit.Tool.DrawTool
                         CPDFAnnotation currentAnnot = textui.GetValue(PopupTextAttachDataProperty) as CPDFAnnotation;
                         AnnotParam annotParam = ParamConverter.AnnotConverter(cPDFViewer.GetDocument(), currentAnnot);
                         if (currentAnnot != null && currentAnnot.IsValid())
-                        { 
+                        {
                             CPDFFreeTextAnnotation updateFreeText = currentAnnot as CPDFFreeTextAnnotation;
                             if (textui.Text != string.Empty || updateFreeText.GetBorderWidth() != 0)
                             {
@@ -1581,7 +1622,7 @@ namespace ComPDFKit.Tool.DrawTool
                                     ));
                                 updateFreeText.UpdateAp();
                                 FreeTextAnnotHistory freeTextAnnotHistory = new FreeTextAnnotHistory();
-                                annotParam = ParamConverter.AnnotConverter(cPDFViewer.GetDocument(), currentAnnot); 
+                                annotParam = ParamConverter.AnnotConverter(cPDFViewer.GetDocument(), currentAnnot);
                                 annotParam.AnnotIndex = currentAnnot.Page.GetAnnotCount() - 1;
                                 freeTextAnnotHistory.CurrentParam = (FreeTextParam)annotParam;
                                 freeTextAnnotHistory.PDFDoc = cPDFViewer.GetDocument();
@@ -1758,7 +1799,7 @@ namespace ComPDFKit.Tool.DrawTool
                         {
                             dashCollection.Add(num);
                         }
-                        dashBorder.DrawDashBorder(true, drawWidth,rawWidth, dashCollection);
+                        dashBorder.DrawDashBorder(true, drawWidth, rawWidth, dashCollection);
                     }
 
                     //string fontName = string.Empty;
@@ -1916,5 +1957,16 @@ namespace ComPDFKit.Tool.DrawTool
             }
             return anglePoint;
         }
+
+        public bool IsCreateFinshed()
+        {
+            if (cPDFAnnotation is CPDFPolygonAnnotation)
+            {
+                if (drawPoints.Count <= 2)
+                    return false;
+            }
+
+            return true;
+        }
     }
 }

+ 1 - 27
Demo/Examples/ComPDFKit.Tool/DrawTool/FrameSelectTool.cs

@@ -1,35 +1,9 @@
-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 ComPDFKit.Viewer.Layer;
 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
 {

+ 3 - 12
Demo/Examples/ComPDFKit.Tool/DrawTool/MultiSelectedRect.cs

@@ -1,15 +1,9 @@
 using ComPDFKit.Tool.SettingParam;
-using ComPDFKitViewer;
 using System;
 using System.Collections.Generic;
-using System.Linq;
-using System.Reflection;
-using System.Text;
-using System.Threading.Tasks;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Media;
-using static ComPDFKit.Tool.Help.ImportWin32;
 
 namespace ComPDFKit.Tool.DrawTool
 {
@@ -20,7 +14,6 @@ namespace ComPDFKit.Tool.DrawTool
         Alone
     }
 
-
     public class MultiSelectedRect : DrawingVisual
     {
         /// <summary>
@@ -178,7 +171,7 @@ namespace ComPDFKit.Tool.DrawTool
         /// <summary>
         /// Array passed from outside for multiple selection
         /// </summary>
-        protected List<SelectedRect> selectedRects = new List<SelectedRect>();
+        internal List<SelectedRect> selectedRects = new List<SelectedRect>();
         protected Dictionary<SelectedRect,KeyValuePair<int,int>> RelationDict=new Dictionary<SelectedRect, KeyValuePair<int, int>>();
 
         protected bool isHover = false;
@@ -357,7 +350,6 @@ namespace ComPDFKit.Tool.DrawTool
             return (float)(drawRect.Height - drawDefaultRect.Height);
         }
 
-
         public void Draw()
         {
             switch (currentDrawType)
@@ -373,9 +365,9 @@ namespace ComPDFKit.Tool.DrawTool
                             SolidColorBrush solidColorBrush = drawParam.SPDFEditMultiRectFillBrush;
                             Pen pen = drawParam.SPDFEditMultiRectLinePen;
                             GetBrushAndPen(ref solidColorBrush, ref pen);
-                            if (selectedRects.Count >= 1)
+                            foreach (SelectedRect item in selectedRects)
                             {
-                                foreach (SelectedRect item in selectedRects)
+                                if (!item.IsPath)
                                 {
                                     Rect rect = item.GetRect();
                                     rect.X -= rectPadding;
@@ -435,7 +427,6 @@ namespace ComPDFKit.Tool.DrawTool
                             drawDC?.Close();
                             drawDC = null;
                         }
-
                     });
                     break;
                 case MulitiDrawMoveType.Alone:

+ 144 - 31
Demo/Examples/ComPDFKit.Tool/DrawTool/SelectedRect.cs

@@ -1,18 +1,15 @@
-using ComPDFKit.PDFAnnotation;
+using ComPDFKit.Import;
+using ComPDFKit.PDFAnnotation;
 using ComPDFKit.Tool.SettingParam;
-using ComPDFKit.Viewer.Layer;
+using ComPDFKit.Viewer.Helper;
 using ComPDFKitViewer;
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
 using System.Diagnostics;
 using System.Linq;
-using System.Reflection;
-using System.Text;
-using System.Threading.Tasks;
 using System.Windows;
 using System.Windows.Controls;
-using System.Windows.Controls.Primitives;
 using System.Windows.Input;
 using System.Windows.Media;
 using System.Windows.Media.Media3D;
@@ -45,7 +42,6 @@ namespace ComPDFKit.Tool.DrawTool
         PDFEdit
     }
 
-
     public enum DrawPointType
     {
         Circle,
@@ -73,6 +69,7 @@ namespace ComPDFKit.Tool.DrawTool
 
         public AnnotData annotData { get; set; }
 
+        public int rotationAngle { get; set; }
     }
 
     public partial class SelectedRect : DrawingVisual
@@ -126,6 +123,8 @@ namespace ComPDFKit.Tool.DrawTool
 
         protected bool isSelected = false;
 
+        protected bool canRotate = false;
+
         protected SelectedType selectedType = SelectedType.None;
 
         public SelectedType GetSelectedType()
@@ -184,6 +183,17 @@ namespace ComPDFKit.Tool.DrawTool
                 if (hitControlType != PointControlType.None)
                 {
                     cacheRect = drawRect;
+                    rotateRect = drawRect;
+                    rotateControlPoints = controlPoints.ToList();
+
+                    if (hitControlType != PointControlType.Rotate)
+                    {
+                        isInScaling = true;
+                    }
+                    else
+                    {
+                        isInRotate = true;
+                    }
                 }
             }
         }
@@ -281,7 +291,7 @@ namespace ComPDFKit.Tool.DrawTool
                             SolidColorBrush moveBrush = DrawParam.AnnotMoveBrush;
                             Pen movepen = DrawParam.AnnotMovePen;
 
-                            GetMoveBrushAndPen(ref moveBrush, ref movepen);
+                            GetMoveBrushAndPen(ref moveBrush, ref movepen); 
                             if (selectedType == SelectedType.PDFEdit)
                             {
                                 DrawMoveBounds(drawDC, hitControlType, movepen, moveBrush, drawRect, DrawParam.PDFEditMoveRectPen);
@@ -470,6 +480,7 @@ namespace ComPDFKit.Tool.DrawTool
         public virtual void ClearDraw()
         {
             SetDrawRect = drawRect = new Rect();
+            rotateAngle = 0;
             drawDC = RenderOpen();
             drawDC?.Close();
             drawDC = null;
@@ -490,7 +501,7 @@ namespace ComPDFKit.Tool.DrawTool
             {
                 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((newRect.X - rectPadding * zoom), (newRect.Y - rectPadding * zoom), (newRect.Width + 2 * rectPadding * zoom), (newRect.Height + 2 * rectPadding * zoom));
             currentZoom = zoom;
             SetDrawRect = drawRect = newRect;
             drawCenterPoint = new Point(drawRect.Left + drawRect.Width / 2, drawRect.Top + drawRect.Height / 2);
@@ -502,12 +513,22 @@ namespace ComPDFKit.Tool.DrawTool
         /// <param name="newRect">
         /// The new rect to set
         /// </param>
-        public Rect GetRect()
+        public Rect GetRect() 
         {
-            Rect rect = new Rect(drawRect.X + rectPadding * currentZoom, drawRect.Y + rectPadding * currentZoom, Math.Max(rectMinWidth, drawRect.Width - 2 * rectPadding * currentZoom), Math.Max(RectMinHeight, drawRect.Height - 2 * rectPadding * currentZoom));
+            Rect rect = new Rect(drawRect.X + rectPadding * currentZoom, drawRect.Y + rectPadding * currentZoom, Math.Max(RectMinWidth, drawRect.Width - 2 * rectPadding * currentZoom), Math.Max(RectMinHeight, drawRect.Height - 2 * rectPadding * currentZoom));
             return rect;
         }
 
+        public int GetRotation()
+        {
+            return rotateAngle;
+        }
+
+        public void SetRotation(int rotationAngle)
+        {
+            this.rotateAngle = rotationAngle;
+        }
+
         public void SetRectPadding(double rectPadding)
         {
             this.rectPadding = rectPadding;
@@ -569,19 +590,13 @@ namespace ComPDFKit.Tool.DrawTool
         {
             maxRect = rect;
         }
+
         public Rect GetMaxRect()
         {
             return maxRect;
         }
 
-        public void UpdateAnnotData(AnnotData annotData)
-        {
-            if(selectedRectData!=null)
-            {
-                selectedRectData.annotData = annotData;
-            }
-        }
-        public void SetAnnotData(AnnotData annotData)
+        public void SetAnnotData(AnnotData annotData, CPDFViewer viewer)
         {
             SetIgnorePoints(new List<PointControlType>());
             SetIsProportionalScaling(false);
@@ -614,12 +629,46 @@ namespace ComPDFKit.Tool.DrawTool
                 default:
                     break;
             }
+
             SetMaxRect(annotData.PaintOffset);
-            SetRect(annotData.PaintRect, annotData.CurrentZoom);
-            selectedRectData = new SelectedAnnotData();
+            if(annotData.AnnotType == C_ANNOTATION_TYPE.C_ANNOTATION_STAMP)
+            {
+                CRect sourceRect = new CRect();
+                annotData.Annot.GetSourceRect(ref sourceRect);
+                if (!sourceRect.IsEmpty)
+                {
+                    RenderData renderData = viewer.GetCurrentRenderPageForIndex(annotData.PageIndex);
+                    Rect zoomRect = new Rect(sourceRect.left / 72 * 96 * annotData.CurrentZoom, sourceRect.top / 72 * 96 * annotData.CurrentZoom, sourceRect.width() / 72 * 96 * annotData.CurrentZoom, sourceRect.height() / 72 * 96 * annotData.CurrentZoom);
+                    Rect rotateRect = zoomRect;
+                    rotateRect.X += renderData.PageBound.X - renderData.CropLeft * annotData.CurrentZoom;
+                    rotateRect.Y += renderData.PageBound.Y - renderData.CropTop * annotData.CurrentZoom;
+                    SetRect(rotateRect, annotData.CurrentZoom);
+                    rotateAngle = -(annotData.Annot as CPDFStampAnnotation).AnnotationRotator.GetRotation();
+                    pageRotation = annotData.Annot.Page.Rotation;
+                }
+                else
+                {
+                    SetRect(annotData.PaintRect, annotData.CurrentZoom);
+                }
+            }
+            else
+            {
+                SetRect(annotData.PaintRect, annotData.CurrentZoom);
+            }
+
+            //SetRotation(annotData.Rotation);
+            if (selectedRectData != null)
+            {
+                selectedRectData = new SelectedAnnotData();
+            }
             selectedRectData.annotData = annotData;
         }
 
+        private void SetRoationHandle(bool canRotate)
+        {
+            this.canRotate = canRotate;
+        }
+
         public void SetIsProportionalScaling(bool isProportionalScaling)
         {
             this.isProportionalScaling = isProportionalScaling;
@@ -793,7 +842,6 @@ namespace ComPDFKit.Tool.DrawTool
             if (hitResult != null && hitResult.VisualHit is DrawingVisual)
             {
                 List<PointControlType> ignoreList = GetIgnorePoints();
-
                 List<Point> IgnorePointsList = new List<Point>();
                 foreach (PointControlType type in ignoreList)
                 {
@@ -806,10 +854,33 @@ namespace ComPDFKit.Tool.DrawTool
                 {
                     Point checkPoint = controlPoints[i];
 
+                    if (canRotate)
+                    {
+                        // Convert the rotation angle from degrees to radians
+                        double angleRad = rotateAngle * Math.PI / 180.0;
+
+                        // Calculate the sine and cosine of the angle
+                        double cosAngle = Math.Cos(angleRad);
+                        double sinAngle = Math.Sin(angleRad);
+
+                        // Translate checkPoint to the origin (centerPoint becomes the origin)
+                        double translatedX = checkPoint.X - centerPoint.X;
+                        double translatedY = checkPoint.Y - centerPoint.Y;
+
+                        // Apply the rotation matrix
+                        double rotatedX = translatedX * cosAngle - translatedY * sinAngle;
+                        double rotatedY = translatedX * sinAngle + translatedY * cosAngle;
+
+                        // Translate the point back to its original position
+                        checkPoint.X = rotatedX + centerPoint.X;
+                        checkPoint.Y = rotatedY + centerPoint.Y;
+                    }
+
                     if (isIgnore && IgnorePointsList.Contains(checkPoint))
                     {
                         continue;
                     }
+
                     switch (currentDrawPointType)
                     {
                         case DrawPointType.Circle:
@@ -838,7 +909,6 @@ namespace ComPDFKit.Tool.DrawTool
                             }
                             if ((PointControlType)i == PointControlType.RightMiddle)
                             {
-
                                 if (Math.Abs(point.X - checkPoint.X) < wlen && checkVector.Length < drawRect.Height/3)
                                 {
                                     return (PointControlType)i;
@@ -872,6 +942,7 @@ namespace ComPDFKit.Tool.DrawTool
                                 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);
@@ -879,6 +950,18 @@ namespace ComPDFKit.Tool.DrawTool
                             {
                                 return (PointControlType)i;
                             }
+
+                            if (canRotate)
+                            {
+                                Point hitRotationPoint = new Point(centerPoint.X + (rotationPoint.X - centerPoint.X) * Math.Cos(rotateAngle * Math.PI / 180) - (rotationPoint.Y - centerPoint.Y) * Math.Sin(rotateAngle * Math.PI / 180),
+                                    centerPoint.Y + (rotationPoint.X - centerPoint.X) * Math.Sin(rotateAngle * Math.PI / 180) + (rotationPoint.Y - centerPoint.Y) * Math.Cos(rotateAngle * Math.PI / 180));
+                                Vector checkVector1 = point - hitRotationPoint;
+
+                                if (checkVector1.Length < pointSize)
+                                {
+                                    return PointControlType.Rotate;
+                                } 
+                            }
                             break;
 
                         case DrawPointType.Crop:
@@ -888,28 +971,58 @@ namespace ComPDFKit.Tool.DrawTool
                                 return (PointControlType)i;
                             }
                             break;
+
                         default:
                             break;
                     }
                 }
-                if (drawRect.Contains(point))
+
+                if (canRotate)
                 {
-                    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))
+                    bool isIn = DataConversionForWPF.IsPointInRotatedRectangle(point, drawRect, rotateAngle);
+                    if(isIn)
                     {
+                        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);
+                        isIn = DataConversionForWPF.IsPointInRotatedRectangle(point, rect, rotateAngle);
+                        if (isIn)
+                        {
+                            if (!ignoreList.Contains(PointControlType.Body))
+                            {
+                                return PointControlType.Body;
+                            }
+                        }
+
                         if (!ignoreList.Contains(PointControlType.Body))
                         {
-                            return PointControlType.Body;
+                            return PointControlType.Line;
                         }
                     }
-                    if (!ignoreList.Contains(PointControlType.Body))
+                }
+                else
+                {
+                    if (drawRect.Contains(point))
                     {
-                        return PointControlType.Line;
+                        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;
         }
 

+ 369 - 34
Demo/Examples/ComPDFKit.Tool/DrawTool/SelectedRect.protected.cs

@@ -1,5 +1,6 @@
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using System.Windows;
 using System.Windows.Media;
 
@@ -8,7 +9,6 @@ namespace ComPDFKit.Tool.DrawTool
     public partial class SelectedRect
     {
         #region Properties
-
         /// <summary>
         /// Current control point drawing style.
         /// </summary>
@@ -18,7 +18,6 @@ namespace ComPDFKit.Tool.DrawTool
             set;
         }
 
-
         /// <summary>
         /// Current drag drawing style.
         /// </summary>
@@ -39,6 +38,10 @@ namespace ComPDFKit.Tool.DrawTool
         /// </summary>
         protected bool isMouseDown { get; set; }
 
+        protected bool isInRotate { get; set; } = false;
+
+        protected bool isInScaling { get; set; } = false;
+
         /// <summary>
         /// Whether proportional scaling is required.
         /// </summary>
@@ -52,12 +55,12 @@ namespace ComPDFKit.Tool.DrawTool
         /// <summary>
         /// Rectangular minimum width.
         /// </summary>
-        protected int rectMinWidth { get; set; } = 10;
+        public int RectMinWidth { get; set; } = 10;
 
         /// <summary>
         /// Rectangular minimum height.
         /// </summary>
-        protected int RectMinHeight { get; set; } = 10;
+        public int RectMinHeight { get; set; } = 10;
 
         /// <summary>
         /// Current set of ignore points.
@@ -67,12 +70,20 @@ namespace ComPDFKit.Tool.DrawTool
         /// <summary>
         /// Current set of drawing rectangles (original data).
         /// </summary>
-        protected Rect SetDrawRect { get; set; } = new Rect(0, 0, 0, 0);
+        protected Rect SetDrawRect
+        {
+            get;
+            set;
+        } = new Rect(0, 0, 0, 0);
 
         /// <summary>
         /// Current drawing rectangle (calculated during operation).
         /// </summary>
-        protected Rect drawRect { get; set; } = new Rect(0, 0, 0, 0);
+        protected Rect drawRect
+        {
+            get;
+            set;
+        } = new Rect(0, 0, 0, 0);
 
         /// <summary>
         /// Maximum range that can be drawn.
@@ -94,6 +105,12 @@ namespace ComPDFKit.Tool.DrawTool
         /// </summary>
         protected List<Point> controlPoints { get; set; } = new List<Point>();
 
+        protected Point centerPoint = new Point();
+
+        protected Point rotationPoint = new Point();
+
+        protected Point dragRotationPoint = new Point();
+
         /// <summary>
         /// Move offset during movement.
         /// </summary>
@@ -119,6 +136,10 @@ namespace ComPDFKit.Tool.DrawTool
 
         protected double PDFViewerActualHeight { get; set; } = 0;
 
+        protected int rotateAngle { get; set; } = 0;
+
+        protected int pageRotation { get; set; } = 0;
+
         protected double rectPadding = 6;
 
         protected double currentZoom = 1;
@@ -127,6 +148,12 @@ namespace ComPDFKit.Tool.DrawTool
 
         protected bool disable = false;
 
+        protected List<Point> rotateControlPoints = new List<Point>();
+
+        protected Rect rotateRect = new Rect();
+
+        public bool IsPath { get; set; } = false;
+
         #endregion
 
         #region Functions
@@ -150,7 +177,33 @@ namespace ComPDFKit.Tool.DrawTool
             controlPoints.Add(new Point(currentRect.Right, currentRect.Bottom));
             controlPoints.Add(new Point(currentRect.Right, centerY));
             controlPoints.Add(new Point(currentRect.Right, currentRect.Top));
-            controlPoints.Add(new Point(centerX, currentRect.Top));
+            controlPoints.Add(new Point(centerPoint.X, currentRect.Top));
+
+            if (canRotate)
+            {
+                rotationPoint = new Point(centerPoint.X, currentRect.Top - 30);
+                switch (pageRotation)
+                {
+                    case 0:
+                        rotationPoint = new Point(centerPoint.X, currentRect.Top - 30);
+                        break;
+
+                    case 1:
+                        rotationPoint = new Point(currentRect.Right + 30, centerPoint.Y);
+                        break;
+
+                    case 2:
+                        rotationPoint = new Point(centerPoint.X, currentRect.Bottom + 30);
+                        break;
+
+                    case 3:
+                        rotationPoint = new Point(currentRect.Left - 30, centerPoint.Y);
+                        break;
+
+                    default:
+                        break;
+                }
+            }
         }
 
         protected List<Point> GetControlPoint(Rect currentRect)
@@ -234,9 +287,23 @@ namespace ComPDFKit.Tool.DrawTool
             {
                 return false;
             }
+
+            if (hitControlType == PointControlType.Rotate)
+            {
+                SetRotateByMousePoint(mousePoint);
+                return false;
+            }
+
             if (!isOutSideScaling)
             {
-                return NormalScaling(mousePoint);
+                if (selectedRectData.rotationAngle != 0)
+                {
+                    return RotateScaling(mousePoint);
+                }
+                else
+                {
+                    return NormalScaling(mousePoint);
+                }
             }
             else
             {
@@ -249,11 +316,10 @@ namespace ComPDFKit.Tool.DrawTool
             isOutSideScaling = IsOutSideScaling;
         }
 
-
         private Size GetProportionalScalingSize(double width, double height)
         {
             double minHeight = RectMinHeight + 2 * rectPadding * currentZoom;
-            double minWidth = rectMinWidth + 2 * rectPadding * currentZoom;
+            double minWidth = RectMinWidth + 2 * rectPadding * currentZoom;
             if (minWidth > width || minHeight > height)
             {
                 if (cacheRect.Width >= cacheRect.Height)
@@ -271,6 +337,13 @@ namespace ComPDFKit.Tool.DrawTool
             return new Size(width, height);
         }
 
+        private void SetRotateByMousePoint(Point mousePoint)
+        {
+            dragRotationPoint = mousePoint;
+            Vector moveVector = (mousePoint - centerPoint);
+            rotateAngle = (int)(Math.Atan2(moveVector.X, -moveVector.Y) * 180  / Math.PI) - pageRotation * 90;
+        }
+
         /// <summary>
         /// Draw the algorithm in the form of normal scaling (drag a point, only scale in one direction).
         /// </summary>
@@ -282,7 +355,7 @@ namespace ComPDFKit.Tool.DrawTool
             {
                 double left = 0, right = 0, top = 0, bottom = 0;
                 double minHeight = RectMinHeight + 2 * rectPadding * currentZoom;
-                double minWidth = rectMinWidth + 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);
@@ -434,7 +507,7 @@ namespace ComPDFKit.Tool.DrawTool
                                 }
                             }
                             else
-                            {
+                            { 
                                 if (left + minWidth > right)
                                 {
                                     right = left + minWidth;
@@ -521,11 +594,11 @@ namespace ComPDFKit.Tool.DrawTool
                     case PointControlType.Body:
                     case PointControlType.Line:
                         {
-                            Point OffsetPos = CalcMoveBound(cacheRect, ((Point)(mousePoint - mouseDownPoint)), maxRect);
-                            left = cacheRect.Left + OffsetPos.X;
-                            right = cacheRect.Right + OffsetPos.X;
-                            top = cacheRect.Top + OffsetPos.Y;
-                            bottom = cacheRect.Bottom + OffsetPos.Y;
+                            Point offsetPos = CalcMoveBound(cacheRect, ((Point)(mousePoint - mouseDownPoint)), maxRect);
+                            left = cacheRect.Left + offsetPos.X;
+                            right = cacheRect.Right + offsetPos.X;
+                            top = cacheRect.Top + offsetPos.Y;
+                            bottom = cacheRect.Bottom + offsetPos.Y;
                         }
                         break;
 
@@ -563,6 +636,182 @@ namespace ComPDFKit.Tool.DrawTool
             return false;
         }
 
+        protected bool RotateScaling(Point mouseMovePoint)
+        {
+            Point rotatePoint = new Point();
+            Point hitControlUIPos = new Point();
+            if (hitControlType < PointControlType.Body)
+            {
+                hitControlUIPos = rotateControlPoints[(int)hitControlType];
+            }
+
+            hitControlUIPos = GetRotateUIPoint(hitControlUIPos);
+            Point centerPoint = new Point((rotateRect.Left + rotateRect.Right) / 2, (rotateRect.Top + rotateRect.Bottom) / 2);
+            Vector moveVector = mouseMovePoint - mouseDownPoint;
+            Vector hitVector = hitControlUIPos - centerPoint;
+
+            Rect tmpRect = cacheRect;
+            if (hitControlType == PointControlType.LeftTop
+                || hitControlType == PointControlType.LeftBottom
+                || hitControlType == PointControlType.RightTop
+                || hitControlType == PointControlType.RightBottom)
+            {
+                if (isProportionalScaling)
+                {
+                    double vectorAngle = Vector.AngleBetween(moveVector, hitVector);
+                    double newLenght = Math.Cos(Math.PI / 180.0 * vectorAngle) * moveVector.Length;
+
+                    hitVector.Normalize();
+                    hitVector.X *= newLenght;
+                    hitVector.Y *= newLenght;
+                    rotatePoint = new Point(hitControlUIPos.X + hitVector.X, hitControlUIPos.Y + hitVector.Y);
+                }
+            }
+
+            switch (hitControlType)
+            {
+                case PointControlType.LeftTop:
+                    {
+                        Point rightBottomPoint = rotateControlPoints[(int)PointControlType.RightBottom];
+                        Point rightBottomUIPos = GetRotateUIPoint(rightBottomPoint);
+                        centerPoint = new Point((rotatePoint.X + rightBottomUIPos.X) / 2, (rotatePoint.Y + rightBottomUIPos.Y) / 2);
+
+                        Matrix rotateMatrix = new Matrix();
+                        rotateMatrix.RotateAt(-rotateAngle, centerPoint.X, centerPoint.Y);
+
+                        Point leftTopPoint = rotateMatrix.Transform(rotatePoint);
+                        rightBottomPoint = rotateMatrix.Transform(rightBottomUIPos);
+                        tmpRect = new Rect(leftTopPoint, rightBottomPoint);
+                    }
+                    break;
+
+                case PointControlType.LeftBottom:
+                    {
+                        Point rightTopPoint = rotateControlPoints[(int)PointControlType.RightTop];
+                        Point rightTopUIPos = GetRotateUIPoint(rightTopPoint);
+                        centerPoint = new Point((rotatePoint.X + rightTopUIPos.X) / 2, (rotatePoint.Y + rightTopUIPos.Y) / 2);
+
+                        Matrix rotateMatrix = new Matrix();
+                        rotateMatrix.RotateAt(-rotateAngle, centerPoint.X, centerPoint.Y);
+
+                        Point leftBottomPoint = rotateMatrix.Transform(rotatePoint);
+                        rightTopPoint = rotateMatrix.Transform(rightTopUIPos);
+                        tmpRect = new Rect(leftBottomPoint, rightTopPoint);
+                    }
+                    break;
+
+                case PointControlType.RightTop:
+                    {
+                        Point leftBottomPoint = rotateControlPoints[(int)PointControlType.LeftBottom];
+                        Point leftBottomUIPos = GetRotateUIPoint(leftBottomPoint);
+                        centerPoint = new Point((rotatePoint.X + leftBottomUIPos.X) / 2, (rotatePoint.Y + leftBottomUIPos.Y) / 2);
+
+                        Matrix rotateMatrix = new Matrix();
+                        rotateMatrix.RotateAt(-rotateAngle, centerPoint.X, centerPoint.Y);
+
+                        Point rightTopPoint = rotateMatrix.Transform(rotatePoint);
+                        leftBottomPoint = rotateMatrix.Transform(leftBottomUIPos);
+                        tmpRect = new Rect(leftBottomPoint, rightTopPoint);
+                    }
+                    break;
+
+                case PointControlType.RightBottom:
+                    {
+                        Point leftTopPoint = rotateControlPoints[(int)PointControlType.LeftTop];
+                        Point leftTopUIPos = GetRotateUIPoint(leftTopPoint);
+                        centerPoint = new Point((rotatePoint.X + leftTopUIPos.X) / 2, (rotatePoint.Y + leftTopUIPos.Y) / 2);
+
+                        Matrix rotateMatrix = new Matrix();
+                        rotateMatrix.RotateAt(-rotateAngle, centerPoint.X, centerPoint.Y);
+
+                        Point rightBottomPoint = rotateMatrix.Transform(rotatePoint);
+                        leftTopPoint = rotateMatrix.Transform(leftTopUIPos);
+                        tmpRect = new Rect(leftTopPoint, rightBottomPoint);
+                    }
+                    break;
+
+                case PointControlType.Body:
+                case PointControlType.Line:
+                    {
+                        Point offsetPos = (Point)(mouseMovePoint - mouseDownPoint);
+                        double left = cacheRect.Left + offsetPos.X;
+                        double right = cacheRect.Right + offsetPos.X;
+                        double top = cacheRect.Top + offsetPos.Y;
+                        double bottom = cacheRect.Bottom + offsetPos.Y;
+                        tmpRect = new Rect(new Point(left,top), new Point(right,bottom));
+                    }
+                    break;
+
+                default:
+                    break;
+            }
+
+            List<Point> tempPoints = new List<Point>
+            {
+                new Point(tmpRect.Left, tmpRect.Top),
+                new Point(tmpRect.Right, tmpRect.Top),
+                new Point(tmpRect.Right, tmpRect.Bottom),
+                new Point(tmpRect.Left, tmpRect.Bottom)
+            };
+
+            List<Point> boundPoint = new List<Point>();
+            Point center = new Point((tmpRect.Left + tmpRect.Right) / 2, (tmpRect.Top + tmpRect.Bottom) / 2);
+            foreach (Point point in tempPoints)
+            {
+                float x = (float)(center.X + (point.X - center.X) * Math.Cos(rotateAngle * Math.PI / 180) - (point.Y - center.Y) * Math.Sin(rotateAngle * Math.PI / 180));
+                float y = (float)(center.Y + (point.X - center.X) * Math.Sin(rotateAngle * Math.PI / 180) + (point.Y - center.Y) * Math.Cos(rotateAngle * Math.PI / 180));
+                boundPoint.Add(new Point(x, y));
+            }
+
+            Rect boundRect = new Rect(new Point(boundPoint.Min(p => p.X), boundPoint.Min(p => p.Y)), new Point(boundPoint.Max(p => p.X), boundPoint.Max(p => p.Y)));
+            if (maxRect.Contains(boundRect))
+            {
+                drawRect = tmpRect;
+            }
+            else
+            {
+                if(hitControlType == PointControlType.Body || hitControlType == PointControlType.Line)
+                {
+                    Point boundRectCenterPos = new Point((boundRect.Left + boundRect.Right) / 2, (boundRect.Top + boundRect.Bottom) / 2);
+                    Point maxRectCenterPos = new Point((maxRect.Left + maxRect.Right) / 2, (maxRect.Top + maxRect.Bottom) / 2);
+                    Vector moveCenterVector = boundRectCenterPos - maxRectCenterPos;
+                    Point moveOffsetPos = new Point(0, 0);
+                    if (Math.Abs(moveCenterVector.X) > (maxRect.Width - boundRect.Width) / 2)
+                    {
+                        double moveLength = maxRectCenterPos.X - boundRectCenterPos.X;
+                        moveOffsetPos.X = Math.Abs(moveLength) - (maxRect.Width - boundRect.Width) / 2;
+                        if (moveLength < 0)
+                        {
+                            moveOffsetPos.X *= -1;
+                        }
+                    }
+
+                    if (Math.Abs(moveCenterVector.Y) > (maxRect.Height - boundRect.Height) / 2)
+                    {
+                        double moveLength = maxRectCenterPos.Y - boundRectCenterPos.Y;
+                        moveOffsetPos.Y = Math.Abs(moveLength) - (maxRect.Height - boundRect.Height) / 2;
+                        if (moveLength < 0)
+                        {
+                            moveOffsetPos.Y *= -1;
+                        }
+                    }
+
+                    drawRect = new Rect(tmpRect.Left + moveOffsetPos.X, tmpRect.Top + moveOffsetPos.Y, tmpRect.Width, tmpRect.Height);
+                }
+            }
+
+            moveOffset = new Point(drawRect.X - cacheRect.X, drawRect.Y - cacheRect.Y);
+            return true;
+        }
+
+        private Point GetRotateUIPoint(Point point)
+        {
+            Point centerPoint = new Point((rotateRect.Left + rotateRect.Right) / 2, (rotateRect.Top + rotateRect.Bottom) / 2);
+            Matrix rotateMatrix = new Matrix();
+            rotateMatrix.RotateAt(rotateAngle, centerPoint.X, centerPoint.Y);
+            return rotateMatrix.Transform(point);
+        }
+
         /// <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>
@@ -574,7 +823,7 @@ namespace ComPDFKit.Tool.DrawTool
             {
                 double left = 0, right = 0, top = 0, bottom = 0;
                 double minHeight = RectMinHeight + 2 * rectPadding * currentZoom;
-                double minWidth = rectMinWidth + 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);
@@ -988,29 +1237,115 @@ namespace ComPDFKit.Tool.DrawTool
         /// </param>
         protected void DrawSquarePoint(DrawingContext drawingContext, List<PointControlType> ignoreList, int PointSize, Pen PointPen, SolidColorBrush BorderBrush)
         {
-            GeometryGroup controlGroup = new GeometryGroup();
-            controlGroup.FillRule = FillRule.Nonzero;
-            List<Point> ignorePointsList = new List<Point>();
-            // Get specific points
-            foreach (PointControlType type in ignoreList)
+            RotateTransform rotateTransform = new RotateTransform(rotateAngle, centerPoint.X, centerPoint.Y);
+            if (canRotate && !isInScaling)
             {
-                if ((int)type < controlPoints.Count)
+                Point currentRotationPoint = isInRotate ? dragRotationPoint : rotationPoint;
+                double angleInRadians = rotateAngle * (Math.PI / 180);
+                double sinValue = Math.Sin(angleInRadians);
+                double cosValue = Math.Cos(angleInRadians);
+                double rotatedX = 0;
+                double rotatedY = 0;
+                switch (pageRotation)
                 {
-                    ignorePointsList.Add(controlPoints[(int)type]);
+                    case 0:
+                         rotatedX = currentRotationPoint.X - pointSize * sinValue;
+                         rotatedY = currentRotationPoint.Y + pointSize * cosValue;
+                        break;
+
+                    case 1:
+                        rotatedX = currentRotationPoint.X - pointSize * cosValue;
+                        rotatedY = currentRotationPoint.Y + pointSize * sinValue;
+                        break;
+
+                    case 2:
+                        rotatedX = currentRotationPoint.X + pointSize * sinValue;
+                        rotatedY = currentRotationPoint.Y - pointSize * cosValue;
+                        break;
+
+                    case 3:
+                        rotatedX = currentRotationPoint.X + pointSize * sinValue;
+                        rotatedY = currentRotationPoint.Y - pointSize * cosValue;
+                        break;
+
+                    default:
+                        break;
+                }
+
+                GeometryGroup rotateGroup = new GeometryGroup();
+                LineGeometry moveLineGeometry = new LineGeometry(centerPoint, new Point(rotatedX, rotatedY));
+                EllipseGeometry ellipseGeometry = new EllipseGeometry(currentRotationPoint, PointSize, pointSize);
+                rotateGroup.Children.Add(moveLineGeometry);
+                rotateGroup.Children.Add(ellipseGeometry);
+                if (!isInRotate)
+                {
+                    rotateGroup.Children.Remove(moveLineGeometry);
+                    LineGeometry stopLineGeometry = new LineGeometry(centerPoint, new Point(currentRotationPoint.X, currentRotationPoint.Y + pointSize));
+                    switch (pageRotation)
+                    {
+                        case 0:
+                            stopLineGeometry = new LineGeometry(centerPoint, new Point(currentRotationPoint.X, currentRotationPoint.Y + pointSize));
+
+                            break;
+
+                        case 1:
+                            stopLineGeometry = new LineGeometry(centerPoint, new Point(currentRotationPoint.X - pointSize, currentRotationPoint.Y ));
+
+                            break;
+
+                        case 2:
+                            stopLineGeometry = new LineGeometry(centerPoint, new Point(currentRotationPoint.X, currentRotationPoint.Y - pointSize));
+
+                            break;
+
+                        case 3:
+                            stopLineGeometry = new LineGeometry(centerPoint, new Point(currentRotationPoint.X + pointSize, currentRotationPoint.Y));
+                            break;
+
+                        default:
+                            break;
+                    }
+
+                    rotateGroup.Children.Add(stopLineGeometry);
+                    drawingContext.PushTransform(rotateTransform);
+                }
+
+                drawingContext?.DrawGeometry(BorderBrush, PointPen, rotateGroup);
+                if (!isInRotate)
+                {
+
+                    drawingContext.Pop();
                 }
             }
-            for (int i = 0; i < controlPoints.Count; i++)
+            if (!isInRotate)
             {
-                Point controlPoint = controlPoints[i];
-                if (ignorePointsList.Contains(controlPoint))
+                GeometryGroup controlGroup = new GeometryGroup();
+                controlGroup.FillRule = FillRule.Nonzero;
+                List<Point> ignorePointsList = new List<Point>();
+                // Get specific points
+                foreach (PointControlType type in ignoreList)
                 {
-                    continue;
+                    if ((int)type < controlPoints.Count)
+                    {
+                        ignorePointsList.Add(controlPoints[(int)type]);
+                    }
                 }
-                RectangleGeometry rectPoint = new RectangleGeometry(new Rect(controlPoint.X - PointSize, controlPoint.Y - PointSize,
-                    PointSize * 2, PointSize * 2), 1, 1);
-                controlGroup.Children.Add(rectPoint);
+                for (int i = 0; i < controlPoints.Count; i++)
+                {
+                    Point controlPoint = controlPoints[i];
+                    if (ignorePointsList.Contains(controlPoint))
+                    {
+                        continue;
+                    }
+                    RectangleGeometry rectPoint = new RectangleGeometry(new Rect(controlPoint.X - PointSize, controlPoint.Y - PointSize,
+                        PointSize * 2, PointSize * 2), 1, 1);
+                    controlGroup.Children.Add(rectPoint);
+                }
+
+                drawingContext.PushTransform(rotateTransform);
+                drawingContext?.DrawGeometry(BorderBrush, PointPen, controlGroup);
+                drawingContext.Pop();
             }
-            drawingContext?.DrawGeometry(BorderBrush, PointPen, controlGroup);
         }
 
         protected void DrawCropPoint(DrawingContext drawingContext, List<PointControlType> ignoreList, int PointSize, Pen PointPen, SolidColorBrush BorderBrush)
@@ -1168,6 +1503,7 @@ namespace ComPDFKit.Tool.DrawTool
         protected void InvokeDataChangEvent(bool isFinish)
         {
             selectedRectData.Square = GetRect();
+            selectedRectData.rotationAngle = rotateAngle;
             if (isFinish)
             {
                 DataChanged?.Invoke(this, selectedRectData);
@@ -1196,7 +1532,6 @@ namespace ComPDFKit.Tool.DrawTool
             Draw();
         }
 
-
         /// <summary>
         /// Get the current set of ignore points
         /// </summary>

+ 100 - 39
Demo/Examples/ComPDFKit.Tool/Help/ParamConverter.cs

@@ -9,7 +9,8 @@ using ComPDFKit.PDFPage.Edit;
 using ComPDFKit.Tool.SettingParam;
 using ComPDFKit.Tool.UndoManger;
 using ComPDFKit.Viewer.Helper;
-using ComPDFKitViewer.Annot;
+using ComPDFKitViewer.Helper;
+using ComPDFKitViewer;
 using System.Collections.Generic;
 using System.IO;
 using System.Linq;
@@ -232,12 +233,39 @@ namespace ComPDFKit.Tool.Help
             return new AnnotHistory();
         }
 
-        public static bool RemovePageAnnot(Dictionary<int, List<int>> removeAnnots, CPDFDocument cPDFDocument)
+        public static bool RemovePageAnnot(Dictionary<int, List<int>> removeAnnots,  CPDFViewer cPDFViewer)
         {
+            CPDFDocument cPDFDocument = cPDFViewer.GetDocument();
             if (cPDFDocument == null || removeAnnots.Count <= 0)
             {
                 return false;
             }
+
+            GroupHistory historyGroup = new GroupHistory();
+            foreach (int pageIndex in removeAnnots.Keys)
+            {
+                CPDFPage pageCore = cPDFDocument.PageAtIndex(pageIndex);
+                List<CPDFAnnotation> cPDFAnnotations = pageCore.GetAnnotations();
+                foreach (int annotIndex in removeAnnots[pageIndex])
+                {
+                    CPDFAnnotation cPDFAnnotation = cPDFAnnotations.ElementAtOrDefault(annotIndex);
+                    if (cPDFAnnotation != null)
+                    {
+                        AnnotParam annotParam = CPDFDataConverterToAnnotParam(cPDFDocument, pageIndex, cPDFAnnotation);
+                        AnnotHistory annotHistory = CreateHistory(cPDFAnnotation);
+                        annotHistory.CurrentParam = annotParam;
+                        annotHistory.PDFDoc = cPDFDocument;
+                        annotHistory.Action = HistoryAction.Remove;
+                        historyGroup.Histories.Add(annotHistory);
+                    }
+                }
+            }
+
+            if (historyGroup.Histories.Count > 0)
+            {
+                cPDFViewer.UndoManager.AddHistory(historyGroup);
+            }
+
             foreach (int pageIndex in removeAnnots.Keys)
             {
                 CPDFPage pageCore = cPDFDocument.PageAtIndex(pageIndex);
@@ -251,7 +279,8 @@ namespace ComPDFKit.Tool.Help
                     }
                 }
             }
-            return false;
+
+            return true;
         }
 
         public static FormField ConverterWidgetFormFlags(int Flags, bool IsHidden)
@@ -374,10 +403,10 @@ namespace ComPDFKit.Tool.Help
             return annotParam;
         }
 
-        public static PDFEditParam CPDFDataConverterToPDFEitParam(CPDFDocument cPDFDocument, CPDFEditArea cPDFEditArea, int PageIndex)
+        public static PDFEditParam CPDFDataConverterToPDFEitParam(CPDFDocument cPDFDocument, CPDFEditArea cPDFEditArea, int pageIndex)
         {
             PDFEditParam annotParam = null;
-            if (cPDFEditArea == null && !cPDFEditArea.IsValid() && cPDFDocument == null && !cPDFDocument.IsValid() && PageIndex >= 0)
+            if (cPDFEditArea == null && !cPDFEditArea.IsValid() && cPDFDocument == null && !cPDFDocument.IsValid() && pageIndex >= 0)
             {
                 return null;
             }
@@ -386,11 +415,15 @@ namespace ComPDFKit.Tool.Help
                 case CPDFEditType.None:
                     break;
                 case CPDFEditType.EditText:
-                    annotParam = GetTextEditParam(cPDFDocument, cPDFEditArea as CPDFEditTextArea, PageIndex);
+                    annotParam = GetTextEditParam(cPDFDocument, cPDFEditArea as CPDFEditTextArea, pageIndex);
                     break;
                 case CPDFEditType.EditImage:
-                    annotParam = GetImageEditParam(cPDFDocument, cPDFEditArea as CPDFEditImageArea, PageIndex);
+                    annotParam = GetImageEditParam(cPDFDocument, cPDFEditArea as CPDFEditImageArea, pageIndex);
+                    break;
+                case CPDFEditType.EditPath:
+                    annotParam = GetPathEditParam(cPDFDocument, cPDFEditArea as CPDFEditPathArea, pageIndex);
                     break;
+
                 default:
                     break;
             }
@@ -400,7 +433,7 @@ namespace ComPDFKit.Tool.Help
 
         #region PDFEdit
 
-        internal static TextEditParam GetTextEditParam(CPDFDocument cPDFDocument, CPDFEditTextArea cPDFEditArea, int PageIndex)
+        internal static TextEditParam GetTextEditParam(CPDFDocument cPDFDocument, CPDFEditTextArea cPDFEditArea, int pageIndex)
         {
             TextEditParam textEditParam = new TextEditParam();
             string fontName = "Helvetica";
@@ -417,10 +450,10 @@ namespace ComPDFKit.Tool.Help
             textEditParam.Transparency = transparency;
             textEditParam.TextAlign = cPDFEditArea.GetTextSectionAlign();
             textEditParam.EditType = CPDFEditType.EditText;
-            CPDFPage docPage = cPDFDocument.PageAtIndex(PageIndex);
-            CPDFEditPage EditPage = docPage.GetEditPage();
-            textEditParam.EditIndex = EditPage.GetEditAreaList().IndexOf(cPDFEditArea);
-            textEditParam.PageIndex = PageIndex;
+            CPDFPage docPage = cPDFDocument.PageAtIndex(pageIndex);
+            CPDFEditPage editPage = docPage.GetEditPage();
+            textEditParam.EditIndex = editPage.GetEditAreaList().IndexOf(cPDFEditArea);
+            textEditParam.PageIndex = pageIndex;
 
             if(string.IsNullOrEmpty(cPDFEditArea.SelectText))
             {
@@ -436,18 +469,38 @@ namespace ComPDFKit.Tool.Help
             return textEditParam;
         }
 
-        internal static ImageEditParam GetImageEditParam(CPDFDocument cPDFDocument, CPDFEditImageArea cPDFEditArea, int PageIndex)
+        internal static ImageEditParam GetImageEditParam(CPDFDocument cPDFDocument, CPDFEditImageArea cPDFEditArea, int pageIndex)
         {
             ImageEditParam imageEditParam = new ImageEditParam();
             imageEditParam.Transparency = cPDFEditArea.GetImageTransparency();
+            imageEditParam.Rotate = cPDFEditArea.GetRotation();
+            imageEditParam.ClipRect = cPDFEditArea.GetClipRect();
             imageEditParam.EditType = CPDFEditType.EditImage;
-            CPDFPage docPage = cPDFDocument.PageAtIndex(PageIndex);
-            CPDFEditPage EditPage = docPage.GetEditPage();
-            imageEditParam.EditIndex = EditPage.GetEditAreaList().IndexOf(cPDFEditArea);
-            imageEditParam.PageIndex = PageIndex;
+
+            CPDFPage docPage = cPDFDocument.PageAtIndex(pageIndex);
+            CPDFEditPage editPage = docPage.GetEditPage();
+            imageEditParam.EditIndex = editPage.GetEditAreaList().IndexOf(cPDFEditArea);
+            imageEditParam.PageIndex = pageIndex;
             return imageEditParam;
         }
 
+        internal static PathEditParam GetPathEditParam(CPDFDocument cPDFDocument, CPDFEditPathArea cPDFEditArea, int pageIndex)
+        {
+            PathEditParam pathEditParam = new PathEditParam();
+            pathEditParam.Transparency = cPDFEditArea.GetTransparency();
+            pathEditParam.Rotate = cPDFEditArea.GetRotation();
+            pathEditParam.StrokeColor = cPDFEditArea.GetStrokeColor();
+            pathEditParam.FillColor = cPDFEditArea.GetFillColor();
+            pathEditParam.ClipRect = cPDFEditArea.GetClipRect();
+            pathEditParam.EditType = CPDFEditType.EditPath;
+
+            CPDFPage docPage = cPDFDocument.PageAtIndex(pageIndex);
+            CPDFEditPage editPage = docPage.GetEditPage();
+            pathEditParam.EditIndex = editPage.GetEditAreaList().IndexOf(cPDFEditArea);
+            pathEditParam.PageIndex = pageIndex;
+            return pathEditParam;
+        }
+
         #endregion
 
         #region Widegt
@@ -1004,7 +1057,7 @@ namespace ComPDFKit.Tool.Help
                 case C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON:
                     {
                         CPDFPolygonAnnotation polygonAnnot= pdfAnnot as CPDFPolygonAnnotation;
-                        if(polygonAnnot!=null && polygonAnnot.IsMeasured())
+                        if(polygonAnnot!=null)
                         {
                             return GetPolygonMeasureParam(polygonAnnot);
                         }
@@ -1038,6 +1091,7 @@ namespace ComPDFKit.Tool.Help
             {
                 annotParam.AnnotIndex = pdfAnnot.Page.GetAnnotCount() - 1;
             }
+
             annotParam.PageIndex = pdfAnnot.Page.PageIndex;
         }
 
@@ -1188,7 +1242,6 @@ namespace ComPDFKit.Tool.Help
             }
 
             PolygonMeasureParam polygonParam = new PolygonMeasureParam();
-
             if (polygonAnnot.LineColor != null && polygonAnnot.LineColor.Length == 3)
             {
                 polygonParam.LineColor = new byte[3]
@@ -1630,7 +1683,6 @@ namespace ComPDFKit.Tool.Help
             }
 
             StampParam stampParam = new StampParam();
-
             C_STAMP_TYPE stampType = stampAnnot.GetStampType();
             switch (stampType)
             {
@@ -1660,6 +1712,7 @@ namespace ComPDFKit.Tool.Help
                     }
                     break;
                 case C_STAMP_TYPE.IMAGE_STAMP:
+                case C_STAMP_TYPE.UNKNOWN_STAMP:
                     {
                         stampParam.StampType = stampType;
                         CRect rawRect = stampAnnot.GetRect();
@@ -1697,8 +1750,13 @@ namespace ComPDFKit.Tool.Help
                     return null;
             }
 
-            GetAnnotCommonParam(stampAnnot, stampParam);
+            stampParam.PageRotation = stampAnnot.Page.Rotation;
+            stampParam.Rotation = stampAnnot.AnnotationRotator.GetRotation();
+            CRect sourceRect = new CRect();
+            stampAnnot.GetSourceRect(ref sourceRect);
+            stampParam.SourceRect = sourceRect;
 
+            GetAnnotCommonParam(stampAnnot, stampParam);
             return stampParam;
         }
 
@@ -1710,7 +1768,6 @@ namespace ComPDFKit.Tool.Help
             }
 
             LinkParam linkParam = new LinkParam();
-
             CPDFAction linkAction = linkAnnot.GetLinkAction();
             if (linkAction != null)
             {
@@ -1791,7 +1848,7 @@ namespace ComPDFKit.Tool.Help
                     redactParam.FontColor = new byte[3] { redactAnnot.TextDa.FontColor[0], redactAnnot.TextDa.FontColor[1], redactAnnot.TextDa.FontColor[2] };
                 }
                 
-               redactParam.FontName= redactAnnot.TextDa.FontName;
+                redactParam.FontName= redactAnnot.TextDa.FontName;
                 redactParam.FontSize = redactAnnot.TextDa.FontSize;
                 redactParam.Alignment=redactAnnot.TextAlignment;
             }
@@ -1844,21 +1901,33 @@ namespace ComPDFKit.Tool.Help
 
         internal static PolygonMeasureParam GetPolygonMeasureParam(CPDFPolygonAnnotation polygonAnnot)
         {
-            if (polygonAnnot == null || polygonAnnot.IsValid() == false || polygonAnnot.IsMeasured() == false)
+            if (polygonAnnot == null || polygonAnnot.IsValid() == false)
             {
                 return null;
             }
 
             PolygonMeasureParam measureParam = new PolygonMeasureParam();
-            CPDFAreaMeasure areaMeasure = polygonAnnot.GetAreaMeasure();
-            measureParam.measureInfo = areaMeasure.MeasureInfo;
+            if(polygonAnnot.IsMeasured())
+            {
+                CPDFAreaMeasure areaMeasure = polygonAnnot.GetAreaMeasure();
+                measureParam.measureInfo = areaMeasure.MeasureInfo;
+                CTextAttribute textAttr = polygonAnnot.GetTextAttribute();
+                measureParam.FontName = textAttr.FontName;
+                measureParam.FontSize = textAttr.FontSize;
+                if (textAttr.FontColor != null && textAttr.FontColor.Length == 3)
+                {
+                    measureParam.FontColor = new byte[] { textAttr.FontColor[0], textAttr.FontColor[1], textAttr.FontColor[2] };
+                }
+                measureParam.IsBold = CFontNameHelper.IsBold(textAttr.FontName);
+                measureParam.IsItalic = CFontNameHelper.IsItalic(textAttr.FontName);
+            }
 
             if (polygonAnnot.LineColor != null && polygonAnnot.LineColor.Length == 3)
             {
                 measureParam.LineColor = new byte[] { polygonAnnot.LineColor[0], polygonAnnot.LineColor[1], polygonAnnot.LineColor[2] };
             }
 
-            if(polygonAnnot.BgColor!=null && polygonAnnot.BgColor.Length == 3)
+            if(polygonAnnot.HasBgColor && polygonAnnot.BgColor!=null && polygonAnnot.BgColor.Length == 3)
             {
                 measureParam.HasFillColor = true;
                 measureParam.FillColor = new byte[] { polygonAnnot.BgColor[0], polygonAnnot.BgColor[1], polygonAnnot.BgColor[2] };
@@ -1869,15 +1938,7 @@ namespace ComPDFKit.Tool.Help
             measureParam.LineWidth = polygonAnnot.LineWidth;
             measureParam.Transparency = polygonAnnot.Transparency;
             measureParam.LineDash = polygonAnnot.Dash;
-            CTextAttribute textAttr = polygonAnnot.GetTextAttribute();
-            measureParam.FontName = textAttr.FontName;
-            measureParam.FontSize = textAttr.FontSize;
-            if (textAttr.FontColor != null && textAttr.FontColor.Length == 3)
-            {
-                measureParam.FontColor = new byte[] { textAttr.FontColor[0], textAttr.FontColor[1], textAttr.FontColor[2] };
-            }
-            measureParam.IsBold = CFontNameHelper.IsBold(textAttr.FontName);
-            measureParam.IsItalic = CFontNameHelper.IsItalic(textAttr.FontName);
+            measureParam.BorderEffector = polygonAnnot.GetAnnotBorderEffector();
 
             GetAnnotCommonParam(polygonAnnot, measureParam);
             return measureParam;
@@ -2972,7 +3033,7 @@ namespace ComPDFKit.Tool.Help
                             {
                                 stampText = string.Empty;
                             }
-                            stampAnnot.SetStandardStamp(stampText, CurrentParam.Rotation);
+                            stampAnnot.SetStandardStamp(stampText, CurrentParam.PageRotation);
                             stampAnnot.SetRect(CurrentParam.ClientRect);
                         }
                         break;
@@ -2993,7 +3054,7 @@ namespace ComPDFKit.Tool.Help
                                 dateText,
                                 CurrentParam.TextStampShape,
                                 CurrentParam.TextStampColor,
-                                CurrentParam.Rotation);
+                                CurrentParam.PageRotation);
                             stampAnnot.SetRect(CurrentParam.ClientRect);
                         }
                         break;
@@ -3010,7 +3071,7 @@ namespace ComPDFKit.Tool.Help
                                     imageData,
                                     imageWidth,
                                     imageHeight,
-                                    CurrentParam.Rotation);
+                                    CurrentParam.PageRotation);
                             }
                         }
                         break;

+ 2 - 2
Demo/Examples/ComPDFKit.Tool/Properties/AssemblyInfo.cs

@@ -15,5 +15,5 @@ using System.Runtime.InteropServices;
 
 [assembly: Guid("a061ee7a-6704-4bd9-86ee-48ed5df75e2f")]
 
-[assembly: AssemblyVersion("2.1.0.0")]
-[assembly: AssemblyFileVersion("2.1.0.0")]
+[assembly: AssemblyVersion("2.2.0.0")]
+[assembly: AssemblyFileVersion("2.2.0.0")]

BIN
Demo/Examples/ComPDFKit.Tool/Resource/Cursor/Rotation.cur


+ 11 - 7
Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam.cs

@@ -4,27 +4,31 @@ using System.Windows;
 
 namespace ComPDFKit.Tool
 {
-	public class AnnotParam
+    public class AnnotParam
     {
         public string Content { get; set; } = string.Empty;
         public string Author { get; set; } = string.Empty;
         public string CreateTime { get; set; } = string.Empty;
         public string UpdateTime { get; set; } = string.Empty;
-        public C_ANNOTATION_TYPE CurrentType {  get; set; }
+        public C_ANNOTATION_TYPE CurrentType { get; set; }
         public bool Locked { get; set; }
 
         /// <summary>
         /// The rectangle of the annotation within the PDF (PDF DPI)
         /// </summary>
         public CRect ClientRect { get; set; }
-        public int PageIndex {  get; set; }
-        public int AnnotIndex {  get; set; }
-        public byte Transparency {  get; set; }
+        public int PageIndex { get; set; }
+        public int AnnotIndex { get; set; }
+        public byte Transparency
+        {
+            get;
+            set;
+        } = 255;
         public virtual bool CopyTo(AnnotParam transfer)
         {
             if (transfer == null)
             {
-               return false;
+                return false;
             }
 
             transfer.Content = Content;
@@ -34,7 +38,7 @@ namespace ComPDFKit.Tool
             transfer.CurrentType = CurrentType;
             transfer.Locked = Locked;
             transfer.ClientRect = ClientRect;
-            transfer.CurrentType=CurrentType;
+            transfer.CurrentType = CurrentType;
             transfer.PageIndex = PageIndex;
             transfer.Transparency = Transparency;
             transfer.AnnotIndex = AnnotIndex;

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

@@ -20,7 +20,7 @@ namespace ComPDFKit.Tool
         public bool IsItalic { get; set; }
         public string FontName { get; set; } = string.Empty;
         public double FontSize { get; set; }
-        public C_TEXT_ALIGNMENT Alignment {  get; set; }
+        public C_TEXT_ALIGNMENT Alignment { get; set; }
         public float[] Dash { get; set; }
 
         public override bool CopyTo(AnnotParam transfer)

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

@@ -6,17 +6,17 @@ using System.Windows.Media;
 
 namespace ComPDFKit.Tool
 {
-	public class HighlightParam:AnnotParam
+    public class HighlightParam : AnnotParam
     {
 
-        public  HighlightParam()
+        public HighlightParam()
         {
             CurrentType = C_ANNOTATION_TYPE.C_ANNOTATION_HIGHLIGHT;
         }
 
-        public byte[] HighlightColor { get; set; }
+        public byte[] HighlightColor { get; set; } = new byte[3] { 255, 0, 0 };
 
-        public List<CRect> QuardRects {  get; set; }
+        public List<CRect> QuardRects { get; set; }
 
         public override bool CopyTo(AnnotParam transfer)
         {
@@ -31,7 +31,7 @@ namespace ComPDFKit.Tool
                 return false;
             }
 
-            if(HighlightColor!=null )
+            if (HighlightColor != null)
             {
                 highlightTransfer.HighlightColor = (byte[])HighlightColor.Clone();
             }

+ 25 - 13
Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/LineMeasureParam.cs

@@ -12,24 +12,36 @@ namespace ComPDFKit.Tool
 {
     public class LineMeasureParam : AnnotParam
     {
-        public LineMeasureParam() 
+        public LineMeasureParam()
         {
             CurrentType = C_ANNOTATION_TYPE.C_ANNOTATION_LINE;
+            Transparency = 255;
         }
-        public byte[] LineColor { get; set; }
-        public float LineWidth { get; set; }
-        public float[] LineDash { get; set; }
+        public byte[] LineColor { get; set; } = new byte[] { 255, 0, 0 };
+        public float LineWidth { get; set; } = 2;
+        public float[] LineDash { get; set; } = new float[] { };
         public CPoint HeadPoint { get; set; }
         public CPoint TailPoint { get; set; }
-        public C_LINE_TYPE HeadLineType { get; set; }
-        public C_LINE_TYPE TailLineType { get; set; }
-        public string FontName { get; set; }
-        public double FontSize { get; set; }
-        public byte[] FontColor { get; set; }
-        public bool IsBold { get; set; }
-        public bool IsItalic { get; set; }
-        public C_BORDER_STYLE BorderStyle { get; set; }
+        public C_LINE_TYPE HeadLineType { get; set; } = C_LINE_TYPE.LINETYPE_ARROW;
+        public C_LINE_TYPE TailLineType { get; set; } = C_LINE_TYPE.LINETYPE_ARROW;
+        public string FontName { get; set; } = "Arial";
+        public double FontSize { get; set; } = 14;
+        public byte[] FontColor { get; set; } = new byte[] { 255, 0, 0 };
+        public bool IsBold { get; set; } = false;
+        public bool IsItalic { get; set; } = false;
+        public C_BORDER_STYLE BorderStyle { get; set; } = C_BORDER_STYLE.BS_SOLID;
         public CPDFMeasureInfo measureInfo { get; set; }
+            = new CPDFMeasureInfo
+            {
+                Unit = CPDFMeasure.CPDF_CM,
+                Precision = CPDFMeasure.PRECISION_VALUE_TWO,
+                RulerBase = 1,
+                RulerBaseUnit = CPDFMeasure.CPDF_CM,
+                RulerTranslate = 1,
+                RulerTranslateUnit = CPDFMeasure.CPDF_CM,
+                CaptionType = CPDFCaptionType.CPDF_CAPTION_LENGTH,
+            };
+
         public double LeadLength {  get; set; }
         public double LeadExtension {  get; set; }
         public double LeadOffset {  get; set; }
@@ -77,7 +89,7 @@ namespace ComPDFKit.Tool
                     RulerBase = measureInfo.RulerBase,
                     RulerBaseUnit = measureInfo.RulerBaseUnit,
                     RulerTranslateUnit = measureInfo.RulerTranslateUnit,
-                    RulerTranslate= measureInfo.RulerTranslate,
+                    RulerTranslate = measureInfo.RulerTranslate,
                     CaptionType = measureInfo.CaptionType,
                 };
                 lineTransfer.measureInfo = cPDFMeasureInfo;

+ 18 - 7
Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/PolyLineMeasureParam.cs

@@ -15,18 +15,29 @@ namespace ComPDFKit.Tool
         public PolyLineMeasureParam()
         {
             CurrentType = C_ANNOTATION_TYPE.C_ANNOTATION_POLYLINE;
+            Transparency = 255;
         }
-        public byte[] LineColor { get; set; }
-        public float LineWidth { get; set; }
+        public byte[] LineColor { get; set; } = new byte[] { 255, 0, 0, };
+        public float LineWidth { get; set; } = 2;
         public float[] LineDash { get; set; }
         public List<CPoint> SavePoints { get; set; }
-        public string FontName { get; set; }
-        public double FontSize { get; set; }
-        public byte[] FontColor { get; set; }
+        public string FontName { get; set; } = "Arial";
+        public double FontSize { get; set; } = 14;
+        public byte[] FontColor { get; set; } = new byte[] { 255, 0, 0, };
         public bool IsBold { get; set; }
         public bool IsItalic { get; set; }
         public C_BORDER_STYLE BorderStyle { get; set; }
-        public CPDFMeasureInfo measureInfo { get; set; }
+        public CPDFMeasureInfo measureInfo { get; set; } =
+            new CPDFMeasureInfo
+            {
+                Unit = CPDFMeasure.CPDF_CM,
+                Precision = CPDFMeasure.PRECISION_VALUE_TWO,
+                RulerBase = 1,
+                RulerBaseUnit = CPDFMeasure.CPDF_CM,
+                RulerTranslate = 1,
+                RulerTranslateUnit = CPDFMeasure.CPDF_CM,
+                CaptionType = CPDFCaptionType.CPDF_CAPTION_LENGTH,
+            };
 
         public override bool CopyTo(AnnotParam transfer)
         {
@@ -78,7 +89,7 @@ namespace ComPDFKit.Tool
                     RulerBaseUnit = measureInfo.RulerBaseUnit,
                     RulerTranslateUnit = measureInfo.RulerTranslateUnit,
                     CaptionType = measureInfo.CaptionType,
-                    RulerTranslate= measureInfo.RulerTranslate,
+                    RulerTranslate = measureInfo.RulerTranslate,
                 };
                 polygonTransfer.measureInfo = cPDFMeasureInfo;
             }

+ 47 - 24
Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/PolygonMeasureParam.cs

@@ -14,27 +14,46 @@ namespace ComPDFKit.Tool
 {
     public class PolygonMeasureParam : AnnotParam
     {
-        public PolygonMeasureParam() 
+        public PolygonMeasureParam()
         {
             CurrentType = C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON;
-        }    
-        public byte[] FillColor { get; set; }
+        }
+
+        public byte[] FillColor { get; set; } = new byte[] { 255, 0, 0, };
         public bool HasFillColor { get; set; }
-        public byte[] LineColor { get; set; }
+        public byte[] LineColor
+        {
+            get;
+            set;
+        }
         public float LineWidth { get; set; }
         public float[] LineDash { get; set; }
-        public List<CPoint> SavePoints { get; set; } 
+        public List<CPoint> SavePoints { get; set; }
         public byte[] EndLineColor { get; set; }
         public double EndLineWidth { get; set; }
         public double EndTransparency { get; set; }
         public DashStyle EndLineDash { get; set; }
+        public CPDFBorderEffector BorderEffector
+        {
+            get;
+            set;
+        }
         public string FontName { get; set; }
         public double FontSize { get; set; }
         public byte[] FontColor { get; set; }
         public bool IsBold { get; set; }
         public bool IsItalic { get; set; }
+        public bool IsMeasure
+        {
+            get;
+            set;
+        } = true;
         public C_BORDER_STYLE BorderStyle { get; set; }
-        public CPDFMeasureInfo measureInfo { get; set; }
+        public CPDFMeasureInfo measureInfo
+        {
+            get;
+            set;
+        }
 
         public override bool CopyTo(AnnotParam transfer)
         {
@@ -56,7 +75,9 @@ namespace ComPDFKit.Tool
 
             if (SavePoints != null)
             {
-                polygonTransfer.SavePoints.CopyTo(SavePoints.ToArray());
+                CPoint[] pointArray = new CPoint[SavePoints.Count];
+                SavePoints.CopyTo(pointArray);
+                polygonTransfer.SavePoints = pointArray.ToList();
             }
 
             if (LineColor != null)
@@ -66,7 +87,7 @@ namespace ComPDFKit.Tool
 
             if (LineDash != null)
             {
-                polygonTransfer.LineDash = (float[])LineDash.Clone(); 
+                polygonTransfer.LineDash = (float[])LineDash.Clone();
             }
 
             if (EndLineColor != null)
@@ -84,24 +105,26 @@ namespace ComPDFKit.Tool
                 polygonTransfer.FontColor = (byte[])FontColor.Clone();
             }
 
-            if (measureInfo != null)
+            polygonTransfer.BorderEffector = BorderEffector;
+
+            if (measureInfo != null && IsMeasure)
             {
-                CPDFMeasureInfo cPDFMeasureInfo =new CPDFMeasureInfo() 
+                CPDFMeasureInfo cPDFMeasureInfo = new CPDFMeasureInfo()
                 {
-                    Factor=measureInfo.Factor,
-                    Unit=measureInfo.Unit,
-                    DecimalSymbol=measureInfo.DecimalSymbol,
-                    ThousandSymbol=measureInfo.ThousandSymbol,
-                    Display=measureInfo.Display,
-                    Precision=measureInfo.Precision,
-                    UnitPrefix=measureInfo.UnitPrefix,
-                    UnitSuffix=measureInfo.UnitSuffix,
-                    UnitPosition=measureInfo.UnitPosition,
-                    RulerBase=measureInfo.RulerBase,
-                    RulerBaseUnit=measureInfo.RulerBaseUnit,
-                    RulerTranslateUnit=measureInfo.RulerTranslateUnit,
-                    CaptionType=measureInfo.CaptionType,
-                    RulerTranslate=measureInfo.RulerTranslate,
+                    Factor = measureInfo.Factor,
+                    Unit = measureInfo.Unit,
+                    DecimalSymbol = measureInfo.DecimalSymbol,
+                    ThousandSymbol = measureInfo.ThousandSymbol,
+                    Display = measureInfo.Display,
+                    Precision = measureInfo.Precision,
+                    UnitPrefix = measureInfo.UnitPrefix,
+                    UnitSuffix = measureInfo.UnitSuffix,
+                    UnitPosition = measureInfo.UnitPosition,
+                    RulerBase = measureInfo.RulerBase,
+                    RulerBaseUnit = measureInfo.RulerBaseUnit,
+                    RulerTranslateUnit = measureInfo.RulerTranslateUnit,
+                    CaptionType = measureInfo.CaptionType,
+                    RulerTranslate = measureInfo.RulerTranslate,
                 };
                 polygonTransfer.measureInfo = cPDFMeasureInfo;
             }

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

@@ -12,7 +12,7 @@ namespace ComPDFKit.Tool
         {
             CurrentType = C_ANNOTATION_TYPE.C_ANNOTATION_SQUIGGLY;
         }
-        public byte[] SquigglyColor { get; set; }
+        public byte[] SquigglyColor { get; set; } = new byte[3] { 255, 0, 0 };
 
         public List<CRect> QuardRects { get; set; }
 

+ 7 - 9
Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/StampParam.cs

@@ -1,4 +1,5 @@
-using ComPDFKit.PDFAnnotation;
+using ComPDFKit.Import;
+using ComPDFKit.PDFAnnotation;
 using System.IO;
 
 namespace ComPDFKit.Tool
@@ -10,18 +11,15 @@ namespace ComPDFKit.Tool
             CurrentType = C_ANNOTATION_TYPE.C_ANNOTATION_STAMP;
         }
 
-
 		public string StampText { get; set; } = string.Empty;
 		public string DateText {  get; set; }= string.Empty;
 		public C_STAMP_TYPE StampType { get; set; }
 		public C_TEXTSTAMP_SHAPE TextStampShape {  get; set; }
 		public C_TEXTSTAMP_COLOR TextStampColor {  get; set; }
 		public MemoryStream ImageStream { get; set; }
+		public int PageRotation { get; set; }	
 		public int Rotation { get; set; }	
-		//暂时做旋转用
-		//后续底层更新旋转角度支持后废除
-		//-1 逆时针 0 未动  1顺时针
-		public int Clockwise {  get; set; }
+		public CRect SourceRect { get; set; }
 
         public override bool CopyTo(AnnotParam transfer)
 		{
@@ -42,9 +40,9 @@ namespace ComPDFKit.Tool
 			stampTransfer.TextStampColor = TextStampColor;
 			stampTransfer.TextStampShape = TextStampShape;
 			stampTransfer.ImageStream = ImageStream;
-			stampTransfer.Rotation = Rotation;
-			stampTransfer.Clockwise = Clockwise;
-
+			stampTransfer.PageRotation = PageRotation;
+            stampTransfer.Rotation = Rotation;
+			stampTransfer.SourceRect = SourceRect;
 			return true;
 		}
 	}

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

@@ -12,7 +12,7 @@ namespace ComPDFKit.Tool
         {
             CurrentType = C_ANNOTATION_TYPE.C_ANNOTATION_STRIKEOUT;
         }
-		public byte[] StrikeoutColor { get; set; }
+		public byte[] StrikeoutColor { get; set; } = new byte[3] { 255, 0, 0 };
 
 		public List<CRect> QuardRects { get; set; }
 

+ 30 - 30
Demo/Examples/ComPDFKit.Tool/SettingParam/AnnotParam/UnderlineParam.cs

@@ -6,46 +6,46 @@ using System.Windows.Media;
 
 namespace ComPDFKit.Tool
 {
-	public class UnderlineParam:AnnotParam
-	{
-		public UnderlineParam ()
+    public class UnderlineParam : AnnotParam
+    {
+        public UnderlineParam()
         {
             CurrentType = C_ANNOTATION_TYPE.C_ANNOTATION_UNDERLINE;
         }
-		public byte[] UnderlineColor { get; set; }
+        public byte[] UnderlineColor { get; set; } = new byte[3] { 255, 0, 0 };
 
-		public List<CRect> QuardRects { get; set; }
+        public List<CRect> QuardRects { get; set; }
 
-		public override bool CopyTo(AnnotParam transfer)
-		{
-			UnderlineParam underlineTransfer = transfer as UnderlineParam;
-			if (underlineTransfer == null)
-			{
-				return false;
-			}
+        public override bool CopyTo(AnnotParam transfer)
+        {
+            UnderlineParam underlineTransfer = transfer as UnderlineParam;
+            if (underlineTransfer == null)
+            {
+                return false;
+            }
 
-			if (!base.CopyTo(underlineTransfer))
-			{
-				return false;
-			}
+            if (!base.CopyTo(underlineTransfer))
+            {
+                return false;
+            }
 
-			if(UnderlineColor != null)
-			{
+            if (UnderlineColor != null)
+            {
                 underlineTransfer.UnderlineColor = (byte[])UnderlineColor.Clone();
             }
 
-			if (QuardRects != null)
-			{
-				List<CRect> rectList = new List<CRect>();
-				foreach (CRect saveRect in QuardRects)
-				{
-					rectList.Add(saveRect);
-				}
+            if (QuardRects != null)
+            {
+                List<CRect> rectList = new List<CRect>();
+                foreach (CRect saveRect in QuardRects)
+                {
+                    rectList.Add(saveRect);
+                }
 
-				underlineTransfer.QuardRects = rectList;
-			}
+                underlineTransfer.QuardRects = rectList;
+            }
 
-			return true;
-		}
-	}
+            return true;
+        }
+    }
 }

+ 7 - 7
Demo/Examples/ComPDFKit.Tool/SettingParam/DefaultSettingParam.cs

@@ -21,7 +21,7 @@ namespace ComPDFKit.Tool.SettingParam
 
         #region Measure
 
-        public bool IsOpenMeasure = false;
+        public bool IsOpenMeasure { get; set; } = false;
 
         public bool IsCreateSquarePolygonMeasure = false;
 
@@ -722,8 +722,7 @@ namespace ComPDFKit.Tool.SettingParam
             InitFreeText();
             InitCircle();
             InitStickyNote();
-            InitSound();
-
+            InitSound(); 
             #endregion
 
             #region Widget
@@ -746,6 +745,8 @@ namespace ComPDFKit.Tool.SettingParam
             #endregion
         }
 
+
+
         public bool SetAnnotParam(AnnotParam annotParam)
         {
             bool IsOK = false;
@@ -811,14 +812,14 @@ namespace ComPDFKit.Tool.SettingParam
                     {
                         PolygonMeasureParamDef = annotParam as PolygonMeasureParam;
                         IsOK = true;
-                    }
+                    } 
                     break;
                 case C_ANNOTATION_TYPE.C_ANNOTATION_POLYLINE:
                     if (annotParam is PolyLineMeasureParam)
                     {
                         PolyLineMeasureParamDef = annotParam as PolyLineMeasureParam;
                         IsOK = true;
-                    }
+                    } 
                     break;
                 case C_ANNOTATION_TYPE.C_ANNOTATION_HIGHLIGHT:
                     if (annotParam is HighlightParam)
@@ -874,8 +875,7 @@ namespace ComPDFKit.Tool.SettingParam
                         SoundParamDef = annotParam as SoundParam;
                         IsOK = true;
                     }
-                    break;
-                    break;
+                    break; 
                 case C_ANNOTATION_TYPE.C_ANNOTATION_MOVIE:
                     break;
                 case C_ANNOTATION_TYPE.C_ANNOTATION_WIDGET:

+ 1 - 10
Demo/Examples/ComPDFKit.Tool/SettingParam/PDFEditParam/ImageEditParam.cs

@@ -15,20 +15,11 @@ namespace ComPDFKit.Tool
         public override bool CopyTo(PDFEditParam transfer)
         {
             ImageEditParam imageTransfer = transfer as ImageEditParam;
-            if (imageTransfer == null)
-            {
+            if (imageTransfer == null || !base.CopyTo(imageTransfer))
                 return false;
-            }
 
-            if (!base.CopyTo(imageTransfer))
-            {
-                return false;
-            }
-
-           
             imageTransfer.ClipRect = ClipRect;
             imageTransfer.Rotate = Rotate;
-
             return true;
         }
     }

+ 1 - 3
Demo/Examples/ComPDFKit.Tool/SettingParam/PDFEditParam/PDFEditParam.cs

@@ -13,15 +13,13 @@ namespace ComPDFKit.Tool
         public virtual bool CopyTo(PDFEditParam transfer)
         {
             if (transfer == null)
-            {
                 return false;
-            }
+
             transfer.PageIndex = PageIndex;
             transfer.EditIndex = EditIndex;
             transfer.EditType = EditType;
             transfer.Transparency = Transparency;
             transfer.ClientRect = ClientRect;
-
             return true;
         }
     }

+ 31 - 0
Demo/Examples/ComPDFKit.Tool/SettingParam/PDFEditParam/PathEditParam.cs

@@ -0,0 +1,31 @@
+using ComPDFKit.Import;
+using ComPDFKit.PDFPage;
+
+namespace ComPDFKit.Tool
+{
+    public class PathEditParam:PDFEditParam
+    {
+        public PathEditParam() 
+        {
+            EditType = CPDFEditType.EditPath;
+        }
+
+        public byte[] StrokeColor { get; set; }
+        public byte[] FillColor { get; set; }
+        public CRect ClipRect { get; set; }
+        public int Rotate { get; set; }
+
+        public override bool CopyTo(PDFEditParam transfer)
+        {
+            PathEditParam pathTransfer = transfer as PathEditParam;
+            if (pathTransfer == null || !base.CopyTo(pathTransfer))
+                return false;
+
+            pathTransfer.StrokeColor = StrokeColor;
+            pathTransfer.FillColor = FillColor;
+            pathTransfer.ClipRect = ClipRect;
+            pathTransfer.Rotate = Rotate;
+            return true;
+        }
+    }
+}

+ 2 - 11
Demo/Examples/ComPDFKit.Tool/SettingParam/PDFEditParam/TextEditParam.cs

@@ -19,26 +19,17 @@ namespace ComPDFKit.Tool
         public override bool CopyTo(PDFEditParam transfer)
         {
             TextEditParam texteditTransfer = transfer as TextEditParam;
-            if (texteditTransfer == null)
-            {
+            if (texteditTransfer == null || !base.CopyTo(texteditTransfer))
                 return false;
-            }
-
-            if (!base.CopyTo(texteditTransfer))
-            {
-                return false;
-            }
 
             texteditTransfer.FontSize = FontSize;
             if (FontColor != null)
-            {
                 texteditTransfer.FontColor = (byte[])FontColor.Clone();
-            }
+
             texteditTransfer.TextAlign = TextAlign;
             texteditTransfer.FontName = FontName;
             texteditTransfer.IsItalic = IsItalic;
             texteditTransfer.IsBold = IsBold;
-
             return true;
         }
     }

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

@@ -39,7 +39,6 @@ namespace ComPDFKit.Tool.UndoManger
             }
         }
 
-
         internal override bool Add()
         {
             HighlightParam currentParam = CurrentParam as HighlightParam;

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

@@ -11,7 +11,7 @@ using static ComPDFKit.PDFAnnotation.CTextAttribute;
 
 namespace ComPDFKit.Tool.UndoManger
 {
-    internal class PolyLineMeasureAnnotHistory : AnnotHistory
+    public class PolyLineMeasureAnnotHistory : AnnotHistory
     {
         public override int GetAnnotIndex()
         {

+ 242 - 0
Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/PolygonAnnotHistory.cs

@@ -0,0 +1,242 @@
+using ComPDFKit.PDFAnnotation;
+using ComPDFKit.PDFPage;
+using ComPDFKit.Tool.Help;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace ComPDFKit.Tool.UndoManger
+{
+    public class PolygonAnnotHistory : AnnotHistory
+    {
+        public override int GetAnnotIndex()
+        {
+            if (CurrentParam != null)
+            {
+                return CurrentParam.AnnotIndex;
+            }
+            return base.GetAnnotIndex();
+        }
+
+        public override int GetPageIndex()
+        {
+            if (CurrentParam != null)
+            {
+                return CurrentParam.PageIndex;
+            }
+            return base.GetPageIndex();
+        }
+
+        public override void SetAnnotIndex(int newIndex)
+        {
+            if (CurrentParam != null)
+            {
+                CurrentParam.AnnotIndex = newIndex;
+            }
+
+            if (PreviousParam != null)
+            {
+                PreviousParam.AnnotIndex = newIndex;
+            }
+        }
+
+        internal override bool Add()
+        {
+            PolygonMeasureParam currentParam = CurrentParam as PolygonMeasureParam;
+            if (CurrentParam == null || PDFDoc == null || !PDFDoc.IsValid())
+            {
+                return false;
+            }
+
+            CPDFPage pdfPage = PDFDoc.PageAtIndex(currentParam.PageIndex);
+            CPDFPolygonAnnotation polygonAnnot = pdfPage?.CreateAnnot(C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON) as CPDFPolygonAnnotation;
+
+            if (polygonAnnot != null)
+            {
+                int annotIndex = pdfPage.GetAnnotCount() - 1;
+
+                if (currentParam.HasFillColor)
+                {
+                    if (currentParam.FillColor != null && currentParam.FillColor.Length == 3)
+                    {
+                        polygonAnnot.SetBgColor(currentParam.FillColor);
+                    }
+                }
+                if (currentParam.LineColor != null && currentParam.LineColor.Length == 3)
+                {
+                    polygonAnnot.SetLineColor(currentParam.LineColor);
+                }
+
+                polygonAnnot.SetTransparency((byte)currentParam.Transparency);
+                polygonAnnot.SetLineWidth(currentParam.LineWidth);
+
+                polygonAnnot.SetPoints(currentParam.SavePoints);
+                polygonAnnot.SetRect(currentParam.ClientRect);
+
+                if (currentParam.LineDash != null)
+                {
+                    if (currentParam.LineDash.Length == 0)
+                    {
+                        polygonAnnot.SetBorderStyle(C_BORDER_STYLE.BS_SOLID, new float[0]);
+                    }
+                    else
+                    {
+                        List<float> floatArray = new List<float>();
+                        foreach (float num in currentParam.LineDash)
+                        {
+                            floatArray.Add(num);
+                        }
+                        polygonAnnot.SetBorderStyle(C_BORDER_STYLE.BS_DASHDED, floatArray.ToArray());
+                    }
+                }
+
+                if (!string.IsNullOrEmpty(currentParam.Author))
+                {
+                    polygonAnnot.SetAuthor(currentParam.Author);
+                }
+
+                if (!string.IsNullOrEmpty(currentParam.Content))
+                {
+                    polygonAnnot.SetContent(currentParam.Content);
+                }
+
+                polygonAnnot.SetIsLocked(currentParam.Locked);
+                polygonAnnot.SetCreationDate(PDFHelp.GetCurrentPdfTime());
+                polygonAnnot.UpdateAp();
+                polygonAnnot.ReleaseAnnot();
+
+                if (currentParam != null)
+                {
+                    currentParam.AnnotIndex = annotIndex;
+                }
+
+                if (PreviousParam != null)
+                {
+                    PreviousParam.AnnotIndex = annotIndex;
+                }
+                return true;
+            }
+            return true;
+        }
+
+        internal override bool Update(bool isUndo)
+        {
+            if (CurrentParam as PolygonMeasureParam == null || PreviousParam as PolygonMeasureParam == null)
+            {
+                return false;
+            }
+
+            if (MakeAnnotValid(CurrentParam))
+            {
+                CPDFPolygonAnnotation polygonAnnot = Annot as CPDFPolygonAnnotation;
+                if (polygonAnnot == null || !polygonAnnot.IsValid() || !polygonAnnot.IsMeasured())
+                {
+                    return false;
+                }
+
+
+                PolygonMeasureParam updateParam = (isUndo ? PreviousParam : CurrentParam) as PolygonMeasureParam;
+                PolygonMeasureParam checkParam = (isUndo ? CurrentParam : PreviousParam) as PolygonMeasureParam;
+
+                if (!CheckArrayEqual(updateParam.LineColor, checkParam.LineColor))
+                {
+                    if (updateParam.LineColor != null && updateParam.LineColor.Length == 3)
+                    {
+                        polygonAnnot.SetLineColor(updateParam.LineColor);
+                    }
+                }
+
+                if (!CheckArrayEqual(updateParam.FillColor, checkParam.FillColor))
+                {
+                    if (updateParam.HasFillColor)
+                    {
+                        if (updateParam.FillColor != null && updateParam.FillColor.Length == 3)
+                        {
+                            polygonAnnot.SetBgColor(updateParam.FillColor);
+                        }
+                    }
+                    else
+                    {
+                        polygonAnnot.ClearBgColor();
+                    }
+
+                    if (updateParam.Transparency != checkParam.Transparency)
+                    {
+                        polygonAnnot.SetTransparency((byte)updateParam.Transparency);
+                    }
+
+                    if (updateParam.LineWidth != checkParam.LineWidth)
+                    {
+                        polygonAnnot.SetLineWidth((byte)updateParam.LineWidth);
+                    }
+
+                    if (!CheckArrayEqual(updateParam.LineDash, checkParam.LineDash))
+                    {
+                        if (updateParam.LineDash != null)
+                        {
+                            if (updateParam.LineDash.Length == 0)
+                            {
+                                polygonAnnot.SetBorderStyle(C_BORDER_STYLE.BS_SOLID, new float[0]);
+                            }
+                            else
+                            {
+                                List<float> floatArray = new List<float>();
+                                foreach (float num in updateParam.LineDash)
+                                {
+                                    floatArray.Add(num);
+                                }
+                                polygonAnnot.SetBorderStyle(C_BORDER_STYLE.BS_DASHDED, floatArray.ToArray());
+                            }
+                        }
+                    }
+
+
+                    if (!updateParam.SavePoints.SequenceEqual(checkParam.SavePoints))
+                    {
+                        polygonAnnot.SetPoints(updateParam.SavePoints);
+                    }
+
+                    if (!updateParam.ClientRect.Equals(checkParam.ClientRect))
+                    {
+                        polygonAnnot.SetRect(updateParam.ClientRect);
+                    }
+
+
+                    if (updateParam.Author != checkParam.Author)
+                    {
+                        polygonAnnot.SetAuthor(updateParam.Author);
+                    }
+
+                    if (updateParam.Content != checkParam.Content)
+                    {
+                        polygonAnnot.SetContent(updateParam.Content);
+                    }
+
+
+                    if (updateParam.Locked != checkParam.Locked)
+                    {
+                        polygonAnnot.SetIsLocked(updateParam.Locked);
+                    }
+                }
+                polygonAnnot.SetModifyDate(PDFHelp.GetCurrentPdfTime());
+
+                polygonAnnot.UpdateAp();
+
+                return true;
+            }
+            return false;
+        }
+
+        internal override bool Remove()
+        {
+            if (MakeAnnotValid(CurrentParam))
+            {
+                Annot.RemoveAnnot();
+                return true;
+            }
+            return false;
+        }
+    }
+}

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

@@ -2,17 +2,13 @@
 using ComPDFKit.PDFAnnotation;
 using ComPDFKit.PDFPage;
 using ComPDFKit.Tool.Help;
-using ComPDFKitViewer.Annot;
-using System;
 using System.Collections.Generic;
 using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 using static ComPDFKit.PDFAnnotation.CTextAttribute;
 
 namespace ComPDFKit.Tool.UndoManger
 {
-    internal class PolygonMeasureAnnotHistory : AnnotHistory
+    public class PolygonMeasureAnnotHistory : AnnotHistory
     {
         public override int GetAnnotIndex()
         {
@@ -31,6 +27,7 @@ namespace ComPDFKit.Tool.UndoManger
             }
             return base.GetPageIndex();
         }
+
         public override void SetAnnotIndex(int newIndex)
         {
             if (CurrentParam != null)
@@ -43,6 +40,7 @@ namespace ComPDFKit.Tool.UndoManger
                 PreviousParam.AnnotIndex = newIndex;
             }
         }
+
         internal override bool Add()
         {
             PolygonMeasureParam currentParam = CurrentParam as PolygonMeasureParam;
@@ -56,7 +54,6 @@ namespace ComPDFKit.Tool.UndoManger
             if (polygonAnnot != null)
             {
                 int annotIndex = pdfPage.GetAnnotCount() - 1;
-
                 if (currentParam.HasFillColor)
                 {
                     if (currentParam.FillColor != null && currentParam.FillColor.Length == 3)
@@ -70,12 +67,11 @@ namespace ComPDFKit.Tool.UndoManger
                     polygonAnnot.SetLineColor(currentParam.LineColor);
                 }
 
-                polygonAnnot.SetTransparency((byte)currentParam.Transparency);
+                polygonAnnot.SetTransparency(currentParam.Transparency);
                 polygonAnnot.SetLineWidth(currentParam.LineWidth);
-
                 polygonAnnot.SetPoints(currentParam.SavePoints);
+                polygonAnnot.SetAnnotBorderEffector(currentParam.BorderEffector);
                 polygonAnnot.SetRect(currentParam.ClientRect);
-
                 if (currentParam.LineDash != null)
                 {
                     if (currentParam.LineDash.Length == 0)
@@ -89,28 +85,33 @@ namespace ComPDFKit.Tool.UndoManger
                         {
                             floatArray.Add(num);
                         }
+
                         polygonAnnot.SetBorderStyle(C_BORDER_STYLE.BS_DASHDED, floatArray.ToArray());
                     }
                 }
 
-                CTextAttribute textAttribute = new CTextAttribute();
-                textAttribute.FontColor = currentParam.FontColor;
-                textAttribute.FontSize = (float)currentParam.FontSize;
-                textAttribute.FontName = CFontNameHelper.ObtainFontName(CFontNameHelper.GetFontType(currentParam.FontName),
-                            currentParam.IsBold,
-                            currentParam.IsItalic);
-                polygonAnnot.SetTextAttribute(textAttribute);
-                if (currentParam.measureInfo != null)
+                if(polygonAnnot.IsMeasured())
                 {
-                    CPDFAreaMeasure polygonMeasure = polygonAnnot.GetAreaMeasure();
-                    if (polygonMeasure != null)
+                    CTextAttribute textAttribute = new CTextAttribute();
+                    textAttribute.FontColor = currentParam.FontColor;
+                    textAttribute.FontSize = (float)currentParam.FontSize;
+                    textAttribute.FontName = CFontNameHelper.ObtainFontName(CFontNameHelper.GetFontType(currentParam.FontName),
+                                currentParam.IsBold,
+                                currentParam.IsItalic);
+                    polygonAnnot.SetTextAttribute(textAttribute);
+                    if (currentParam.measureInfo != null)
                     {
-                        polygonMeasure.SetMeasureInfo(currentParam.measureInfo);
-                        polygonMeasure.SetMeasureScale(currentParam.measureInfo.RulerBase, currentParam.measureInfo.RulerBaseUnit,
-                                                       currentParam.measureInfo.RulerTranslate, currentParam.measureInfo.RulerTranslateUnit);
-                        polygonMeasure.UpdateAnnotMeasure();
+                        CPDFAreaMeasure polygonMeasure = polygonAnnot.GetAreaMeasure();
+                        if (polygonMeasure != null)
+                        {
+                            polygonMeasure.SetMeasureInfo(currentParam.measureInfo);
+                            polygonMeasure.SetMeasureScale(currentParam.measureInfo.RulerBase, currentParam.measureInfo.RulerBaseUnit,
+                                                           currentParam.measureInfo.RulerTranslate, currentParam.measureInfo.RulerTranslateUnit);
+                            polygonMeasure.UpdateAnnotMeasure();
+                        }
                     }
                 }
+ 
                 if (!string.IsNullOrEmpty(currentParam.Author))
                 {
                     polygonAnnot.SetAuthor(currentParam.Author);
@@ -120,6 +121,7 @@ namespace ComPDFKit.Tool.UndoManger
                 {
                     polygonAnnot.SetContent(currentParam.Content);
                 }
+
                 polygonAnnot.SetIsLocked(currentParam.Locked);
                 polygonAnnot.SetCreationDate(PDFHelp.GetCurrentPdfTime());
                 polygonAnnot.UpdateAp();
@@ -129,6 +131,7 @@ namespace ComPDFKit.Tool.UndoManger
                 {
                     currentParam.AnnotIndex = annotIndex;
                 }
+
                 if (PreviousParam != null)
                 {
                     PreviousParam.AnnotIndex = annotIndex;
@@ -137,6 +140,7 @@ namespace ComPDFKit.Tool.UndoManger
             }
             return false;
         }
+
         internal override bool Update(bool isUndo)
         {
             if (CurrentParam as PolygonMeasureParam == null || PreviousParam as PolygonMeasureParam == null)
@@ -146,7 +150,7 @@ namespace ComPDFKit.Tool.UndoManger
             if (MakeAnnotValid(CurrentParam))
             {
                 CPDFPolygonAnnotation polygonAnnot = Annot as CPDFPolygonAnnotation;
-                if (polygonAnnot == null || !polygonAnnot.IsValid() || !polygonAnnot.IsMeasured())
+                if (polygonAnnot == null || !polygonAnnot.IsValid())
                 {
                     return false;
                 }
@@ -208,12 +212,16 @@ namespace ComPDFKit.Tool.UndoManger
                     polygonAnnot.SetPoints(updateParam.SavePoints);
                 }
 
+                if(!updateParam.BorderEffector.Equals(checkParam.BorderEffector))
+                {
+                    polygonAnnot.SetAnnotBorderEffector(updateParam.BorderEffector);
+                }
+
                 if (!updateParam.ClientRect.Equals(checkParam.ClientRect))
                 {
                     polygonAnnot.SetRect(updateParam.ClientRect);
                 }
 
-
                 if (updateParam.Author != checkParam.Author)
                 {
                     polygonAnnot.SetAuthor(updateParam.Author);
@@ -228,19 +236,23 @@ namespace ComPDFKit.Tool.UndoManger
                 {
                     polygonAnnot.SetIsLocked(updateParam.Locked);
                 }
-                if (updateParam.measureInfo != checkParam.measureInfo)
+
+                if (polygonAnnot.IsMeasured())
                 {
-                    CPDFAreaMeasure polygonMeasure = polygonAnnot.GetAreaMeasure();
-                    if (polygonMeasure != null)
+                    if (updateParam.measureInfo != checkParam.measureInfo)
                     {
-                        polygonMeasure.SetMeasureInfo(updateParam.measureInfo);
-                        polygonMeasure.SetMeasureScale(updateParam.measureInfo.RulerBase, updateParam.measureInfo.RulerBaseUnit,
-                                                       updateParam.measureInfo.RulerTranslate, updateParam.measureInfo.RulerTranslateUnit);
-                        polygonMeasure.UpdateAnnotMeasure();
+                        CPDFAreaMeasure polygonMeasure = polygonAnnot.GetAreaMeasure();
+                        if (polygonMeasure != null)
+                        {
+                            polygonMeasure.SetMeasureInfo(updateParam.measureInfo);
+                            polygonMeasure.SetMeasureScale(updateParam.measureInfo.RulerBase, updateParam.measureInfo.RulerBaseUnit,
+                                                           updateParam.measureInfo.RulerTranslate, updateParam.measureInfo.RulerTranslateUnit);
+                            polygonMeasure.UpdateAnnotMeasure();
+                        }
                     }
                 }
-                polygonAnnot.SetModifyDate(PDFHelp.GetCurrentPdfTime());
 
+                polygonAnnot.SetModifyDate(PDFHelp.GetCurrentPdfTime());
                 polygonAnnot.UpdateAp();
 
                 return true;

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

@@ -40,12 +40,11 @@ namespace ComPDFKit.Tool.UndoManger
         internal override bool Add()
 		{
             SquigglyParam currentParam = CurrentParam as SquigglyParam;
-
-
             if (currentParam == null || PDFDoc == null || !PDFDoc.IsValid())
 			{
 				return false;
 			}
+
 			CPDFPage pdfPage = PDFDoc.PageAtIndex(currentParam.PageIndex);
 			CPDFSquigglyAnnotation squigglyAnnot = pdfPage?.CreateAnnot(C_ANNOTATION_TYPE.C_ANNOTATION_SQUIGGLY) as CPDFSquigglyAnnotation;
 			if (squigglyAnnot != null)

+ 26 - 176
Demo/Examples/ComPDFKit.Tool/UndoManger/AnnotHistory/StampAnnotHistory.cs

@@ -4,7 +4,6 @@ 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;
@@ -47,7 +46,6 @@ namespace ComPDFKit.Tool.UndoManger
         internal override bool Add()
 		{
             StampParam currentParam = CurrentParam as StampParam;
-
             if (currentParam == null || PDFDoc == null || !PDFDoc.IsValid())
 			{
 				return false;
@@ -65,11 +63,10 @@ namespace ComPDFKit.Tool.UndoManger
 
 			CPDFPage pdfPage = PDFDoc.PageAtIndex(currentParam.PageIndex);
 			CPDFStampAnnotation stampAnnot = pdfPage?.CreateAnnot(C_ANNOTATION_TYPE.C_ANNOTATION_STAMP) as CPDFStampAnnotation;
-           
             if (stampAnnot != null)
 			{
 				int annotIndex = pdfPage.GetAnnotCount() - 1;
-				switch(currentParam.StampType)
+                switch (currentParam.StampType)
 				{
 					case C_STAMP_TYPE.STANDARD_STAMP:
 						{
@@ -78,10 +75,11 @@ namespace ComPDFKit.Tool.UndoManger
 							{
 								stampText = string.Empty;
 							}
+
 							stampAnnot.SetStandardStamp(stampText, pdfPage.Rotation);
-                            stampAnnot.SetRect(currentParam.ClientRect);
                         }
 						break;
+
 					case C_STAMP_TYPE.TEXT_STAMP:
 						{
 							string dateText = currentParam.DateText;
@@ -90,19 +88,21 @@ namespace ComPDFKit.Tool.UndoManger
 							{
 								dateText = string.Empty;
 							}
+
 							if (stampText == null)
 							{
 								stampText = string.Empty;
 							}
+
 							stampAnnot.SetTextStamp(
 								stampText,
 								dateText,
 								currentParam.TextStampShape,
 								currentParam.TextStampColor,
 								pdfPage.Rotation);
-                            stampAnnot.SetRect(currentParam.ClientRect);
                         }
 						break;
+
 					case C_STAMP_TYPE.IMAGE_STAMP:
 						{
                             byte[] imageData = null;
@@ -111,7 +111,8 @@ namespace ComPDFKit.Tool.UndoManger
                             PDFHelp.ImageStreamToByte(currentParam.ImageStream, ref imageData, ref imageWidth, ref imageHeight);
 							if (imageData != null && imageWidth > 0 && imageHeight > 0)
 							{
-                                stampAnnot.SetRect(currentParam.ClientRect);
+                                stampAnnot.SetSourceRect(currentParam.SourceRect);
+                                stampAnnot.AnnotationRotator.SetRotation(currentParam.Rotation);
                                 stampAnnot.SetImageStamp(
                                     imageData,
                                     imageWidth,
@@ -124,14 +125,14 @@ 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);
+                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);
+                }
 
                 if (!string.IsNullOrEmpty(currentParam.Author))
 				{
@@ -179,46 +180,29 @@ namespace ComPDFKit.Tool.UndoManger
 
 				StampParam updateParam = (isUndo ? PreviousParam : CurrentParam) as StampParam;
 				StampParam checkParam = (isUndo ? CurrentParam : PreviousParam) as StampParam;
-
-                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(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))
+				if (!updateParam.SourceRect.Equals(checkParam.SourceRect))
+                {
+                    stampAnnot.SetSourceRect(updateParam.SourceRect);
+                    stampAnnot.AnnotationRotator.SetRotation(updateParam.Rotation);
+                }
+
+                if (updateParam.Rotation != checkParam.Rotation)
                 {
-                    stampAnnot.SetRect(updateParam.ClientRect);
+                    stampAnnot.AnnotationRotator.SetRotation(updateParam.Rotation);
                 }
 
-				if (updateParam.Author != checkParam.Author)
+                if (updateParam.Author != checkParam.Author)
 				{
 					stampAnnot.SetAuthor(updateParam.Author);
 				}
@@ -251,140 +235,6 @@ 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;

+ 21 - 4
Demo/Examples/Compdfkit.Controls/Annotation/AnnotationControl/AnnotationControl.xaml.cs

@@ -20,6 +20,8 @@ using ComPDFKitViewer.Widget;
 using ComPDFKit.Tool.Help;
 using ComPDFKit.Tool.DrawTool;
 using System.Collections.Generic;
+using ComPDFKitViewer.BaseObject;
+using ComPDFKitViewer;
 
 namespace ComPDFKit.Controls.PDFControl
 {
@@ -96,7 +98,7 @@ namespace ComPDFKit.Controls.PDFControl
             {
                     CPDFAnnotationType.Highlight, CPDFAnnotationType.Underline, CPDFAnnotationType.Strikeout,
                     CPDFAnnotationType.Squiggly, CPDFAnnotationType.Freehand, CPDFAnnotationType.FreeText,
-                    CPDFAnnotationType.Note, CPDFAnnotationType.Circle, CPDFAnnotationType.Square,
+                    CPDFAnnotationType.Note, CPDFAnnotationType.Circle, CPDFAnnotationType.Square, CPDFAnnotationType.Polygon,
                     CPDFAnnotationType.Arrow, CPDFAnnotationType.Line, CPDFAnnotationType.Image,
                     CPDFAnnotationType.Stamp, CPDFAnnotationType.Signature, CPDFAnnotationType.Link,
                     CPDFAnnotationType.Audio
@@ -182,7 +184,15 @@ baseWidget.GetAnnotData().Annot);
                         CPDFSignatureUI signatureProperty = new CPDFSignatureUI();
                         signatureProperty.SetFormProperty(annotParam, PDFViewControl, baseWidget.GetAnnotData().Annot);
                         PropertyContainer.Child = signatureProperty;
-                    } 
+                    }
+                }
+            }
+            else
+            {
+                 BaseAnnot baseAnnot = PDFViewControl.GetCacheHitTestWidget();
+                if (baseAnnot != null)
+                {
+                    AnnotData annotData = baseAnnot.GetAnnotData();
                 }
             }
         }
@@ -232,8 +242,8 @@ baseWidget.GetAnnotData().Annot);
         }
 
         private void PDFViewTool_AnnotChanged(object sender, object e)
-        { 
-                OnAnnotEditHandler?.Invoke(this, EventArgs.Empty); 
+        {
+            OnAnnotEditHandler?.Invoke(this, EventArgs.Empty);
         }
 
         private void PDFToolManager_MouseLeftButtonUpHandler(object sender, MouseEventObject e)
@@ -519,6 +529,7 @@ baseWidget.GetAnnotData().Annot);
         private void UndoManager_PropertyChanged(object sender, PropertyChangedEventArgs e)
         {
             OnPropertyChanged(e.PropertyName);
+            OnCanSaveChanged?.Invoke(this, CanSave);
         }
 
         private void PanelState_PropertyChanged(object sender, PropertyChangedEventArgs e)
@@ -574,6 +585,9 @@ baseWidget.GetAnnotData().Annot);
             if (PDFViewControl != null && PDFViewControl.PDFViewTool.GetCPDFViewer() != null && CanUndo)
             {
                 PDFViewControl.PDFViewTool.GetCPDFViewer().UndoManager?.Undo();
+                PDFViewControl.PDFToolManager.ClearSelect();
+                PDFViewControl.PDFViewTool.GetCPDFViewer().UpdateAnnotFrame();
+                (BotaContainer.Child as CPDFBOTABarControl).LoadAnnotationList();
             }
         }
 
@@ -582,6 +596,9 @@ baseWidget.GetAnnotData().Annot);
             if (PDFViewControl != null && PDFViewControl.PDFViewTool.GetCPDFViewer() != null && CanRedo)
             {
                 PDFViewControl.PDFViewTool.GetCPDFViewer().UndoManager?.Redo();
+                PDFViewControl.PDFToolManager.ClearSelect();
+                PDFViewControl.PDFViewTool.GetCPDFViewer().UpdateAnnotFrame();
+                (BotaContainer.Child as CPDFBOTABarControl).LoadAnnotationList();
             }
         }
 

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 8 - 1
Demo/Examples/Compdfkit.Controls/Annotation/CPDFAnnotationPreviewerControl.xaml


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

@@ -152,6 +152,12 @@ namespace ComPDFKit.Controls.PDFControl
             SharpPath.StrokeThickness = freehandData.Thickness;
         }
 
+        public void DrawCloudPreview()
+        { 
+            CollapsedAll();
+            gdPolygon.Visibility = Visibility.Visible;
+        }
+
         public void DrawNotePreview(CPDFAnnotationData annotationData)
         {
             CollapsedAll();
@@ -176,10 +182,63 @@ namespace ComPDFKit.Controls.PDFControl
             string fontStyle = string.Empty;
 
             CPDFFont.GetFamilyStyleName(freeTextData.FontFamily, ref fontFamily, ref fontStyle);
-            FreeText.FontFamily = new FontFamily(fontFamily); 
+            FreeText.FontFamily = new FontFamily(fontFamily);
             FreeText.FontSize = freeTextData.FontSize / 1.2;
             FreeText.Foreground = new SolidColorBrush(freeTextData.BorderColor);
             FreeText.Opacity = freeTextData.Opacity;
         }
+
+        private Path DrawCloudLine(Point startPoint, Point endPoint, double radius, double angle, Brush strokeColor, double strokeThickness, bool isUpward)
+        {
+            double lineLength = Math.Sqrt(Math.Pow(endPoint.X - startPoint.X, 2) + Math.Pow(endPoint.Y - startPoint.Y, 2));
+            double arcLength = 2 * Math.PI * radius * (angle / 360);
+            int arcCount = (int)Math.Ceiling(lineLength / arcLength);
+            Vector direction = new Vector(endPoint.X - startPoint.X, endPoint.Y - startPoint.Y);
+
+            direction.Normalize();
+            direction *= arcLength; 
+            Point currentPoint = startPoint;
+            
+            // 创建一个完整的PathGeometry
+            PathGeometry pathGeometry = new PathGeometry(); 
+            PathFigure pathFigure = new PathFigure
+            {
+                StartPoint = currentPoint,
+                IsClosed = false
+            };
+            
+            for (int i = 0; i < arcCount; i++)
+            {
+                // Calculate the end point of the arc
+                Point nextPoint = new Point(currentPoint.X + direction.X, currentPoint.Y + direction.Y);
+
+                ArcSegment arcSegment = new ArcSegment
+                {
+                    Point = nextPoint,
+                    Size = new Size(radius, radius),
+                    SweepDirection = isUpward ? SweepDirection.Clockwise : SweepDirection.Counterclockwise, // 控制圆弧方向
+                    IsLargeArc = angle > 180
+                };
+
+                // Add the ArcSegment to the path
+                pathFigure.Segments.Add(arcSegment);
+
+                // Update currentPoint to be the end point of the arc
+                currentPoint = nextPoint;
+            }
+
+            // 将所有圆弧段添加到一个PathFigure中
+            pathGeometry.Figures.Add(pathFigure);
+
+            // 创建最终的Path对象
+            Path cloudPath = new Path
+            {
+                Stroke = strokeColor,
+                StrokeThickness = strokeThickness,
+                Data = pathGeometry
+            };
+
+            return cloudPath;
+        } 
     }
 }

+ 21 - 3
Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationData/CPDFAnnotationData.cs

@@ -82,7 +82,8 @@ namespace ComPDFKit.Controls.Data
             { "Signature", CPDFAnnotationType.Signature },
             { "Link", CPDFAnnotationType.Link },
             {"Audio", CPDFAnnotationType.Audio },
-            {"Image", CPDFAnnotationType.Image }
+            {"Image", CPDFAnnotationType.Image },
+            {"Polygon", CPDFAnnotationType.Polygon}
         };
 
         public static Dictionary<int, C_LINE_TYPE> GetLineTypeFromIndex = new Dictionary<int, C_LINE_TYPE>()
@@ -126,7 +127,8 @@ namespace ComPDFKit.Controls.Data
         }
 
         private int _dashSpacing = 1;
-        public int DashSpacing {
+        public int DashSpacing
+        {
             get => _dashSpacing;
             set
             {
@@ -168,6 +170,22 @@ namespace ComPDFKit.Controls.Data
         public DashStyle DashStyle = DashStyles.Solid;
     }
 
+    public class CPDFPolygonData : CPDFAnnotationData
+    {
+        public Color BorderColor = Color.FromRgb(255, 0, 0);
+        public Color FillColor = Color.FromRgb(255, 255, 255);
+        public CPDFBorderEffector BorderEffector
+        {
+            get;
+            set;
+        } = new CPDFBorderEffector(C_BORDER_TYPE.C_BORDER_TYPE_Cloud, C_BORDER_INTENSITY.C_INTENSITY_ONE);
+        public C_BORDER_STYLE BorderStyle = C_BORDER_STYLE.BS_SOLID; 
+        public double Opacity = 1;
+        public int Thickness = 1;
+        public bool IsMeasured = false;
+        public DashStyle DashStyle = DashStyles.Solid;
+    }
+
     public class CPDFLineShapeData : CPDFAnnotationData
     {
         public Color BorderColor = Color.FromRgb(255, 0, 0);
@@ -278,7 +296,7 @@ namespace ComPDFKit.Controls.Data
         {
             get
             {
-                if(Type == C_STAMP_TYPE.TEXT_STAMP)
+                if (Type == C_STAMP_TYPE.TEXT_STAMP)
                 {
                     return "Text Stamp";
                 }

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

@@ -96,8 +96,8 @@ namespace ComPDFKit.Controls.PDFControl
             if (pdfViewer != null)
             {
                 pdfViewer.PDFToolManager.ClearSelect();
-                ParamConverter.RemovePageAnnot(e, pdfViewer.PDFViewTool.GetCPDFViewer().GetDocument());
-                pdfViewer.PDFViewTool.GetCPDFViewer().UpdateAnnotFrame();
+                ParamConverter.RemovePageAnnot(e, pdfViewer.GetCPDFViewer());
+                pdfViewer.GetCPDFViewer().UpdateAnnotFrame();
                 LoadAnnotationList();
             }
         }

+ 175 - 91
Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationPanel/PDFAnnotationControl/CPDFAnnotationControl.xaml.cs

@@ -44,6 +44,7 @@ namespace ComPDFKit.Controls.PDFControl
         private CPDFShapeUI pdfCircleUI;
         private CPDFShapeUI pdfLineUI;
         private CPDFShapeUI pdfArrowUI;
+        private CPDFCloudUI pdfCloudUI;
         private CPDFFreehandUI pdfFreehandUI;
         private CPDFFreeTextUI pdfFreeTextUI;
         private CPDFNoteUI pdfNoteUI;
@@ -116,7 +117,7 @@ namespace ComPDFKit.Controls.PDFControl
 
         private void AnnotationControl_Unloaded(object sender, RoutedEventArgs e)
         {
-             UnLoadPDFViewHandler();
+            UnLoadPDFViewHandler();
         }
 
         private UIElement GetAnnotationPanel()
@@ -154,6 +155,11 @@ namespace ComPDFKit.Controls.PDFControl
                     (annotationPanel as CPDFShapeUI).PropertyChanged += CPDFAnnotationControl_PropertyChanged;
                     SetAnnotationProperty((annotationPanel as CPDFShapeUI).GetShapeData());
                     break;
+                case CPDFAnnotationType.Polygon:
+                    (annotationPanel as CPDFCloudUI).PropertyChanged -= CPDFAnnotationControl_PropertyChanged;
+                    (annotationPanel as CPDFCloudUI).PropertyChanged += CPDFAnnotationControl_PropertyChanged;
+                    SetAnnotationProperty((annotationPanel as CPDFCloudUI).GetPolygonData());
+                    break;
                 case CPDFAnnotationType.Note:
                     (annotationPanel as CPDFNoteUI).PropertyChanged -= CPDFAnnotationControl_PropertyChanged;
                     (annotationPanel as CPDFNoteUI).PropertyChanged += CPDFAnnotationControl_PropertyChanged;
@@ -261,8 +267,10 @@ namespace ComPDFKit.Controls.PDFControl
                 case CPDFAnnotationType.Square:
                     {
                         CPDFShapeData squareData = pdfAnnotationData as CPDFShapeData;
-                        annotHandlerEventArgs = new SquareParam();
-                        annotHandlerEventArgs.CurrentType = C_ANNOTATION_TYPE.C_ANNOTATION_SQUARE;
+                        annotHandlerEventArgs = new SquareParam()
+                        {
+                            CurrentType = C_ANNOTATION_TYPE.C_ANNOTATION_SQUARE
+                        };
                         byte[] LineColor = new byte[] { squareData.BorderColor.R, squareData.BorderColor.G, squareData.BorderColor.B };
                         (annotHandlerEventArgs as SquareParam).LineColor = LineColor;
                         if (squareData.FillColor != Colors.Transparent)
@@ -285,45 +293,84 @@ namespace ComPDFKit.Controls.PDFControl
 
                 case CPDFAnnotationType.Circle:
                     {
-                        CPDFShapeData cicleData = pdfAnnotationData as CPDFShapeData;
-                        annotHandlerEventArgs = new CircleParam();
-                        annotHandlerEventArgs.CurrentType = C_ANNOTATION_TYPE.C_ANNOTATION_CIRCLE;
-                        byte[] LineColor = new byte[] { cicleData.BorderColor.R, cicleData.BorderColor.G, cicleData.BorderColor.B };
-                        (annotHandlerEventArgs as CircleParam).LineColor = LineColor;
-                        if (cicleData.FillColor != Colors.Transparent)
+                        CPDFShapeData circleData = pdfAnnotationData as CPDFShapeData;
+                        byte[] LineColor = new byte[] { circleData.BorderColor.R, circleData.BorderColor.G, circleData.BorderColor.B };
+
+                        annotHandlerEventArgs = new CircleParam
                         {
-                            byte[] BgColor = new byte[] { cicleData.FillColor.R, cicleData.FillColor.G, cicleData.FillColor.B };
-                            (annotHandlerEventArgs as CircleParam).BgColor = BgColor;
-                            (annotHandlerEventArgs as CircleParam).HasBgColor = true;
+                            CurrentType = C_ANNOTATION_TYPE.C_ANNOTATION_CIRCLE
+                        };
+
+                        if (annotHandlerEventArgs is CircleParam circleParam)
+                        {
+                            circleParam.LineColor = LineColor;
+                            if (circleData.FillColor != Colors.Transparent)
+                            {
+                                byte[] BgColor = new byte[] { circleData.FillColor.R, circleData.FillColor.G, circleData.FillColor.B };
+                                circleParam.BgColor = BgColor;
+                                circleParam.HasBgColor = true;
+                            }
+                            circleParam.LineWidth = circleData.Thickness;
+                            circleParam.Transparency = Convert.ToByte(circleData.Opacity * 255);
+                            ParamConverter.ParseDashStyle(circleData.DashStyle, out float[] LineDash, out C_BORDER_STYLE BorderStyle);
+                            circleParam.LineDash = LineDash;
+                            circleParam.BorderStyle = BorderStyle;
+                            circleParam.Author = CPDFMarkupData.Author;
+                            circleParam.Content = circleData.Note; 
                         }
-                        (annotHandlerEventArgs as CircleParam).LineWidth = cicleData.Thickness;
-                        (annotHandlerEventArgs as CircleParam).Transparency = Convert.ToByte(cicleData.Opacity * 255);
-                        ParamConverter.ParseDashStyle(cicleData.DashStyle, out float[] LineDash, out C_BORDER_STYLE BorderStyle);
-                        (annotHandlerEventArgs as CircleParam).LineDash = LineDash;
-                        (annotHandlerEventArgs as CircleParam).BorderStyle = BorderStyle;
-                        (annotHandlerEventArgs as CircleParam).Author = CPDFMarkupData.Author;
-                        (annotHandlerEventArgs as CircleParam).Content = cicleData.Note;
                         pdfViewerControl.SetCreateAnnotType(C_ANNOTATION_TYPE.C_ANNOTATION_CIRCLE);
                     }
                     break;
-
+                case CPDFAnnotationType.Polygon:
+                    {
+                        CPDFPolygonData polygonData = pdfAnnotationData as CPDFPolygonData;
+                        pdfViewerControl.PDFViewTool.GetDefaultSettingParam().IsCreateSquarePolygonMeasure = false;
+                        annotHandlerEventArgs = new PolygonMeasureParam()
+                        {
+                            CurrentType = C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON
+                        };
+                        if (annotHandlerEventArgs is PolygonMeasureParam polygonMeasureParam)
+                        { 
+                            polygonMeasureParam.LineColor = new byte[] { polygonData.BorderColor.R, polygonData.BorderColor.G, polygonData.BorderColor.B };
+                            polygonMeasureParam.HasFillColor = true;
+                            if(polygonData.FillColor.A == 0)
+                            {
+                                polygonMeasureParam.HasFillColor = false;
+                            }
+                            polygonMeasureParam.FillColor = new byte[] { polygonData.FillColor.R, polygonData.FillColor.G, polygonData.FillColor.B };
+                            polygonMeasureParam.BorderStyle = polygonData.BorderStyle;
+                            ParamConverter.ParseDashStyle(polygonData.DashStyle, out float[] LineDash, out C_BORDER_STYLE BorderStyle);
+                            polygonMeasureParam.LineDash = LineDash;
+                            polygonMeasureParam.BorderEffector = polygonData.BorderEffector;
+                            polygonMeasureParam.LineWidth = polygonData.Thickness; 
+                            polygonMeasureParam.Transparency = (byte)(polygonData.Opacity / 100 * 255.0);
+                            polygonMeasureParam.IsMeasure = false;
+                        }
+                        pdfViewerControl.SetCreateAnnotType(C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON);
+                    }
+                    break;
                 case CPDFAnnotationType.Arrow:
                 case CPDFAnnotationType.Line:
                     {
                         CPDFLineShapeData lineData = pdfAnnotationData as CPDFLineShapeData;
-                        annotHandlerEventArgs = new LineParam();
-                        annotHandlerEventArgs.CurrentType = C_ANNOTATION_TYPE.C_ANNOTATION_LINE;
-                        byte[] LineColor = new byte[] { lineData.BorderColor.R, lineData.BorderColor.G, lineData.BorderColor.B };
-                        (annotHandlerEventArgs as LineParam).LineColor = LineColor;
-                        (annotHandlerEventArgs as LineParam).LineWidth = lineData.Thickness;
-                        (annotHandlerEventArgs as LineParam).Transparency = Convert.ToByte(lineData.Opacity * 255);
-                        ParamConverter.ParseDashStyle(lineData.DashStyle, out float[] LineDash, out C_BORDER_STYLE BorderStyle);
-                        (annotHandlerEventArgs as LineParam).LineDash = LineDash;
-                        (annotHandlerEventArgs as LineParam).BorderStyle = BorderStyle;
-                        (annotHandlerEventArgs as LineParam).HeadLineType = lineData.LineType.HeadLineType;
-                        (annotHandlerEventArgs as LineParam).TailLineType = lineData.LineType.TailLineType;
-                        (annotHandlerEventArgs as LineParam).Author = CPDFMarkupData.Author;
-                        (annotHandlerEventArgs as LineParam).Content = lineData.Note;
+                        annotHandlerEventArgs = new LineParam()
+                        {
+                            CurrentType = C_ANNOTATION_TYPE.C_ANNOTATION_LINE
+                        };
+                        if (annotHandlerEventArgs is LineParam lineParam)
+                        { 
+                            byte[] LineColor = new byte[] { lineData.BorderColor.R, lineData.BorderColor.G, lineData.BorderColor.B };
+                            lineParam.LineColor = LineColor;
+                            lineParam.LineWidth = lineData.Thickness;
+                            lineParam.Transparency = Convert.ToByte(lineData.Opacity * 255);
+                            ParamConverter.ParseDashStyle(lineData.DashStyle, out float[] LineDash, out C_BORDER_STYLE BorderStyle);
+                            lineParam.LineDash = LineDash;
+                            lineParam.BorderStyle = BorderStyle;
+                            lineParam.HeadLineType = lineData.LineType.HeadLineType;
+                            lineParam.TailLineType = lineData.LineType.TailLineType;
+                            lineParam.Author = CPDFMarkupData.Author;
+                            lineParam.Content = lineData.Note;
+                        }
                         pdfViewerControl.SetCreateAnnotType(C_ANNOTATION_TYPE.C_ANNOTATION_LINE);
                     }
                     break;
@@ -332,12 +379,15 @@ namespace ComPDFKit.Controls.PDFControl
                     {
                         CPDFNoteData noteData = pdfAnnotationData as CPDFNoteData;
                         annotHandlerEventArgs = new StickyNoteParam();
-                        annotHandlerEventArgs.CurrentType = C_ANNOTATION_TYPE.C_ANNOTATION_TEXT;
-                        byte[] StickyNoteColor = new byte[] { noteData.BorderColor.R, noteData.BorderColor.G, noteData.BorderColor.B };
-                        (annotHandlerEventArgs as StickyNoteParam).StickyNoteColor = StickyNoteColor;
-                        (annotHandlerEventArgs as StickyNoteParam).Content = noteData.Note;
-                        (annotHandlerEventArgs as StickyNoteParam).Transparency = 255;
-                        (annotHandlerEventArgs as StickyNoteParam).Author = CPDFMarkupData.Author;
+                        if (annotHandlerEventArgs is StickyNoteParam stickyNoteParam)
+                        {
+                            annotHandlerEventArgs.CurrentType = C_ANNOTATION_TYPE.C_ANNOTATION_TEXT;
+                            byte[] StickyNoteColor = new byte[] { noteData.BorderColor.R, noteData.BorderColor.G, noteData.BorderColor.B };
+                            stickyNoteParam.StickyNoteColor = StickyNoteColor;
+                            stickyNoteParam.Content = noteData.Note;
+                            stickyNoteParam.Transparency = 255;
+                            stickyNoteParam.Author = CPDFMarkupData.Author;
+                        }  
                         pdfViewerControl.SetCreateAnnotType(C_ANNOTATION_TYPE.C_ANNOTATION_TEXT);
                     }
                     break;
@@ -345,14 +395,20 @@ namespace ComPDFKit.Controls.PDFControl
                 case CPDFAnnotationType.Freehand:
                     {
                         CPDFFreehandData freehandData = pdfAnnotationData as CPDFFreehandData;
-                        annotHandlerEventArgs = new InkParam();
-                        annotHandlerEventArgs.CurrentType = C_ANNOTATION_TYPE.C_ANNOTATION_INK;
-                        byte[] LineColor = new byte[] { freehandData.BorderColor.R, freehandData.BorderColor.G, freehandData.BorderColor.B };
-                        (annotHandlerEventArgs as InkParam).InkColor = LineColor;
-                        (annotHandlerEventArgs as InkParam).Thickness = freehandData.Thickness;
-                        (annotHandlerEventArgs as InkParam).Transparency = Convert.ToByte(freehandData.Opacity * 255);
-                        (annotHandlerEventArgs as InkParam).Content = freehandData.Note;
-                        (annotHandlerEventArgs as InkParam).Author = CPDFMarkupData.Author;
+                        annotHandlerEventArgs = new InkParam()
+                        {
+                            CurrentType = C_ANNOTATION_TYPE.C_ANNOTATION_INK
+                        };
+                        if (annotHandlerEventArgs is InkParam inkParam)
+                        {
+                            byte[] LineColor = new byte[] { freehandData.BorderColor.R, freehandData.BorderColor.G, freehandData.BorderColor.B };
+                            inkParam.InkColor = LineColor;
+                            inkParam.Thickness = freehandData.Thickness;
+                            inkParam.Transparency = Convert.ToByte(freehandData.Opacity * 255);
+                            inkParam.Content = freehandData.Note;
+                            inkParam.Author = CPDFMarkupData.Author;
+                        } 
+
                         pdfViewerControl.SetCreateAnnotType(C_ANNOTATION_TYPE.C_ANNOTATION_INK);
                     }
                     break;
@@ -360,57 +416,66 @@ namespace ComPDFKit.Controls.PDFControl
                 case CPDFAnnotationType.FreeText:
                     {
                         CPDFFreeTextData freeTextData = pdfAnnotationData as CPDFFreeTextData;
-                        annotHandlerEventArgs = new FreeTextParam();
-                        annotHandlerEventArgs.CurrentType = C_ANNOTATION_TYPE.C_ANNOTATION_FREETEXT;
-                        (annotHandlerEventArgs as FreeTextParam).Transparency = Convert.ToByte(freeTextData.Opacity * 255);
-                        (annotHandlerEventArgs as FreeTextParam).FontName = freeTextData.FontFamily.ToString();
-
-                        byte[] FontColor = new byte[] { freeTextData.BorderColor.R, freeTextData.BorderColor.G, freeTextData.BorderColor.B };
-                        (annotHandlerEventArgs as FreeTextParam).FontColor = FontColor;
-                        (annotHandlerEventArgs as FreeTextParam).FontSize = freeTextData.FontSize; 
-
-                        string postScriptName = string.Empty;
-                        CPDFFont.GetPostScriptName(pdfFreeTextUI.CPDFFontControl.FontFamilyValue, pdfFreeTextUI.CPDFFontControl.FontStyleValue, ref postScriptName);
-                        (annotHandlerEventArgs as FreeTextParam).FontName = postScriptName;
-                        switch (freeTextData.TextAlignment)
+                        annotHandlerEventArgs = new FreeTextParam()
                         {
-                            case TextAlignment.Left:
-                                (annotHandlerEventArgs as FreeTextParam).Alignment = C_TEXT_ALIGNMENT.ALIGNMENT_LEFT;
-                                break;
-                            case TextAlignment.Right:
-                                (annotHandlerEventArgs as FreeTextParam).Alignment = C_TEXT_ALIGNMENT.ALIGNMENT_RIGHT;
-                                break;
-                            case TextAlignment.Center:
-                                (annotHandlerEventArgs as FreeTextParam).Alignment = C_TEXT_ALIGNMENT.ALIGNMENT_CENTER;
-                                break;
-                            default:
-                                break;
+                            CurrentType = C_ANNOTATION_TYPE.C_ANNOTATION_FREETEXT
+                        };
+                        if (annotHandlerEventArgs is FreeTextParam freeTextParam)
+                        {
+                            freeTextParam.Transparency = Convert.ToByte(freeTextData.Opacity * 255);
+                            freeTextParam.FontName = freeTextData.FontFamily.ToString();
+
+                            byte[] FontColor = new byte[] { freeTextData.BorderColor.R, freeTextData.BorderColor.G, freeTextData.BorderColor.B };
+                            freeTextParam.FontColor = FontColor;
+                            freeTextParam.FontSize = freeTextData.FontSize;
+
+                            string postScriptName = string.Empty;
+                            CPDFFont.GetPostScriptName(pdfFreeTextUI.CPDFFontControl.FontFamilyValue, pdfFreeTextUI.CPDFFontControl.FontStyleValue, ref postScriptName);
+                            freeTextParam.FontName = postScriptName;
+                            switch (freeTextData.TextAlignment)
+                            {
+                                case TextAlignment.Left:
+                                    freeTextParam.Alignment = C_TEXT_ALIGNMENT.ALIGNMENT_LEFT;
+                                    break;
+                                case TextAlignment.Right:
+                                    freeTextParam.Alignment = C_TEXT_ALIGNMENT.ALIGNMENT_RIGHT;
+                                    break;
+                                case TextAlignment.Center:
+                                    freeTextParam.Alignment = C_TEXT_ALIGNMENT.ALIGNMENT_CENTER;
+                                    break;
+                                default:
+                                    break;
+                            }
+                            freeTextParam.Content = freeTextData.Note;
+                            freeTextParam.Author = CPDFMarkupData.Author;
                         }
-                        (annotHandlerEventArgs as FreeTextParam).Content = freeTextData.Note;
-                        (annotHandlerEventArgs as FreeTextParam).Author = CPDFMarkupData.Author;
+
                         pdfViewerControl.SetCreateAnnotType(C_ANNOTATION_TYPE.C_ANNOTATION_FREETEXT);
                     }
                     break;
 
                 case CPDFAnnotationType.Stamp:
                     {
-                        StampParam stampParam = new StampParam();
-                        stampParam.CurrentType = C_ANNOTATION_TYPE.C_ANNOTATION_STAMP;
-                        CPDFStampData stampData = pdfAnnotationData as CPDFStampData;
-                        SetStamp(ref stampParam, stampData);
-                        annotHandlerEventArgs = stampParam;
-                        pdfViewerControl.SetCreateAnnotType(C_ANNOTATION_TYPE.C_ANNOTATION_STAMP);
-
-                        byte[] imageData = null;
-                        int imageWidth = 0;
-                        int imageHeight = 0;
-                        PDFHelp.ImageStreamToByte(stampParam.ImageStream, ref imageData, ref imageWidth, ref imageHeight);
-                        if (imageData != null && imageWidth > 0 && imageHeight > 0)
+                        StampParam stampParam = new StampParam()
                         {
-                            pdfViewerControl.PDFViewTool.GetCPDFViewer().SetMouseImageMaxSize(200, 300);
-                            pdfViewerControl.SetStampMouseImage(imageData, imageWidth, imageHeight);
-                        }
-
+                            CurrentType = C_ANNOTATION_TYPE.C_ANNOTATION_STAMP
+                        }; 
+                        if(pdfAnnotationData is CPDFStampData stampData)
+                        {
+                            SetStamp(ref stampParam, stampData);
+                            annotHandlerEventArgs = stampParam;
+                            pdfViewerControl.SetCreateAnnotType(C_ANNOTATION_TYPE.C_ANNOTATION_STAMP);
+
+                            byte[] imageData = null;
+                            int imageWidth = 0;
+                            int imageHeight = 0;
+                            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);
                     }
@@ -699,6 +764,7 @@ namespace ComPDFKit.Controls.PDFControl
 
         public void AnnotationCancel()
         {
+            this.pdfViewerControl.SetCreateAnnotType(C_ANNOTATION_TYPE.C_ANNOTATION_NONE);
             this.pdfViewerControl.SetToolType(ToolType.Pan);
             pdfViewerControl.SetIsShowStampMouse(false);
             pdfViewerControl.SetIsVisibleCustomMouse(false);
@@ -762,6 +828,13 @@ namespace ComPDFKit.Controls.PDFControl
                     annotationPanel = pdfCircleUI;
                     (annotationPanel as CPDFShapeUI).InitWithAnnotationType(annotationType);
                     break;
+                case CPDFAnnotationType.Polygon:
+                    if (pdfCloudUI == null)
+                    {
+                        pdfCloudUI = new CPDFCloudUI();
+                    }
+                    annotationPanel = pdfCloudUI;
+                    break;
                 case CPDFAnnotationType.Arrow:
                     if (pdfArrowUI == null)
                     {
@@ -1093,6 +1166,17 @@ namespace ComPDFKit.Controls.PDFControl
                         (tempAnnotationPanel as CPDFLinkUI).SetPresentAnnotAttrib(annotParam as LinkParam, baseAnnot.GetAnnotData().Annot as CPDFLinkAnnotation, pdfViewerControl, pdfViewerControl.PDFToolManager.GetDocument().PageCount);
                     }
                     break;
+                case C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON:
+                    {
+                        tempAnnotationPanel = new CPDFCloudUI();
+                        AnnotParam annotParam = ParamConverter.CPDFDataConverterToAnnotParam(
+                            pdfViewerControl.PDFViewTool.GetCPDFViewer().GetDocument(),
+                            baseAnnot.GetAnnotData().PageIndex,
+                            baseAnnot.GetAnnotData().Annot
+                            );
+                        (tempAnnotationPanel as CPDFCloudUI).SetPresentAnnotAttrib(annotParam as PolygonMeasureParam, baseAnnot.GetAnnotData().Annot as CPDFPolygonAnnotation, pdfViewerControl, pdfViewerControl.PDFToolManager.GetDocument().PageCount);
+                    }
+                    break;
                 case C_ANNOTATION_TYPE.C_ANNOTATION_SOUND:
                     tempAnnotationPanel = null;
                     break;
@@ -1116,7 +1200,7 @@ namespace ComPDFKit.Controls.PDFControl
             {
                 if (annotationPanel is CPDFFreehandUI)
                 {
-                    if(pdfViewerControl.PDFToolManager.GetToolType() == ToolType.Customize)
+                    if (pdfViewerControl.PDFToolManager.GetToolType() == ToolType.Customize)
                     {
                         (annotationPanel as CPDFFreehandUI)?.SetEraseCheck(true);
                         return;
@@ -1124,7 +1208,7 @@ namespace ComPDFKit.Controls.PDFControl
                     else
                     {
                         (annotationPanel as CPDFFreehandUI)?.SetEraseCheck(false);
-                    }                    
+                    }
                 }
 
                 SetAnnotationPanel(annotationPanel);

+ 61 - 0
Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationPanel/PDFAnnotationUI/CPDFCloudUI.xaml

@@ -0,0 +1,61 @@
+<UserControl x:Class="ComPDFKit.Controls.PDFControlUI.CPDFCloudUI"
+             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:cpdfcommon="clr-namespace:ComPDFKit.Controls.Common" 
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
+             xmlns:local="clr-namespace:ComPDFKit.Controls.PDFControlUI" 
+             xmlns:cpdftools="clr-namespace:ComPDFKit.Controls.PDFControl" 
+             mc:Ignorable="d" 
+             d:DesignHeight="800" d:DesignWidth="300" Loaded="UserControl_Loaded" Unloaded="UserControl_Unloaded"> 
+    <UserControl.Resources> 
+        <ResourceDictionary> 
+            <ResourceDictionary.MergedDictionaries> 
+                <ResourceDictionary Source="../../../Asset/Styles/ToggleButtonStyle.xaml"></ResourceDictionary>
+            </ResourceDictionary.MergedDictionaries>
+            <cpdfcommon:PropertyPanelResourceConverter x:Key="PropertyPanelResourceConverter"></cpdfcommon:PropertyPanelResourceConverter>
+        </ResourceDictionary> 
+    </UserControl.Resources> 
+    <ScrollViewer VerticalScrollBarVisibility="Auto"> 
+        <Grid Background="#FAFCFF"> 
+            <StackPanel Orientation="Vertical"> 
+                <Border BorderThickness="1" BorderBrush="#1A000000"> 
+                    <Grid  Height="40" Background="White" >
+                        <TextBlock x:Name="TitleTextBlock" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_Cloud}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16" FontFamily="Microsoft YaHei"></TextBlock>
+                    </Grid>
+                </Border>
+                <cpdftools:CPDFAnnotationPreviewerControl x:Name="CPDFAnnotationPreviewerControl" Height="100" Margin="16"></cpdftools:CPDFAnnotationPreviewerControl>
+                <StackPanel Name="CloudPanel" Orientation="Vertical">
+                    <StackPanel Height="75" Margin="5">
+                        <TextBlock Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_LineColor}"></TextBlock>
+                        <cpdfcommon:ColorPickerControl x:Name="ctlBorderColorPicker" TransparentBtnProperty="Collapsed" Brush="Red"></cpdfcommon:ColorPickerControl>
+                    </StackPanel>
+                    <StackPanel Height="75" Margin="5">
+                        <TextBlock Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_FillColor}"></TextBlock>
+                        <cpdfcommon:ColorPickerControl x:Name="ctlFillColorPicker" Brush="Transparent"></cpdfcommon:ColorPickerControl>
+                    </StackPanel>
+                    <StackPanel Height="80" Margin="5">
+                        <TextBlock Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_LineShape}"></TextBlock>
+                        <cpdfcommon:CPDFLineStyleControl x:Name="ctlLineStyle"></cpdfcommon:CPDFLineStyleControl>
+                    </StackPanel>
+                    <StackPanel Height="100" Margin="5">
+                        <TextBlock Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_LineStyle}"></TextBlock>
+                        <cpdfcommon:CPDFCloudStyleControl x:Name="CPDFLineShapeControl"></cpdfcommon:CPDFCloudStyleControl>
+                    </StackPanel>
+                    <StackPanel Height="75" Margin="5">
+                        <TextBlock Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Opacity}"></TextBlock>
+                        <cpdfcommon:CPDFOpacityControl x:Name="CPDFOpacityControl"></cpdfcommon:CPDFOpacityControl>
+                    </StackPanel>
+                    <StackPanel Height="75" Margin="5">
+                        <TextBlock Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_LineWidth}"></TextBlock>
+                        <cpdfcommon:CPDFThicknessControl x:Name="CPDFThicknessControl"></cpdfcommon:CPDFThicknessControl>
+                    </StackPanel>
+                    <StackPanel Height="200" Margin="5">
+                        <TextBlock Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Note}"></TextBlock>
+                        <TextBox Height="150" x:Name="NoteTextBox" TextWrapping="Wrap" AcceptsReturn="True" TextChanged="NoteTextBox_TextChanged"></TextBox>
+                    </StackPanel>
+                </StackPanel>
+            </StackPanel>
+        </Grid>
+    </ScrollViewer>
+</UserControl>

+ 339 - 0
Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationPanel/PDFAnnotationUI/CPDFCloudUI.xaml.cs

@@ -0,0 +1,339 @@
+using ComPDFKit.Controls.Common;
+using ComPDFKit.Controls.Data;
+using ComPDFKit.Controls.PDFControl;
+using ComPDFKit.PDFAnnotation;
+using ComPDFKit.Tool;
+using ComPDFKit.Tool.Help;
+using ComPDFKit.Tool.UndoManger;
+using ComPDFKitViewer.Helper;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Windows.Controls;
+using System.Windows.Media;
+
+namespace ComPDFKit.Controls.PDFControlUI
+{
+    /// <summary>
+    /// Interaction logic for CPDFCloudUI.xaml
+    /// </summary>
+    public partial class CPDFCloudUI : UserControl
+    {
+        bool IsLoadedData = false;
+
+        private AnnotParam annotParam;
+        private CPDFAnnotation annotCore;
+        private PDFViewControl viewControl;
+        public event EventHandler<CPDFAnnotationData> PropertyChanged;
+
+        public CPDFCloudUI()
+        {
+            InitializeComponent();
+
+            ctlBorderColorPicker.ColorChanged -= CtlBorderColorPicker_ColorChanged;
+            ctlFillColorPicker.ColorChanged -= CtlFillColorPicker_ColorChanged;
+            CPDFOpacityControl.OpacityChanged -= CPDFOpacityControl_OpacityChanged;
+            CPDFThicknessControl.ThicknessChanged -= CPDFThicknessControl_ThicknessChanged;
+            CPDFLineShapeControl.LineShapeChanged -= CPDFLineShapeControl_LineShapeChanged;
+            ctlLineStyle.LineStyleChanged -= CtlLineStyle_LineStyleChanged;
+
+            ctlBorderColorPicker.ColorChanged += CtlBorderColorPicker_ColorChanged;
+            ctlFillColorPicker.ColorChanged += CtlFillColorPicker_ColorChanged;
+            CPDFOpacityControl.OpacityChanged += CPDFOpacityControl_OpacityChanged;
+            CPDFThicknessControl.ThicknessChanged += CPDFThicknessControl_ThicknessChanged;
+            CPDFLineShapeControl.LineShapeChanged += CPDFLineShapeControl_LineShapeChanged;
+            ctlLineStyle.LineStyleChanged += CtlLineStyle_LineStyleChanged;
+
+            CPDFAnnotationPreviewerControl.DrawCloudPreview();
+        }
+
+        private void CtlLineStyle_LineStyleChanged(object sender, EventArgs e)
+        {
+            if (annotParam == null)
+            {
+                PropertyChanged?.Invoke(this, GetPolygonData());
+            }
+            else
+            {
+                if (annotCore != null && annotCore.IsValid())
+                {
+                    float[] dashArray = null;
+                    C_BORDER_STYLE borderStyle;
+                    if (ctlLineStyle.DashStyle == DashStyles.Solid || ctlLineStyle.DashStyle == null)
+                    {
+                        dashArray = new float[0];
+                        borderStyle = C_BORDER_STYLE.BS_SOLID;
+                    }
+                    else
+                    {
+                        List<float> floatArray = new List<float>();
+                        foreach (double num in ctlLineStyle.DashStyle.Dashes)
+                        {
+                            floatArray.Add((float)num);
+                        }
+                        dashArray = floatArray.ToArray();
+                        borderStyle = C_BORDER_STYLE.BS_DASHDED;
+                    }
+
+                    if (viewControl != null && viewControl.PDFViewTool != null)
+                    {
+                        PolygonMeasureAnnotHistory history = new PolygonMeasureAnnotHistory();
+                        history.PDFDoc = viewControl.GetCPDFViewer().GetDocument();
+                        history.Action = HistoryAction.Update;
+                        CPDFPolygonAnnotation polygonAnnotation = annotCore as CPDFPolygonAnnotation;
+                        if (polygonAnnotation == null || polygonAnnotation.Dash.SequenceEqual(dashArray)) return;
+                        history.PreviousParam = ParamConverter.CPDFDataConverterToAnnotParam(history.PDFDoc, annotCore.Page.PageIndex, polygonAnnotation);
+                        polygonAnnotation.SetBorderStyle(borderStyle, dashArray);
+                        history.CurrentParam = ParamConverter.CPDFDataConverterToAnnotParam(history.PDFDoc, annotCore.Page.PageIndex, polygonAnnotation);
+                        viewControl.GetCPDFViewer().UndoManager.AddHistory(history);
+
+                        annotCore.UpdateAp();
+                        viewControl.UpdateAnnotFrame();
+                    }
+                }
+            }
+        }
+
+        private void CPDFLineShapeControl_LineShapeChanged(object sender, CPDFBorderEffector e)
+        {
+            if (annotParam == null)
+            {
+                PropertyChanged?.Invoke(this, GetPolygonData());
+            }
+            if (IsLoadedData)
+            {
+                if (annotCore != null && annotCore.IsValid() && annotCore is CPDFPolygonAnnotation polygonAnnotation)
+                {
+                    PolygonMeasureAnnotHistory history = new PolygonMeasureAnnotHistory();
+                    history.PDFDoc = viewControl.GetCPDFViewer().GetDocument();
+                    history.Action = HistoryAction.Update;
+                    history.PreviousParam = ParamConverter.CPDFDataConverterToAnnotParam(history.PDFDoc, annotCore.Page.PageIndex, polygonAnnotation);
+                    polygonAnnotation.SetAnnotBorderEffector(e);
+                    history.CurrentParam = ParamConverter.CPDFDataConverterToAnnotParam(history.PDFDoc, annotCore.Page.PageIndex, polygonAnnotation);
+                    viewControl.GetCPDFViewer().UndoManager.AddHistory(history);
+
+                    annotCore.UpdateAp();
+                    viewControl.UpdateAnnotFrame();
+                }
+            }
+        }
+
+        private void CPDFThicknessControl_ThicknessChanged(object sender, EventArgs e)
+        {
+            if (annotParam == null)
+            {
+                PropertyChanged?.Invoke(this, GetPolygonData());
+            }
+            if (IsLoadedData)
+            {
+                if (annotCore != null && annotCore.IsValid() && annotCore is CPDFPolygonAnnotation polygonAnnotation)
+                {
+                    PolygonMeasureAnnotHistory history = new PolygonMeasureAnnotHistory();
+                    history.PDFDoc = viewControl.GetCPDFViewer().GetDocument();
+                    history.Action = HistoryAction.Update;
+                    history.PreviousParam = ParamConverter.CPDFDataConverterToAnnotParam(history.PDFDoc, annotCore.Page.PageIndex, annotCore);
+                    polygonAnnotation.SetLineWidth((sender as CPDFThicknessControl).Thickness);
+                    history.CurrentParam = ParamConverter.CPDFDataConverterToAnnotParam(history.PDFDoc, annotCore.Page.PageIndex, annotCore);
+                    viewControl.GetCPDFViewer().UndoManager.AddHistory(history);
+
+                    annotCore.UpdateAp();
+                    viewControl.UpdateAnnotFrame();
+                }
+            }
+        }
+
+        private void CPDFOpacityControl_OpacityChanged(object sender, EventArgs e)
+        {
+            if (annotParam == null)
+            {
+                PropertyChanged?.Invoke(this, GetPolygonData());
+            }
+            if (IsLoadedData)
+            {
+                if (annotCore != null && annotCore.IsValid())
+                {
+                    double opacity = (sender as CPDFOpacityControl).OpacityValue / 100.0;
+                    if (opacity > 0 && opacity <= 1)
+                    {
+                        opacity *= 255;
+                    }
+
+                    PolygonMeasureAnnotHistory history = new PolygonMeasureAnnotHistory();
+                    history.PDFDoc = viewControl.GetCPDFViewer().GetDocument();
+                    history.Action = HistoryAction.Update;
+                    history.PreviousParam = ParamConverter.CPDFDataConverterToAnnotParam(history.PDFDoc, annotCore.Page.PageIndex, annotCore);
+                    annotCore.SetTransparency((byte)opacity);
+                    history.CurrentParam = ParamConverter.CPDFDataConverterToAnnotParam(history.PDFDoc, annotCore.Page.PageIndex, annotCore);
+                    viewControl.GetCPDFViewer().UndoManager.AddHistory(history);
+
+                    annotCore.UpdateAp();
+                    viewControl.UpdateAnnotFrame();
+                }
+            }
+        }
+
+        private void CtlFillColorPicker_ColorChanged(object sender, EventArgs e)
+        {
+            if (annotParam == null)
+            {
+                PropertyChanged?.Invoke(this, GetPolygonData());
+            }
+            if (IsLoadedData)
+            {
+                if (annotCore != null && annotCore.IsValid())
+                {
+                    if (annotCore is CPDFPolygonAnnotation polygonAnnotation)
+                    {
+                        PolygonMeasureAnnotHistory history = new PolygonMeasureAnnotHistory();
+                        history.PDFDoc = viewControl.GetCPDFViewer().GetDocument();
+                        history.Action = HistoryAction.Update;
+                        history.PreviousParam = ParamConverter.CPDFDataConverterToAnnotParam(history.PDFDoc, annotCore.Page.PageIndex, polygonAnnotation);
+
+                        SolidColorBrush brush = (sender as ColorPickerControl)?.Brush as SolidColorBrush;
+                        polygonAnnotation.SetBgColor(new byte[3]
+                        {
+                            brush.Color.R,
+                            brush.Color.G,
+                            brush.Color.B
+                        });
+
+                        if(brush.Color.A == 0)
+                        {
+                            polygonAnnotation.ClearBgColor();
+                        }
+
+                        history.CurrentParam = ParamConverter.CPDFDataConverterToAnnotParam(history.PDFDoc, annotCore.Page.PageIndex, polygonAnnotation);
+                        viewControl.GetCPDFViewer().UndoManager.AddHistory(history);
+
+                        annotCore.UpdateAp();
+                        viewControl.UpdateAnnotFrame();
+                    }
+                }
+            }
+        }
+
+        private void CtlBorderColorPicker_ColorChanged(object sender, EventArgs e)
+        {
+            if (annotParam == null)
+            {
+                PropertyChanged?.Invoke(this, GetPolygonData());
+            }
+            if (IsLoadedData)
+            {
+                if (annotCore != null && annotCore.IsValid())
+                {
+                    if (annotCore is CPDFPolygonAnnotation polygonAnnotation)
+                    {
+                        PolygonMeasureAnnotHistory history = new PolygonMeasureAnnotHistory();
+                        history.PDFDoc = viewControl.GetCPDFViewer().GetDocument();
+                        history.Action = HistoryAction.Update;
+                        history.PreviousParam = ParamConverter.CPDFDataConverterToAnnotParam(history.PDFDoc, annotCore.Page.PageIndex, polygonAnnotation);
+
+                        SolidColorBrush brush = (sender as ColorPickerControl)?.Brush as SolidColorBrush;
+                        polygonAnnotation.SetLineColor(new byte[3]
+                        {
+                            brush.Color.R,
+                            brush.Color.G,
+                            brush.Color.B
+                        });
+
+                        history.CurrentParam = ParamConverter.CPDFDataConverterToAnnotParam(history.PDFDoc, annotCore.Page.PageIndex, polygonAnnotation);
+                        
+                        annotCore.UpdateAp();
+                        viewControl.GetCPDFViewer().UndoManager.AddHistory(history);
+                        viewControl.UpdateAnnotFrame();
+                    }
+                }
+            }
+        }
+
+        public void SetPresentAnnotAttrib(PolygonMeasureParam polygonParam, CPDFPolygonAnnotation annotation, PDFViewControl view, int PageCount)
+        {
+            annotParam = polygonParam;
+            annotCore = annotation;
+            viewControl = view;
+            if (polygonParam == null)
+            {
+                return;
+            }
+
+            Color lineColor = Color.FromRgb(polygonParam.LineColor[0], polygonParam.LineColor[1], polygonParam.LineColor[2]);
+            Color fillColor;
+            if (annotation.HasBgColor)
+            {
+                fillColor = Color.FromRgb(polygonParam.FillColor[0], polygonParam.FillColor[1], polygonParam.FillColor[2]);
+            }
+            else
+            {
+                fillColor = Colors.Transparent;
+            }
+
+            ctlBorderColorPicker.SetCheckedForColor(lineColor);
+            ctlFillColorPicker.SetCheckedForColor(fillColor);
+
+            double opacity = polygonParam.Transparency / 255.0 * 100.0;
+            CPDFOpacityControl.OpacityValue = (int)Math.Ceiling(opacity);
+
+            float thickness = polygonParam.LineWidth;
+            CPDFThicknessControl.Thickness = (int)Math.Ceiling(thickness);
+
+            CPDFLineShapeControl.BorderEffector = annotation.GetAnnotBorderEffector();
+            if (polygonParam.BorderStyle == C_BORDER_STYLE.BS_SOLID)
+            {
+                ctlLineStyle.DashStyle = DashStyles.Solid;
+            }
+            else
+            {
+                List<double> dashArray = new List<double>();
+                foreach (double num in polygonParam.LineDash)
+                {
+                    dashArray.Add(num);
+                }
+                ctlLineStyle.DashStyle = new DashStyle(dashArray, 0);
+            }
+
+            NoteTextBox.Text = polygonParam.Content;
+        }
+
+        public CPDFAnnotationData GetPolygonData()
+        {
+            CPDFPolygonData polygonData = new CPDFPolygonData
+            {
+                AnnotationType = CPDFAnnotationType.Polygon,
+                BorderColor = ((SolidColorBrush)ctlBorderColorPicker.Brush).Color,
+                FillColor = ((SolidColorBrush)ctlFillColorPicker.Brush).Color,
+                BorderEffector = CPDFLineShapeControl.BorderEffector,
+                DashStyle = ctlLineStyle.DashStyle, 
+                IsMeasured = false,
+                Thickness = CPDFThicknessControl.Thickness,
+                Opacity = CPDFOpacityControl.OpacityValue,
+                Note = NoteTextBox.Text
+            };
+
+            return polygonData;
+        }
+
+        private void UserControl_Loaded(object sender, System.Windows.RoutedEventArgs e)
+        {
+            IsLoadedData = true;
+        }
+
+        private void UserControl_Unloaded(object sender, System.Windows.RoutedEventArgs e)
+        {
+            IsLoadedData = false;
+        }
+
+        private void NoteTextBox_TextChanged(object sender, TextChangedEventArgs e)
+        {
+            if (IsLoadedData)
+            {
+                if (annotCore != null && annotCore.IsValid())
+                {
+                    annotCore.SetContent(NoteTextBox.Text);
+                    annotCore.UpdateAp();
+                    viewControl?.UpdateAnnotFrame();
+                }
+            }
+        }
+    }
+}

+ 52 - 52
Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationPanel/PDFAnnotationUI/CPDFFreehandUI.xaml

@@ -16,27 +16,27 @@
             <cpdfcommon:PropertyPanelResourceConverter x:Key="PropertyPanelResourceConverter"></cpdfcommon:PropertyPanelResourceConverter>
         </ResourceDictionary>
     </UserControl.Resources>
-    <ScrollViewer VerticalScrollBarVisibility="Auto"> 
+    <ScrollViewer VerticalScrollBarVisibility="Auto">
         <Grid Background="#FAFCFF">
-        <StackPanel Orientation="Vertical">
-            <Border BorderThickness="1" BorderBrush="#1A000000">
-                <Grid  Height="40" Background="White" >
-                    <TextBlock x:Name="TitleTextBlock" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_Ink}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16" FontFamily="Microsoft YaHei"></TextBlock>
-                </Grid>
-            </Border>
-            <StackPanel Orientation="Vertical" Height="130">
-                <cpdftools:CPDFAnnotationPreviewerControl x:Name="CPDFAnnotationPreviewerControl" Height="100" Margin="16"></cpdftools:CPDFAnnotationPreviewerControl>
-
-                <Border BorderBrush="#E2E3E6" BorderThickness="1" Background="White" Height="100" Margin="16" Name="EraseCirclePanel" Visibility="Collapsed">
-                    <Ellipse Name="EraseCircle" Fill="#1A000000" Width="6" Height="6"></Ellipse>
+            <StackPanel Orientation="Vertical">
+                <Border BorderThickness="1" BorderBrush="#1A000000">
+                    <Grid  Height="40" Background="White" >
+                        <TextBlock x:Name="TitleTextBlock" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_Ink}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16" FontFamily="Microsoft YaHei"></TextBlock>
+                    </Grid>
                 </Border>
-            </StackPanel>
-           
-            <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
-                <ToggleButton Name="FreehandBtn" Style="{StaticResource ToggleButtonStyle}" Width="50" Height="32" BorderThickness="0" IsChecked="True" Click="FreehandBtn_Click">
-                    <Path Fill="#43474D">
-                        <Path.Data>
-                            M13.4957 3.18186L11.0208 0.706987C10.6303 0.316463 9.99531 0.318287 9.60254 0.711062L1.96623 8.34737L0.944556 13.2581L5.85532 12.2365L13.4916 4.60015C13.8844 
+                <StackPanel Orientation="Vertical" Height="130">
+                    <cpdftools:CPDFAnnotationPreviewerControl x:Name="CPDFAnnotationPreviewerControl" Height="100" Margin="16"></cpdftools:CPDFAnnotationPreviewerControl>
+
+                    <Border BorderBrush="#E2E3E6" BorderThickness="1" Background="White" Height="100" Margin="16" Name="EraseCirclePanel" Visibility="Collapsed">
+                        <Ellipse Name="EraseCircle" Fill="#1A000000" Width="6" Height="6"></Ellipse>
+                    </Border>
+                </StackPanel>
+
+                <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
+                    <ToggleButton Name="FreehandBtn" Style="{StaticResource ToggleButtonStyle}" Width="50" Height="32" BorderThickness="0" IsChecked="True" Click="FreehandBtn_Click">
+                        <Path Fill="#43474D">
+                            <Path.Data>
+                                M13.4957 3.18186L11.0208 0.706987C10.6303 0.316463 9.99531 0.318287 9.60254 0.711062L1.96623 8.34737L0.944556 13.2581L5.85532 12.2365L13.4916 4.60015C13.8844 
                             4.20737 13.8862 3.57239 13.4957 3.18186ZM10.3096 1.41807L12.7844 3.89295L11.9714 4.70585L9.49654 2.23098L10.3096 1.41807ZM8.78532 2.94212L11.2602 
                             5.41699L5.73071 10.9458C5.45073 10.4059 5.10425 9.92877 4.69144 9.51596C4.27669 9.10121 3.79698 8.75341 3.25399 8.47274L8.78532 2.94212ZM2.77914 
                             9.35888L2.23707 11.9659L4.84581 11.423C4.61097 10.9675 4.32252 10.5694 3.98026 10.2271C3.63668 9.88356 3.23687 9.59421 2.77914 9.35888ZM0 
@@ -50,47 +50,47 @@
                             12.699C8.60834 12.5616 8.26493 12.4956 7.79583 12.5001L7.49924 12.5113C7.39531 12.5178 7.2863 12.5272 7.17215 12.5394L6.81426 12.5844C6.75203 
                             12.5933 6.6885 12.6029 6.62366 12.6132L6.21896 12.6835L5.78265 12.7706L5.31442 12.8744L4.81393 12.9951L4.28087 13.1324L3.41952 13.3696L2.80364 
                             13.5486L2.15407 13.7442L1.11584 14.0687L0 14.4304Z
-                        </Path.Data>
-                    </Path>
-                </ToggleButton>
-                <ToggleButton Name="EraseBtn" Style="{StaticResource ToggleButtonStyle}" Width="50" Height="32" BorderThickness="0" Click="EraseBtn_Click">
-                    <Path Fill="#43474D">
-                        <Path.Data>
-                            M7.71094 14L15.2031 6.5L9.5 0.796875L0.890625 9.40625C0.765625 9.53125 0.670573 9.67839 0.605469 9.84766C0.540365 10.0169 0.507812 10.1927 0.507812 
+                            </Path.Data>
+                        </Path>
+                    </ToggleButton>
+                    <ToggleButton Name="EraseBtn" Style="{StaticResource ToggleButtonStyle}" Width="50" Height="32" BorderThickness="0" Click="EraseBtn_Click">
+                        <Path Fill="#43474D">
+                            <Path.Data>
+                                M7.71094 14L15.2031 6.5L9.5 0.796875L0.890625 9.40625C0.765625 9.53125 0.670573 9.67839 0.605469 9.84766C0.540365 10.0169 0.507812 10.1927 0.507812 
                             10.375C0.507812 10.5573 0.540365 10.7331 0.605469 10.9023C0.670573 11.0716 0.768229 11.2214 0.898438 11.3516L3.53906 14H7.71094ZM8.5 11.7969L4.20312 
                             7.5L9.5 2.20312L13.7969 6.5L8.5 11.7969ZM3.95312 13H7.28906L7.79688 12.5L3.5 8.20312L1.60156 10.1016C1.53385 10.1693 1.5 10.2604 1.5 10.375C1.5 10.4896 
                             1.53646 10.5833 1.60938 10.6562L3.95312 13ZM16 14V13H10.0182L9 14H16ZM1.06227 13L2 14H0V13H1.06227Z
-                        </Path.Data>
-                    </Path>
-                </ToggleButton>
-            </StackPanel>
-            
-            <StackPanel Name="FreehandPanel" Orientation="Vertical">
-                <StackPanel Height="75" Margin="5">
-                    <TextBlock Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Color}"></TextBlock>
-                    <cpdfcommon:ColorPickerControl x:Name="ColorPickerControl" TransparentBtnProperty="Collapsed"></cpdfcommon:ColorPickerControl>
-                </StackPanel>
-                <StackPanel Height="75" Margin="5">
-                    <TextBlock Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Opacity}"></TextBlock>
-                    <cpdfcommon:CPDFOpacityControl x:Name="CPDFOpacityControl"></cpdfcommon:CPDFOpacityControl>
+                            </Path.Data>
+                        </Path>
+                    </ToggleButton>
                 </StackPanel>
-                <StackPanel Height="75" Margin="5">
-                    <TextBlock Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_LineWidth}"></TextBlock>
-                    <cpdfcommon:CPDFThicknessControl x:Name="CPDFThicknessControl"></cpdfcommon:CPDFThicknessControl>
+
+                <StackPanel Name="FreehandPanel" Orientation="Vertical">
+                    <StackPanel Height="75" Margin="5">
+                        <TextBlock Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Color}"></TextBlock>
+                        <cpdfcommon:ColorPickerControl x:Name="ColorPickerControl" TransparentBtnProperty="Collapsed"></cpdfcommon:ColorPickerControl>
+                    </StackPanel>
+                    <StackPanel Height="75" Margin="5">
+                        <TextBlock Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Opacity}"></TextBlock>
+                        <cpdfcommon:CPDFOpacityControl x:Name="CPDFOpacityControl"></cpdfcommon:CPDFOpacityControl>
+                    </StackPanel>
+                    <StackPanel Height="75" Margin="5">
+                        <TextBlock Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_LineWidth}"></TextBlock>
+                        <cpdfcommon:CPDFThicknessControl x:Name="CPDFThicknessControl"></cpdfcommon:CPDFThicknessControl>
+                    </StackPanel>
+                    <StackPanel Height="200" Margin="5">
+                        <TextBlock Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Note}"></TextBlock>
+                        <TextBox Height="150" x:Name="NoteTextBox" TextChanged="NoteTextBox_TextChanged" TextWrapping="Wrap" AcceptsReturn="True"></TextBox>
+                    </StackPanel>
                 </StackPanel>
-                <StackPanel Height="200" Margin="5">
-                    <TextBlock Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_Note}"></TextBlock>
-                    <TextBox Height="150" x:Name="NoteTextBox" TextChanged="NoteTextBox_TextChanged" TextWrapping="Wrap" AcceptsReturn="True"></TextBox>
+
+                <StackPanel Name="ErasePanel" Margin="5" Visibility="Collapsed">
+                    <TextBlock Text="Line Width"></TextBlock>
+                    <cpdfcommon:CPDFThicknessControl x:Name="EraseThickness"></cpdfcommon:CPDFThicknessControl>
                 </StackPanel>
-            </StackPanel>
 
-            <StackPanel Name="ErasePanel" Margin="5" Visibility="Collapsed">
-                <TextBlock Text="Line Width"></TextBlock>
-                <cpdfcommon:CPDFThicknessControl x:Name="EraseThickness"></cpdfcommon:CPDFThicknessControl>
             </StackPanel>
-           
-        </StackPanel>
-    </Grid>
+        </Grid>
     </ScrollViewer>
 
 </UserControl>

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

@@ -39,7 +39,7 @@ namespace ComPDFKit.Controls.PDFControlUI
                 switch (markupAnnot.Type)
                 {
                     case C_ANNOTATION_TYPE.C_ANNOTATION_HIGHLIGHT:
-                        return new LineAnnotHistory();
+                        return new HighlightAnnotHistory();
                     case C_ANNOTATION_TYPE.C_ANNOTATION_UNDERLINE:
                         return new UnderlineAnnotHistory();
                     case C_ANNOTATION_TYPE.C_ANNOTATION_STRIKEOUT:

+ 1 - 1
Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationPanel/PDFAnnotationUI/CPDFShapeUI.xaml

@@ -42,7 +42,7 @@
                 </StackPanel>
                 <StackPanel x:Name="LineStyleStackPanel" Height="90" Margin="5">
                     <TextBlock Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Property_LineStyle}"></TextBlock>
-                    <cpdfcommon:CPDFLineStyleControl x:Name="CPDFLineStyleControl"></cpdfcommon:CPDFLineStyleControl>
+                    <cpdfcommon:CPDFLineStyleControl x:Name="CPDFLineStyleControl"/>
                 </StackPanel>
                 <StackPanel x:Name="ArrowStackPanel" Visibility="Visible" Height="75"  Margin="5">
                     <StackPanel Orientation="Horizontal" Margin="0,0,0,10">

+ 1 - 2
Demo/Examples/Compdfkit.Controls/Annotation/PDFAnnotationPanel/PDFAnnotationUI/CPDFShapeUI.xaml.cs

@@ -419,8 +419,7 @@ namespace ComPDFKit.Controls.PDFControlUI
                 pdfShapeData.DashStyle = CPDFLineStyleControl.DashStyle;
                 pdfShapeData.Note = NoteTextBox.Text;
                 return pdfShapeData;
-            }
-
+            } 
             else
             {
                 CPDFLineShapeData pdfLineShapeData = new CPDFLineShapeData();

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 19 - 5
Demo/Examples/Compdfkit.Controls/Common/BarControl/CPDFAnnotationBarControl.xaml.cs


+ 107 - 122
Demo/Examples/Compdfkit.Controls/Common/BarControl/CPDFMeasureBarControl.xaml.cs

@@ -19,7 +19,7 @@ namespace ComPDFKit.Controls.PDFControl
         #region Data
 
         private bool isFirstLoad = true;
-        
+
         private static string line = LanguageHelper.ToolBarManager.GetString("Button_Line");
         private static string multiline = LanguageHelper.ToolBarManager.GetString("Button_Multiline");
         private static string polygonal = LanguageHelper.ToolBarManager.GetString("Button_Polygonal");
@@ -35,11 +35,15 @@ namespace ComPDFKit.Controls.PDFControl
 
 
         private PDFViewControl pdfViewer;
-
         private MeasurePropertyControl measurePropertyControl = null;
         private MeasureControl measureControl = null;
 
-        private enum MeasureType
+        private AnnotParam createLineMeasureParam = null;
+        private AnnotParam createPolyLineMeasureParam = null;
+        private AnnotParam createPolygonMeasureParam = null;
+        private AnnotParam createRectangleMeasureParam = null;
+
+        public enum MeasureType
         {
             UnKnown = -1,
             Line,
@@ -151,6 +155,32 @@ namespace ComPDFKit.Controls.PDFControl
             this.pdfViewer = pdfViewer;
             measurePropertyControl = FromProperty;
             measureControl = parentControl;
+
+            measurePropertyControl.LineMeasureParamChanged -= MeasurePropertyControl_LineMeasureParamChanged;
+            measurePropertyControl.LineMeasureParamChanged -= MeasurePropertyControl_LineMeasureParamChanged;
+            measurePropertyControl.PolygonMeasureParamChanged -= MeasurePropertyControl_PolygonMeasureParamChanged;
+
+            measurePropertyControl.PolyLineMeasureParamChanged += MeasurePropertyControl_PolyLineMeasureParamChanged;
+            measurePropertyControl.PolyLineMeasureParamChanged += MeasurePropertyControl_PolyLineMeasureParamChanged;
+            measurePropertyControl.PolygonMeasureParamChanged += MeasurePropertyControl_PolygonMeasureParamChanged; 
+        }
+
+        private void MeasurePropertyControl_PolygonMeasureParamChanged(object sender, PolygonMeasureParam e)
+        {
+            createPolygonMeasureParam = e;
+            pdfViewer.SetAnnotParam(e);
+        }
+
+        private void MeasurePropertyControl_PolyLineMeasureParamChanged(object sender, PolyLineMeasureParam e)
+        {
+            createPolyLineMeasureParam = e;
+            pdfViewer.SetAnnotParam(e);
+        }
+
+        private void MeasurePropertyControl_LineMeasureParamChanged(object sender, LineMeasureParam e)
+        {
+            createLineMeasureParam = e;
+            pdfViewer.SetAnnotParam(e);
         }
 
         public void ClearAllToolState()
@@ -170,7 +200,7 @@ namespace ComPDFKit.Controls.PDFControl
             {
                 if (child is ToggleButton toggle)
                 {
-                    if (toggle.IsChecked==true)
+                    if (toggle.IsChecked == true)
                     {
                         return true;
                     }
@@ -188,6 +218,32 @@ namespace ComPDFKit.Controls.PDFControl
                     toggle.IsChecked = false;
                 }
             }
+            measurePropertyControl.CurrentCreateType = C_ANNOTATION_TYPE.C_ANNOTATION_NONE;
+        }
+
+        public AnnotParam GetAnnotParam(MeasureType measureType)
+        {
+            AnnotParam currentParam = null;
+            switch (measureType)
+            {
+                case MeasureType.UnKnown:
+                    break;
+                case MeasureType.Line:
+                    currentParam = CreateLine();
+                    break;
+                case MeasureType.Multiline:
+                    currentParam = CreateMultiline();
+                    break;
+                case MeasureType.Polygonal:
+                    currentParam = CreatePolygonal();
+                    break;
+                case MeasureType.Rectangles:
+                    currentParam = CreateRectangles();
+                    break;
+                default:
+                    break;
+            }
+            return currentParam;
         }
 
         private void MeasureBtn_Click(object sender, RoutedEventArgs e)
@@ -196,25 +252,7 @@ namespace ComPDFKit.Controls.PDFControl
             ClearToolState(sender as ToggleButton);
             if ((bool)(sender as ToggleButton).IsChecked)
             {
-                switch (StringToType((sender as ToggleButton).Tag.ToString()))
-                {
-                    case MeasureType.UnKnown:
-                        break;
-                    case MeasureType.Line:
-                        annotParam = CreateLine();
-                        break;
-                    case MeasureType.Multiline:
-                        annotParam = CreateMultiline();
-                        break;
-                    case MeasureType.Polygonal:
-                        annotParam = CreatePolygonal();
-                        break;
-                    case MeasureType.Rectangles:
-                        annotParam = CreateRectangles();
-                        break;
-                    default:
-                        break;
-                }
+                annotParam = GetAnnotParam(StringToType((sender as ToggleButton).Tag.ToString()));
             }
             else
             {
@@ -232,35 +270,15 @@ namespace ComPDFKit.Controls.PDFControl
         #endregion
 
         #region Create Form
-
         private AnnotParam CreateLine()
         {
             pdfViewer.SetToolType(ToolType.CreateAnnot);
             pdfViewer.SetCreateAnnotType(C_ANNOTATION_TYPE.C_ANNOTATION_LINE);
-            LineMeasureParam lineMeasureParam = new LineMeasureParam();
-            lineMeasureParam.CurrentType = C_ANNOTATION_TYPE.C_ANNOTATION_LINE;
-            lineMeasureParam.LineColor = new byte[] { 255, 0, 0, };
-            lineMeasureParam.LineWidth = 2;
-            lineMeasureParam.Transparency = 255;
-            lineMeasureParam.FontColor = new byte[] { 255, 0, 0, };
-            lineMeasureParam.FontName = "Arial";
-            lineMeasureParam.FontSize = 14;
-            lineMeasureParam.HeadLineType = C_LINE_TYPE.LINETYPE_ARROW;
-            lineMeasureParam.TailLineType = C_LINE_TYPE.LINETYPE_ARROW;
-            lineMeasureParam.measureInfo = new CPDFMeasureInfo
+            if (createLineMeasureParam == null)
             {
-                Unit = CPDFMeasure.CPDF_CM,
-                Precision = CPDFMeasure.PRECISION_VALUE_TWO,
-                RulerBase = 1,
-                RulerBaseUnit = CPDFMeasure.CPDF_CM,
-                RulerTranslate = 1,
-                RulerTranslateUnit = CPDFMeasure.CPDF_CM,
-                CaptionType = CPDFCaptionType.CPDF_CAPTION_LENGTH,
-            };
-            pdfViewer.SetAnnotParam(lineMeasureParam);
-            //pdfViewer?.ClearSelectAnnots();
-            //pdfViewer?.SetMouseMode(MouseModes.AnnotCreate);
-            //pdfViewer?.SetToolParam(lineMeasureArgs);
+                createLineMeasureParam = new LineMeasureParam();
+            }
+            pdfViewer.SetAnnotParam(createLineMeasureParam);
             measureControl.SetMeasureInfoType(CPDFMeasureType.CPDF_DISTANCE_MEASURE);
             measureControl.SetInfoPanelVisble(true, false);
             var measureSetting = pdfViewer.PDFViewTool.GetMeasureSetting();
@@ -270,42 +288,21 @@ namespace ComPDFKit.Controls.PDFControl
                    measureSetting.RulerBaseUnit,
                    measureSetting.RulerTranslate,
                    measureSetting.RulerTranslateUnit));
-            return lineMeasureParam;
+            return createLineMeasureParam;
         }
 
+
         private AnnotParam CreateMultiline()
         {
             pdfViewer.SetToolType(ToolType.CreateAnnot);
             pdfViewer.SetCreateAnnotType(C_ANNOTATION_TYPE.C_ANNOTATION_POLYLINE);
-            PolyLineMeasureParam polyLineMeasureParam = new PolyLineMeasureParam();
-            polyLineMeasureParam.CurrentType = C_ANNOTATION_TYPE.C_ANNOTATION_POLYLINE;
-            polyLineMeasureParam.LineColor = new byte[] { 255, 0, 0, };
-            polyLineMeasureParam.LineWidth = 2;
-            polyLineMeasureParam.Transparency = 255;
-            polyLineMeasureParam.FontColor = new byte[] { 255, 0, 0, };
-            polyLineMeasureParam.FontName = "Arial";
-            polyLineMeasureParam.FontSize = 14;
-            polyLineMeasureParam.measureInfo = new CPDFMeasureInfo
+
+            if (createPolyLineMeasureParam == null)
             {
-                Unit = CPDFMeasure.CPDF_CM,
-                Precision = CPDFMeasure.PRECISION_VALUE_TWO,
-                RulerBase = 1,
-                RulerBaseUnit = CPDFMeasure.CPDF_CM,
-                RulerTranslate = 1,
-                RulerTranslateUnit = CPDFMeasure.CPDF_CM,
-                CaptionType = CPDFCaptionType.CPDF_CAPTION_LENGTH,
-            };
-            pdfViewer.SetAnnotParam(polyLineMeasureParam);
-            //PolyLineMeasureArgs polyLineMeasureArgs = new PolyLineMeasureArgs();
-            //polyLineMeasureArgs.LineColor = Colors.Red;
-            //polyLineMeasureArgs.LineWidth = 2;
-            //polyLineMeasureArgs.Transparency = 1;
-            //polyLineMeasureArgs.FontColor = Colors.Red;
-            //polyLineMeasureArgs.FontName = "Arial";
-            //polyLineMeasureArgs.FontSize = 14;
-            // pdfViewer?.ClearSelectAnnots();
-            // pdfViewer?.SetMouseMode(MouseModes.AnnotCreate);
-            // pdfViewer?.SetToolParam(polyLineMeasureArgs);
+                createPolyLineMeasureParam = new PolyLineMeasureParam();
+            }
+
+            pdfViewer.SetAnnotParam(createPolyLineMeasureParam);
             measureControl.SetMeasureInfoType(CPDFMeasureType.CPDF_PERIMETER_MEASURE);
             measureControl.SetInfoPanelVisble(true, false);
             var measureSetting = pdfViewer.PDFViewTool.GetMeasureSetting();
@@ -315,14 +312,11 @@ namespace ComPDFKit.Controls.PDFControl
                    measureSetting.RulerBaseUnit,
                    measureSetting.RulerTranslate,
                    measureSetting.RulerTranslateUnit));
-            return polyLineMeasureParam;
+            return createPolyLineMeasureParam;
         }
 
-        private AnnotParam CreatePolygonal()
+        private AnnotParam CreatePolygonalParam()
         {
-            pdfViewer.PDFViewTool.GetDefaultSettingParam().IsCreateSquarePolygonMeasure = false;
-            pdfViewer.SetToolType(ToolType.CreateAnnot);
-            pdfViewer.SetCreateAnnotType(C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON);
             PolygonMeasureParam polygonMeasureParam = new PolygonMeasureParam();
             polygonMeasureParam.CurrentType = C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON;
             polygonMeasureParam.LineColor = new byte[] { 255, 0, 0, };
@@ -331,6 +325,7 @@ namespace ComPDFKit.Controls.PDFControl
             polygonMeasureParam.FontColor = new byte[] { 255, 0, 0, };
             polygonMeasureParam.FontName = "Arial";
             polygonMeasureParam.FontSize = 14;
+            polygonMeasureParam.IsMeasure = true;
             polygonMeasureParam.measureInfo = new CPDFMeasureInfo
             {
                 Unit = CPDFMeasure.CPDF_CM,
@@ -341,18 +336,21 @@ namespace ComPDFKit.Controls.PDFControl
                 RulerTranslateUnit = CPDFMeasure.CPDF_CM,
                 CaptionType = CPDFCaptionType.CPDF_CAPTION_LENGTH | CPDFCaptionType.CPDF_CAPTION_AREA,
             };
-            pdfViewer.SetAnnotParam(polygonMeasureParam);
-            //    PolygonMeasureArgs polygonMeasureArgs = new PolygonMeasureArgs();
-            //    polygonMeasureArgs.LineColor = Colors.Red;
-            //    polygonMeasureArgs.LineWidth = 2;
-            //    polygonMeasureArgs.Transparency = 1;
-            //    polygonMeasureArgs.FontColor = Colors.Red;
-            //    polygonMeasureArgs.FillColor = Colors.Transparent;
-            //    polygonMeasureArgs.FontName = "Arial";
-            //    polygonMeasureArgs.FontSize = 14;
-            //    pdfViewer?.ClearSelectAnnots();
-            //    pdfViewer?.SetMouseMode(MouseModes.AnnotCreate);
-            //    pdfViewer?.SetToolParam(polygonMeasureArgs);
+            polygonMeasureParam.BorderStyle = C_BORDER_STYLE.BS_SOLID;
+            polygonMeasureParam.BorderEffector = null;
+            return polygonMeasureParam;
+        }
+
+        private AnnotParam CreatePolygonal()
+        {
+            pdfViewer.PDFViewTool.GetDefaultSettingParam().IsCreateSquarePolygonMeasure = false;
+            pdfViewer.SetToolType(ToolType.CreateAnnot);
+            pdfViewer.SetCreateAnnotType(C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON);
+            if(createPolygonMeasureParam == null)
+            {
+                createPolygonMeasureParam = CreatePolygonalParam();
+            }
+            pdfViewer.SetAnnotParam(createPolygonMeasureParam);
             measureControl.SetMeasureInfoType(CPDFMeasureType.CPDF_AREA_MEASURE);
             measureControl.SetInfoPanelVisble(true, false);
             var measureSetting = pdfViewer.PDFViewTool.GetMeasureSetting();
@@ -363,14 +361,11 @@ namespace ComPDFKit.Controls.PDFControl
                     measureSetting.RulerTranslate,
                     measureSetting.RulerTranslateUnit));
             //    return polygonMeasureArgs;
-            return polygonMeasureParam;
+            return createPolygonMeasureParam;
         }
 
-        private AnnotParam CreateRectangles()
+        private AnnotParam CreateRectangleParam()
         {
-            pdfViewer.PDFViewTool.GetDefaultSettingParam().IsCreateSquarePolygonMeasure = true;
-            pdfViewer.SetToolType(ToolType.CreateAnnot);
-            pdfViewer.SetCreateAnnotType(C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON);
             PolygonMeasureParam polygonMeasureParam = new PolygonMeasureParam();
             polygonMeasureParam.CurrentType = C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON;
             polygonMeasureParam.LineColor = new byte[] { 255, 0, 0, };
@@ -389,32 +384,22 @@ namespace ComPDFKit.Controls.PDFControl
                 RulerTranslateUnit = CPDFMeasure.CPDF_CM,
                 CaptionType = CPDFCaptionType.CPDF_CAPTION_LENGTH | CPDFCaptionType.CPDF_CAPTION_AREA,
             };
-            pdfViewer.SetAnnotParam(polygonMeasureParam);
-            measureControl.SetMeasureInfoType(CPDFMeasureType.CPDF_AREA_MEASURE);
-            //    PolygonMeasureArgs rectPolygonMeasureArgs = new PolygonMeasureArgs();
-            //    rectPolygonMeasureArgs.LineColor = Colors.Red;
-            //    rectPolygonMeasureArgs.IsOnlyDrawRect = true;
-            //    rectPolygonMeasureArgs.LineWidth = 2;
-            //    rectPolygonMeasureArgs.Transparency = 1;
-            //    rectPolygonMeasureArgs.FontColor = Colors.Red;
-            //    rectPolygonMeasureArgs.FillColor = Colors.Transparent;
-            //    rectPolygonMeasureArgs.FontName = "Arial";
-            //    rectPolygonMeasureArgs.FontSize = 14;
-            //    pdfViewer?.ClearSelectAnnots();
-            //    pdfViewer?.SetMouseMode(MouseModes.AnnotCreate);
-            //    pdfViewer?.SetToolParam(rectPolygonMeasureArgs);
-            //    measureControl.SetMeasureInfoType(CPDFMeasureType.CPDF_AREA_MEASURE);
-            //    measureControl.SetInfoPanelVisble(true, false);
-            //    measureControl.SetMeasureScale(CPDFMeasureType.CPDF_AREA_MEASURE,
-            //     string.Format("{0} {1} = {2} {3}",
-            //                 MeasureSetting.RulerBase,
-            //                 MeasureSetting.RulerBaseUnit,
-            //                 MeasureSetting.RulerTranslate,
-            //                 MeasureSetting.RulerTranslateUnit));
-            //    return rectPolygonMeasureArgs;
             return polygonMeasureParam;
         }
+        private AnnotParam CreateRectangles()
+        {
+            pdfViewer.PDFViewTool.GetDefaultSettingParam().IsCreateSquarePolygonMeasure = true;
+            pdfViewer.SetToolType(ToolType.CreateAnnot);
+            pdfViewer.SetCreateAnnotType(C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON);
+            if(createRectangleMeasureParam == null)
+            {
+                createPolygonMeasureParam = CreateRectangleParam();
+            } 
+            pdfViewer.SetAnnotParam(createPolygonMeasureParam);
+            measureControl.SetMeasureInfoType(CPDFMeasureType.CPDF_AREA_MEASURE);
+            return createPolygonMeasureParam;
+        }
 
-#endregion
+        #endregion
     }
 }

+ 532 - 0
Demo/Examples/Compdfkit.Controls/Common/BaseControl/MessageBoxEx.cs

@@ -0,0 +1,532 @@
+using System;
+using System.Windows.Forms;
+using System.Runtime.InteropServices;
+using ComPDFKit.Controls.Helper;
+
+namespace ComPDFKit.Controls.Common
+{
+    public class MessageBoxEx
+    {
+        private static string[] okstring = new string[] { LanguageHelper.CompressManager.GetString("Main_Ok")};
+        private static string[] ok = okstring;
+
+        private static string[] okcancelstring = new string[] { LanguageHelper.CompressManager.GetString("Main_Ok") , LanguageHelper.CompressManager.GetString("Main_Cancel")};
+        private static string[] okcancel = okcancelstring;
+
+        private static string[] abortretryignorestring = new string[] { LanguageHelper.CompressManager.GetString("Main_MenuHelp_About") , "Retry", "Ignore" };
+        private static string[] abortretryignore = abortretryignorestring;
+
+        private static string[] yesnocancelstring = new string[] { LanguageHelper.CompressManager.GetString("Main_Yes"), LanguageHelper.CompressManager.GetString("Main_No"), LanguageHelper.CompressManager.GetString("Main_Cancel") };
+        private static string[] yesnocancel = yesnocancelstring;
+
+        private static string[] yesnostring = new string[] { LanguageHelper.CompressManager.GetString("Main_Yes"), LanguageHelper.CompressManager.GetString("Main_No") };
+        private static string[] yesno = yesnostring;
+
+        private static string[] retrycancelstring = new string[] { "Retry", LanguageHelper.CompressManager.GetString("Main_Cancel") };
+        private static string[] retrycancel = retrycancelstring;
+
+        public static DialogResult Show(string text,string[] buttonTitles = null)
+        {
+            if(buttonTitles!=null&&buttonTitles.Length==1)
+            {
+                ok = buttonTitles;
+            }
+            else
+            {
+                ok = okstring;
+            }
+
+            myProc = new HookProc(OK);
+            SetHook();
+            DialogResult result = MessageBox.Show(text, Application.ProductName,MessageBoxButtons.OK);
+            
+            UnHook();
+
+            return result;
+        }
+
+        public static DialogResult Show(string text,string title,string[] buttonTitles = null)
+        {
+            if (buttonTitles != null && buttonTitles.Length == 1)
+            {
+                ok = buttonTitles;
+            }
+            else
+            {
+                ok = okstring;
+            }
+
+            myProc = new HookProc(OK);
+            SetHook();
+            DialogResult result = MessageBox.Show(text,title);
+            UnHook();
+
+            return result;
+        }
+
+        public static DialogResult Show(string text, string caption, MessageBoxButtons buttons, string[] buttonTitles=null)
+        {
+            switch (buttons)
+            {
+                case MessageBoxButtons.OK:
+                    if (buttonTitles != null && buttonTitles.Length == 1)
+                    {
+                        ok = buttonTitles;
+                    }
+                    else
+                    {
+                        ok = okstring;
+                    }
+                    myProc = new HookProc(OK);
+                    break;
+                case MessageBoxButtons.OKCancel:
+                    if (buttonTitles != null && buttonTitles.Length == 2)
+                    {
+                        okcancel = buttonTitles;
+                    }
+                    else
+                    {
+                        okcancel = okcancelstring;
+                    }
+                    myProc = new HookProc(OKCancel);
+                break;
+                case MessageBoxButtons.AbortRetryIgnore:
+                    if (buttonTitles != null && buttonTitles.Length == 3)
+                    {
+                        abortretryignore = buttonTitles;
+                    }
+                    else
+                    {
+                        abortretryignore = abortretryignorestring;
+                    }
+                    myProc = new HookProc(AbortRetryIgnore);
+                    break;
+                case MessageBoxButtons.YesNoCancel:
+                    if (buttonTitles != null && buttonTitles.Length == 3)
+                    {
+                        yesnocancel = buttonTitles;
+                    }
+                    else
+                    {
+                        yesnocancel = yesnocancelstring;
+                    }
+                    myProc = new HookProc(YesNoCancel);
+                    break;
+                case MessageBoxButtons.YesNo:
+                    if (buttonTitles != null && buttonTitles.Length == 2)
+                    {
+                        yesno = buttonTitles;
+                    }
+                    else
+                    {
+                        yesno = yesnostring;
+                    }
+                    myProc = new HookProc(YesNo);
+                    break;
+                case MessageBoxButtons.RetryCancel:
+                    if (buttonTitles != null && buttonTitles.Length == 2)
+                    {
+                        retrycancel = buttonTitles;
+                    }
+                    else
+                    {
+                        retrycancel = retrycancelstring;
+                    }
+                    myProc = new HookProc(RetryCancel);
+                    break;
+                default:
+                    break;
+            }
+
+            SetHook();
+            DialogResult result = MessageBox.Show(text, string.IsNullOrEmpty(caption)?Application.ProductName:caption, buttons);
+            UnHook();
+            return result;
+        }
+
+        public static DialogResult Show(string text, string caption, MessageBoxButtons buttons,MessageBoxIcon icons,string[] buttonTitles = null)
+        {
+            switch (buttons)
+            {
+                case MessageBoxButtons.OK:
+                    if (buttonTitles != null && buttonTitles.Length == 1)
+                    {
+                        ok = buttonTitles;
+                    }
+                    else
+                    {
+                        ok = okstring;
+                    }
+                    myProc = new HookProc(OK);
+                    break;
+                case MessageBoxButtons.OKCancel:
+                    if (buttonTitles != null && buttonTitles.Length == 2)
+                    {
+                        okcancel = buttonTitles;
+                    }
+                    else
+                    {
+                        okcancel = okcancelstring;
+                    }
+                    myProc = new HookProc(OKCancel);
+                    break;
+                case MessageBoxButtons.AbortRetryIgnore:
+                    if (buttonTitles != null && buttonTitles.Length == 3)
+                    {
+                        abortretryignore = buttonTitles;
+                    }
+                    else
+                    {
+                        abortretryignore = abortretryignorestring;
+                    }
+                    myProc = new HookProc(AbortRetryIgnore);
+                    break;
+                case MessageBoxButtons.YesNoCancel:
+                    if (buttonTitles != null && buttonTitles.Length == 3)
+                    {
+                        yesnocancel = buttonTitles;
+                    }
+                    else
+                    {
+                        yesnocancel = yesnocancelstring;
+                    }
+                    myProc = new HookProc(YesNoCancel);
+                    break;
+                case MessageBoxButtons.YesNo:
+                    if (buttonTitles != null && buttonTitles.Length == 2)
+                    {
+                        yesno = buttonTitles;
+                    }
+                    else
+                    {
+                        yesno = yesnostring;
+                    }
+                    myProc = new HookProc(YesNo);
+                    break;
+                case MessageBoxButtons.RetryCancel:
+                    if (buttonTitles != null && buttonTitles.Length == 2)
+                    {
+                        retrycancel = buttonTitles;
+                    }
+                    else
+                    {
+                        retrycancel = retrycancelstring;
+                    }
+                    myProc = new HookProc(RetryCancel);
+                    break;
+                default:
+                    break;
+            }
+            SetHook();
+            DialogResult result = MessageBox.Show(text, string.IsNullOrEmpty(caption) ? Application.ProductName : caption, buttons, icons);
+            UnHook();
+            return result;
+        }
+        
+        public static DialogResult Show(string text, string caption, MessageBoxButtons buttons,
+            MessageBoxIcon icon, MessageBoxDefaultButton defaultButton, string[] buttonTitles=null)
+        {
+            switch (buttons)
+            {
+                case MessageBoxButtons.OK:
+                    if (buttonTitles != null && buttonTitles.Length == 1)
+                    {
+                        ok = buttonTitles;
+                    }
+                    else
+                    {
+                        ok = okstring;
+                    }
+                    myProc = new HookProc(OK);
+                    break;
+                case MessageBoxButtons.OKCancel:
+                    if (buttonTitles != null && buttonTitles.Length == 2)
+                    {
+                        okcancel = buttonTitles;
+                    }
+                    else
+                    {
+                        okcancel = okcancelstring;
+                    }
+                    myProc = new HookProc(OKCancel);
+                    break;
+                case MessageBoxButtons.AbortRetryIgnore:
+                    if (buttonTitles != null && buttonTitles.Length == 3)
+                    {
+                        abortretryignore = buttonTitles;
+                    }
+                    else
+                    {
+                        abortretryignore = abortretryignorestring;
+                    }
+                    myProc = new HookProc(AbortRetryIgnore);
+                    break;
+                case MessageBoxButtons.YesNoCancel:
+                    if (buttonTitles != null && buttonTitles.Length == 3)
+                    {
+                        yesnocancel = buttonTitles;
+                    }
+                    else
+                    {
+                        yesnocancel = yesnocancelstring;
+                    }
+                    myProc = new HookProc(YesNoCancel);
+                    break;
+                case MessageBoxButtons.YesNo:
+                    if (buttonTitles != null && buttonTitles.Length == 2)
+                    {
+                        yesno = buttonTitles;
+                    }
+                    else
+                    {
+                        yesno = yesnostring;
+                    }
+                    myProc = new HookProc(YesNo);
+                    break;
+                case MessageBoxButtons.RetryCancel:
+                    if (buttonTitles != null && buttonTitles.Length == 2)
+                    {
+                        retrycancel = buttonTitles;
+                    }
+                    else
+                    {
+                        retrycancel = retrycancelstring;
+                    }
+                    myProc = new HookProc(RetryCancel);
+                    break;
+                default:
+                    break;
+            }
+
+            DialogResult result = MessageBox.Show(text, string.IsNullOrEmpty(caption) ? Application.ProductName : caption, buttons, icon, defaultButton);
+
+            return result;
+        }
+
+        public enum HookType
+        {
+            Keyboard = 2,
+            CBT = 5,
+            Mouse = 7, 
+        };
+
+        [DllImport("kernel32.dll")]
+        static extern int GetCurrentThreadId();
+        [DllImport("user32.dll")]
+        static extern int GetDlgItem(IntPtr hDlg, int nIDDlgItem);
+        [DllImport("user32", EntryPoint = "SetDlgItemText")]
+        static extern int SetDlgItemTextA(IntPtr hDlg, int nIDDlgItem, string lpString);
+
+        [DllImport("user32.dll", EntryPoint = "SetWindowTextW", CharSet = CharSet.Unicode)]
+        private static extern bool SetWindowText(IntPtr hWnd, string lpString);
+        [DllImport("user32.dll")]
+        static extern void UnhookWindowsHookEx(IntPtr handle);
+        [DllImport("user32.dll")]
+        static extern IntPtr SetWindowsHookEx(int idHook, [MarshalAs(UnmanagedType.FunctionPtr)] HookProc lpfn, IntPtr hInstance, int threadID);
+        [DllImport("user32.dll")]
+        static extern IntPtr CallNextHookEx(IntPtr handle, int code, IntPtr wparam, IntPtr lparam);
+
+
+        static IntPtr _nextHookPtr;
+        ////must be global, or it will be Collected by GC, then no callback func can be used for the Hook
+        static HookProc myProc = new HookProc(MyHookProc);
+
+        private delegate IntPtr HookProc(int code, IntPtr wparam, IntPtr lparam);
+
+        private static IntPtr OK(int code, IntPtr wparam, IntPtr lparam)
+        {
+            IntPtr hChildWnd;
+            if (code == 5)//HCBT_ACTIVATE = 5
+            {
+                hChildWnd = wparam;
+
+                var index = (IntPtr)GetDlgItem(hChildWnd,1);
+                if (index != IntPtr.Zero)
+                {
+                    SetWindowText(index, ok[0]);
+                }
+            }
+            else
+                CallNextHookEx(_nextHookPtr, code, wparam, lparam);
+
+            return IntPtr.Zero;
+        }
+
+        private static IntPtr OKCancel(int code, IntPtr wparam, IntPtr lparam)
+        {
+            IntPtr hChildWnd;
+            bool result = false;
+            if (code == 5)//HCBT_ACTIVATE = 5
+            {
+                hChildWnd = wparam;
+
+                IntPtr index = (IntPtr)GetDlgItem(hChildWnd, 1);
+                if (index != IntPtr.Zero)
+                {
+                   result = SetWindowText(index, okcancel[0]);
+                }
+                index = (IntPtr)GetDlgItem(hChildWnd, 2);
+                if (index != IntPtr.Zero)
+                {
+                    result = SetWindowText(index, okcancel[1]);
+                }
+            }
+            else
+                CallNextHookEx(_nextHookPtr, code, wparam, lparam);
+
+            return IntPtr.Zero;
+        }
+
+        private static IntPtr RetryCancel(int code, IntPtr wparam, IntPtr lparam)
+        {
+            IntPtr hChildWnd;
+            if (code == 5)//HCBT_ACTIVATE = 5
+            {
+                hChildWnd = wparam;
+
+                var index = (IntPtr)GetDlgItem(hChildWnd,4);
+                if (index!=IntPtr.Zero)
+                {
+                    SetWindowText(index, retrycancel[0]);
+                }
+                index = (IntPtr)GetDlgItem(hChildWnd, 2);
+                if (GetDlgItem(hChildWnd, 2) != 0)
+                {
+                    SetWindowText(index, retrycancel[1]);
+                }
+            }
+            else
+                CallNextHookEx(_nextHookPtr, code, wparam, lparam);
+            return IntPtr.Zero;
+        }
+
+        private static IntPtr YesNo(int code, IntPtr wparam, IntPtr lparam)
+        {
+            IntPtr hChildWnd;
+            if (code == 5)//HCBT_ACTIVATE = 5
+            {
+                hChildWnd = wparam;
+
+                var index = (IntPtr)GetDlgItem(hChildWnd, 6);
+                if (index!=IntPtr.Zero)
+                {
+                    SetWindowText(index, yesno[0]);
+                }
+                index = (IntPtr)GetDlgItem(hChildWnd, 7);
+                if (index != IntPtr.Zero)
+                {
+                    SetWindowText(index, yesno[1]);
+                }
+            }
+            else
+                CallNextHookEx(_nextHookPtr, code, wparam, lparam);
+            return IntPtr.Zero;
+        }
+        private static IntPtr YesNoCancel(int code, IntPtr wparam, IntPtr lparam)
+        {
+            IntPtr hChildWnd;
+            if (code == 5)//HCBT_ACTIVATE = 5
+            {
+                hChildWnd = wparam;
+
+                var index = (IntPtr)GetDlgItem(hChildWnd, 6);
+                if (index != IntPtr.Zero)
+                {
+                    SetWindowText(index,yesnocancel[0]);
+                }
+
+                index = (IntPtr)GetDlgItem(hChildWnd, 7);
+                if (index != IntPtr.Zero)
+                {
+                    SetWindowText(index, yesnocancel[1]);
+                }
+
+                index = (IntPtr)GetDlgItem(hChildWnd, 2);
+                if (index != IntPtr.Zero)
+                {
+                    SetWindowText(index, yesnocancel[2]);
+                }
+            }
+            else
+                CallNextHookEx(_nextHookPtr, code, wparam, lparam);
+            return IntPtr.Zero;
+        }
+
+        private static IntPtr AbortRetryIgnore(int code, IntPtr wparam, IntPtr lparam)
+        {
+            IntPtr hChildWnd;
+            if (code == 5)//HCBT_ACTIVATE = 5
+            {
+                hChildWnd = wparam;
+
+                var index = (IntPtr)GetDlgItem(hChildWnd, 3);
+                if (index != IntPtr.Zero)
+                {
+                    SetWindowText(index, abortretryignore[0]);
+                }
+
+                index = (IntPtr)GetDlgItem(hChildWnd, 4);
+                if (index != IntPtr.Zero)
+                {
+                    SetWindowText(index, abortretryignore[1]);
+                }
+
+                index = (IntPtr)GetDlgItem(hChildWnd, 5);
+                if (index != IntPtr.Zero)
+                {
+                    SetWindowText(index, abortretryignore[2]);
+                }
+            }
+            else
+                CallNextHookEx(_nextHookPtr, code, wparam, lparam);
+            return IntPtr.Zero;
+        }
+
+        private static IntPtr MyHookProc(int code, IntPtr wparam, IntPtr lparam)
+        {
+            IntPtr hChildWnd;// msgbox is "child"
+            // notification that a window is about to be activated
+            // window handle is wParam
+            if (code == 5)//HCBT_ACTIVATE = 5
+            {
+                // set window handles of messagebox
+                hChildWnd = wparam;
+                //to get the text of yes button
+
+                for(int i=0;i<21;i++)
+                {
+                    if (GetDlgItem(hChildWnd, i) != 0)
+                        SetDlgItemTextA(hChildWnd,i,string.Format("Item {0}",i));
+                }
+            }
+            else
+            {
+                CallNextHookEx(_nextHookPtr, code, wparam, lparam);// otherwise, continue with any possible chained hooks
+            }
+
+            return IntPtr.Zero;
+        }
+
+        public static void SetHook()
+        {
+            try
+            {
+                if (_nextHookPtr != IntPtr.Zero)//Hooked already
+                {
+                    return;
+                }
+                _nextHookPtr = SetWindowsHookEx((int)HookType.CBT, myProc, IntPtr.Zero, GetCurrentThreadId());
+            }
+            catch { }
+        }
+
+        public static  void UnHook()
+        {
+            if (_nextHookPtr != IntPtr.Zero)
+            {
+                UnhookWindowsHookEx(_nextHookPtr);
+                _nextHookPtr = IntPtr.Zero;
+            }
+        }
+    }
+}

+ 67 - 2
Demo/Examples/Compdfkit.Controls/Common/Helper/CommonHelper.cs

@@ -59,6 +59,15 @@ namespace ComPDFKit.Controls.Helper
 
     public static class CommonHelper
     {
+        [DllImport("shell32.dll", ExactSpelling = true)]
+        private static extern void ILFree(IntPtr pidlList);
+
+        [DllImport("shell32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
+        private static extern IntPtr ILCreateFromPathW(string pszPath);
+
+        [DllImport("shell32.dll", ExactSpelling = true)]
+        private static extern int SHOpenFolderAndSelectItems(IntPtr pidlList, uint cild, IntPtr children, uint dwFlags);
+
         public static bool IsImageCorrupted(string imagePath)
         {
             try
@@ -116,8 +125,6 @@ namespace ComPDFKit.Controls.Helper
             }
         }
 
-
-
         public static int GetBitmapPointer(Bitmap bitmap)
         {
             IntPtr hBitmap = bitmap.GetHbitmap();
@@ -366,6 +373,64 @@ namespace ComPDFKit.Controls.Helper
             }
         }
 
+        public static string CreateFilePath(string path)
+        {
+            int i = 1;
+            string oldDestName = path;
+            do
+            {
+                if (File.Exists(path))
+                {
+                    int lastDot = oldDestName.LastIndexOf('.');
+
+                    string fileExtension = string.Empty;
+
+                    string fileName = oldDestName;
+
+                    if (lastDot > 0)
+                    {
+                        fileExtension = fileName.Substring(lastDot);
+
+                        fileName = fileName.Substring(0, lastDot);
+                    }
+
+                    path = fileName + string.Format(@"({0})", i) + fileExtension;
+                }
+
+                ++i;
+            } while (File.Exists(path));
+
+            return path;
+        }
+
+        public static void ExplorerFile(string filePath)
+        {
+            try
+            {
+                if (!File.Exists(filePath) && !Directory.Exists(filePath))
+                    return;
+
+                if (Directory.Exists(filePath))
+                    Process.Start(@"explorer.exe", "/select,\"" + filePath + "\"");
+                else
+                {
+                    IntPtr pidlList = ILCreateFromPathW(filePath);
+                    if (pidlList != IntPtr.Zero)
+                    {
+                        try
+                        {
+                            Marshal.ThrowExceptionForHR(SHOpenFolderAndSelectItems(pidlList, 0, IntPtr.Zero, 0));
+                        }
+                        finally
+                        {
+                            ILFree(pidlList);
+                        }
+                    }
+                }
+            }
+            catch { }
+        }
+
         internal static class PageEditHelper
         {
             public static T FindVisualParent<T>(DependencyObject obj) where T : class

+ 1 - 0
Demo/Examples/Compdfkit.Controls/Common/Helper/LanguageHelper.cs

@@ -13,5 +13,6 @@ namespace ComPDFKit.Controls.Helper
         public static ResourceManager DocInfoManager= new ResourceManager("ComPDFKit.Controls.Strings.DocInfo", Assembly.GetExecutingAssembly());
         public static ResourceManager SecurityManager= new ResourceManager("ComPDFKit.Controls.Strings.Security", Assembly.GetExecutingAssembly());
         public static ResourceManager DocEditorManager= new ResourceManager("ComPDFKit.Controls.Strings.DocEditor", Assembly.GetExecutingAssembly());
+        public static ResourceManager CompressManager = new ResourceManager("ComPDFKit.Controls.Strings.Compress", Assembly.GetExecutingAssembly());
     }
 }

+ 8 - 2
Demo/Examples/Compdfkit.Controls/Common/HomePage/HomePageControl.xaml.cs

@@ -13,6 +13,7 @@ using System.Windows.Media;
 using System.Windows.Media.Imaging;
 using System.Windows.Navigation;
 using System.Windows.Shapes;
+using ComPDFKit.Controls.Compress;
 using ComPDFKit.Controls.Helper;
 using Path = System.Windows.Shapes.Path;
 
@@ -159,7 +160,11 @@ namespace ComPDFKit.Controls.PDFControl
                     }
                 case "Compress":
                     {
-                        System.Diagnostics.Process.Start("https://www.compdf.com/contact-sales");
+                        CompressDialog compressDialog = new CompressDialog()
+                        {
+                            Owner = parentWindow
+                        };
+                        compressDialog.ShowDialog();
                         break;
                     }
                 case "Measurement":
@@ -167,6 +172,7 @@ namespace ComPDFKit.Controls.PDFControl
                         OpenFileEvent?.Invoke(this, new OpenFileEventArgs(FileOperationType.OpenFileDirectly, MeasurementFileName, e.Feature));
                         break;
                     }
+
                 default: 
                     break;
             }
@@ -192,6 +198,7 @@ namespace ComPDFKit.Controls.PDFControl
         {
             customItems = new List<CustomItem>()
             {
+                new CustomItem{ IconCanvas = compressCanvas,TitleText = LanguageHelper.CommonManager.GetString("Func_Compress"), DescriptionText= LanguageHelper.CommonManager.GetString("FuncDetail_Compress"), Feature = "Compress"},
                 new CustomItem{ IconCanvas = viewerCanvas,TitleText = LanguageHelper.CommonManager.GetString("Func_Viewer"), DescriptionText= LanguageHelper.CommonManager.GetString("FuncDetail_Viewer"), Feature = "Viewer"},
                 new CustomItem{ IconCanvas = annotationsCanvas,TitleText = LanguageHelper.CommonManager.GetString("Func_Annotations"), DescriptionText= LanguageHelper.CommonManager.GetString("FuncDetail_Annotations"), Feature = "Annotations"},
                 new CustomItem{ IconCanvas = formsCanvas,TitleText = LanguageHelper.CommonManager.GetString("Func_Forms"), DescriptionText= LanguageHelper.CommonManager.GetString("FuncDetail_Forms"), Feature = "Forms"},
@@ -203,7 +210,6 @@ namespace ComPDFKit.Controls.PDFControl
                 new CustomItem{ IconCanvas = redactionCanvas,TitleText = LanguageHelper.CommonManager.GetString("Func_Redaction"), DescriptionText= LanguageHelper.CommonManager.GetString("FuncDetail_Redaction"), Feature = "Redaction"},
                 new CustomItem{ IconCanvas = compareDocumentsCanvas,TitleText = LanguageHelper.CommonManager.GetString("Func_DocCompare"), DescriptionText= LanguageHelper.CommonManager.GetString("FuncDetail_DocCompare"), Feature = "Compare Documents"},
                 new CustomItem{ IconCanvas = conversionCanvas,TitleText = LanguageHelper.CommonManager.GetString("Func_Conversion"), DescriptionText= LanguageHelper.CommonManager.GetString("FuncDetail_Conversion"), Feature = "Conversion"},
-                new CustomItem{ IconCanvas = compressCanvas,TitleText = LanguageHelper.CommonManager.GetString("Func_Compress"), DescriptionText= LanguageHelper.CommonManager.GetString("FuncDetail_Compress"), Feature = "Compress"},
                 new CustomItem{ IconCanvas = measurementCanvas,TitleText = LanguageHelper.CommonManager.GetString("Func_Measurement"), DescriptionText= LanguageHelper.CommonManager.GetString("FuncDetail_Measurement"), Feature = "Measurement"},
             };
         }

+ 4 - 0
Demo/Examples/Compdfkit.Controls/Common/PasswordControl/PasswordWindow.xaml.cs

@@ -23,6 +23,8 @@ namespace ComPDFKit.Controls.Common
         public delegate void DialogCloseEventHandler(object sender, PasswordEventArgs e);
         public event DialogCloseEventHandler DialogClosed;
 
+        public string Password { get; private set; }
+
         public PasswordWindow()
         {
             InitializeComponent();
@@ -67,6 +69,7 @@ namespace ComPDFKit.Controls.Common
                     if (pdfDoc.IsLocked == false)
                     {
                         PasswordEventArgs passwordEventArgs = new PasswordEventArgs(e);
+                        Password = e;
                         CloseWindow(passwordEventArgs);
                     }
                     else
@@ -81,6 +84,7 @@ namespace ComPDFKit.Controls.Common
                         if(pdfDoc.CheckOwnerPassword(e))
                         {
                             PasswordEventArgs passwordEventArgs = new PasswordEventArgs(e);
+                            Password = e;
                             CloseWindow(passwordEventArgs);
                         }
                         else

+ 2 - 3
Demo/Examples/Compdfkit.Controls/Common/PropertyControl/ColorPickerControl.xaml.cs

@@ -25,8 +25,7 @@ namespace ComPDFKit.Controls.Common
         // Using a DependencyProperty as the backing store for TransparentBtnProperty.  This enables animation, styling, binding, etc...
         public static readonly DependencyProperty TransparentBtnPropertyProperty =
             DependencyProperty.Register("TransparentBtnProperty", typeof(Visibility), typeof(ColorPickerControl), new PropertyMetadata(Visibility.Visible));
-
-
+         
         public void SetIsChecked(int index)
         {
             switch (index)
@@ -97,7 +96,7 @@ namespace ComPDFKit.Controls.Common
 
         public bool GetTransparentBtnVisibility()
         {
-            if (TransparentBtn.Visibility == Visibility.Visible)
+            if (TransparentBtnProperty == Visibility.Visible)
             {
                 return true;
             }

+ 116 - 0
Demo/Examples/Compdfkit.Controls/Common/PropertyControl/PDFLineStyle/CPDFCloudStyleControl.xaml

@@ -0,0 +1,116 @@
+<UserControl x:Class="ComPDFKit.Controls.Common.CPDFCloudStyleControl"
+             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.Common"
+             mc:Ignorable="d" 
+             d:DesignHeight="80" d:DesignWidth="260">
+    <UserControl.Resources>
+        <Style x:Key="LineRadioButton" TargetType="{x:Type RadioButton}">
+            <Setter Property="HorizontalAlignment" Value="Left"></Setter>
+            <Setter Property="VerticalAlignment" Value="Center"></Setter>
+            <Setter Property="Height" Value="20"></Setter>
+            <Setter Property="Width" Value="200"></Setter>
+            <Setter Property="Template">
+                <Setter.Value>
+                    <ControlTemplate TargetType="{x:Type RadioButton}">
+                        <Grid>
+                            <Grid.ColumnDefinitions>
+                                <ColumnDefinition Width="20"></ColumnDefinition>
+                                <ColumnDefinition></ColumnDefinition>
+                            </Grid.ColumnDefinitions>
+                            <Grid Grid.Column="0">
+                                <Border x:Name="BackgroundBorder" CornerRadius="20" BorderThickness="2" BorderBrush="#000000" Background="Transparent">
+                                    <Ellipse Name="CheckedEllipse" Height="10" Width="10" Fill="#000000" Visibility="Collapsed"></Ellipse>
+                                </Border>
+                            </Grid>
+                            <ContentPresenter Grid.Column="1"/>
+                        </Grid>
+                        <ControlTemplate.Triggers>
+                            <Trigger Property="IsMouseOver" Value="True">
+                                <Setter TargetName="BackgroundBorder" Property="BorderBrush" Value="#477EDE"></Setter>
+                            </Trigger>
+
+                            <Trigger Property="IsPressed" Value="True">
+                                <Setter TargetName="BackgroundBorder" Property="BorderBrush" Value="#477EDE"></Setter>
+                                <Setter TargetName="BackgroundBorder" Property="Background" Value="#87CEFA"></Setter>
+                            </Trigger>
+
+                            <Trigger Property="IsChecked" Value="True">
+                                <Setter TargetName="CheckedEllipse" Property="Visibility" Value="Visible"></Setter>
+                            </Trigger>
+                        </ControlTemplate.Triggers>
+                    </ControlTemplate>
+                </Setter.Value>
+            </Setter>
+        </Style>
+    </UserControl.Resources>
+    <StackPanel  Margin="16,0,0,0" VerticalAlignment="Center">
+        <RadioButton x:Name="rdoStreat" Tag="Streat" GroupName="Shape"  Style="{StaticResource LineRadioButton}" Checked="rdoShape_Checked">
+            <Rectangle Fill="Black" Height="2" Width="90" HorizontalAlignment="Left"  Margin="5,0,0,0"></Rectangle>
+        </RadioButton>
+        <RadioButton x:Name="rdoCloud1" GroupName="Shape" IsChecked="True" Style="{StaticResource LineRadioButton}" Tag="Cloud1" Margin="0,6,0,6" Checked="rdoShape_Checked">
+            <Canvas VerticalAlignment="Center">
+                <Path Stroke="Black" StrokeThickness="2">
+                    <Path.Data>
+                        <PathGeometry>
+                            <PathFigure StartPoint="20,0">
+                                <ArcSegment Point="6,0" Size="3,3" SweepDirection="Counterclockwise"/>
+                            </PathFigure>
+                            <PathFigure StartPoint="34,0">
+                                <ArcSegment Point="20,0" Size="3,3" SweepDirection="Counterclockwise"/>
+                            </PathFigure>
+                            <PathFigure StartPoint="48,0">
+                                <ArcSegment Point="34,0" Size="3,3" SweepDirection="Counterclockwise"/>
+                            </PathFigure>
+                            <PathFigure StartPoint="62,0">
+                                <ArcSegment Point="48,0" Size="3,3" SweepDirection="Counterclockwise"/>
+                            </PathFigure>
+                            <PathFigure StartPoint="76,0">
+                                <ArcSegment Point="62,0" Size="3,3" SweepDirection="Counterclockwise"/>
+                            </PathFigure>
+                            <PathFigure StartPoint="90,0">
+                                <ArcSegment Point="76,0" Size="3,3" SweepDirection="Counterclockwise"/>
+                            </PathFigure>
+                        </PathGeometry>
+                    </Path.Data>
+                </Path>
+            </Canvas>
+        </RadioButton>
+        <RadioButton x:Name="rdoCloud2" Tag="Cloud2" GroupName="Shape" Style="{StaticResource LineRadioButton}" Checked="rdoShape_Checked">
+            <Canvas VerticalAlignment="Center">
+                <Path Stroke="Black" StrokeThickness="2" Margin="-5,0,0,0">
+                    <Path.Data> 
+                        <PathGeometry>
+                            <PathFigure StartPoint="20,0">
+                                <ArcSegment Point="10,0" Size="2,2" SweepDirection="Counterclockwise"/>
+                            </PathFigure>
+                            <PathFigure StartPoint="30,0">
+                                <ArcSegment Point="20,0" Size="2,2" SweepDirection="Counterclockwise"/>
+                            </PathFigure>
+                            <PathFigure StartPoint="40,0">
+                                <ArcSegment Point="30,0" Size="2,2" SweepDirection="Counterclockwise"/>
+                            </PathFigure>
+                            <PathFigure StartPoint="50,0">
+                                <ArcSegment Point="40,0" Size="2,2" SweepDirection="Counterclockwise"/>
+                            </PathFigure>
+                            <PathFigure StartPoint="60,0">
+                                <ArcSegment Point="50,0" Size="2,2" SweepDirection="Counterclockwise"/>
+                            </PathFigure>
+                            <PathFigure StartPoint="70,0">
+                                <ArcSegment Point="60,0" Size="2,2" SweepDirection="Counterclockwise"/>
+                            </PathFigure>
+                            <PathFigure StartPoint="80,0">
+                                <ArcSegment Point="70,0" Size="2,2" SweepDirection="Counterclockwise"/>
+                            </PathFigure>
+                            <PathFigure StartPoint="90,0">
+                                <ArcSegment Point="80,0" Size="2,2" SweepDirection="Counterclockwise"/>
+                            </PathFigure>
+                        </PathGeometry>
+                    </Path.Data>
+                </Path>
+            </Canvas>
+        </RadioButton>
+    </StackPanel>
+</UserControl>

+ 102 - 0
Demo/Examples/Compdfkit.Controls/Common/PropertyControl/PDFLineStyle/CPDFCloudStyleControl.xaml.cs

@@ -0,0 +1,102 @@
+using ComPDFKit.PDFAnnotation;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+
+namespace ComPDFKit.Controls.Common
+{
+    /// <summary>
+    /// Interaction logic for CPDFCloudStyleControl.xaml
+    /// </summary>
+    public partial class CPDFCloudStyleControl : UserControl
+    {
+        private const string streat = "Streat";
+        private const string cloud1 = "Cloud1";
+        private const string cloud2 = "Cloud2";
+
+        private bool isChecked = false;
+
+        public event EventHandler<CPDFBorderEffector> LineShapeChanged;
+
+        private CPDFBorderEffector _borderEffector = new CPDFBorderEffector(C_BORDER_TYPE.C_BORDER_TYPE_Cloud, C_BORDER_INTENSITY.C_INTENSITY_TWO);
+        public CPDFBorderEffector BorderEffector
+        {
+            get
+            {
+                return _borderEffector;
+            }
+            set
+            {
+                _borderEffector = value;
+                  
+                rdoStreat.Checked -= rdoShape_Checked;
+                rdoCloud1.Checked -= rdoShape_Checked;
+                rdoCloud2.Checked -= rdoShape_Checked;
+
+                if (_borderEffector == null)
+                {
+                    rdoStreat.IsChecked = true;
+                }
+                else if (_borderEffector.BorderType == C_BORDER_TYPE.C_BORDER_TYPE_Cloud)
+                {
+                    if (_borderEffector.BorderIntensity == C_BORDER_INTENSITY.C_INTENSITY_TWO)
+                    {
+                        rdoCloud1.IsChecked = true;
+                    }
+                    else if (_borderEffector.BorderIntensity == C_BORDER_INTENSITY.C_INTENSITY_ONE)
+                    {
+                        rdoCloud2.IsChecked = true;
+                    }
+                    else
+                    {
+                        rdoStreat.IsChecked = true;
+                    }
+                }
+                else
+                {
+                    rdoStreat.IsChecked = true;
+                }
+
+                // 恢复事件处理程序
+                rdoStreat.Checked += rdoShape_Checked;
+                rdoCloud1.Checked += rdoShape_Checked;
+                rdoCloud2.Checked += rdoShape_Checked;
+            }
+        }
+
+        public CPDFCloudStyleControl()
+        {
+            DataContext = this;
+            InitializeComponent();
+        }
+
+        private void rdoShape_Checked(object sender, RoutedEventArgs e)
+        {
+            switch ((sender as RadioButton).Tag)
+            {
+                case streat:
+                    BorderEffector = new CPDFBorderEffector(C_BORDER_TYPE.C_BORDER_TYPE_STRAIGHT, C_BORDER_INTENSITY.C_INTENSITY_ZERO);
+                    break;
+                case cloud1:
+                    BorderEffector = new CPDFBorderEffector(C_BORDER_TYPE.C_BORDER_TYPE_Cloud, C_BORDER_INTENSITY.C_INTENSITY_TWO);
+                    break;
+                case cloud2:
+                    BorderEffector = new CPDFBorderEffector(C_BORDER_TYPE.C_BORDER_TYPE_Cloud, C_BORDER_INTENSITY.C_INTENSITY_ONE);
+                    break;
+            }
+            LineShapeChanged?.Invoke(this, BorderEffector);
+        }
+    }
+}

+ 61 - 0
Demo/Examples/Compdfkit.Controls/Compdfkit.Controls.csproj

@@ -87,6 +87,12 @@
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <ItemGroup>
+    <Reference Include="Microsoft.WindowsAPICodePack, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\WindowsAPICodePack-Core.1.1.1\lib\Microsoft.WindowsAPICodePack.dll</HintPath>
+    </Reference>
+    <Reference Include="Microsoft.WindowsAPICodePack.Shell, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
+      <HintPath>..\packages\WindowsAPICodePack-Shell.1.1.1\lib\Microsoft.WindowsAPICodePack.Shell.dll</HintPath>
+    </Reference>
     <Reference Include="Nager.Country, Version=4.0.0.0, Culture=neutral, processorArchitecture=MSIL">
       <HintPath>..\packages\Nager.Country.4.0.0\lib\netstandard2.0\Nager.Country.dll</HintPath>
     </Reference>
@@ -135,6 +141,9 @@
     <Compile Include="Annotation\PDFAnnotationList\PDFAnnotationListUI\ReplyStatusControl.xaml.cs">
       <DependentUpon>ReplyStatusControl.xaml</DependentUpon>
     </Compile>
+    <Compile Include="Annotation\PDFAnnotationPanel\PDFAnnotationUI\CPDFCloudUI.xaml.cs">
+      <DependentUpon>CPDFCloudUI.xaml</DependentUpon>
+    </Compile>
     <Compile Include="Annotation\PDFAnnotationPanel\PDFAnnotationUI\CPDFFreehandUI.xaml.cs">
       <DependentUpon>CPDFFreehandUI.xaml</DependentUpon>
     </Compile>
@@ -173,6 +182,7 @@
     <Compile Include="Common\BaseControl\MatrixRadioControl.xaml.cs">
       <DependentUpon>MatrixRadioControl.xaml</DependentUpon>
     </Compile>
+    <Compile Include="Common\BaseControl\MessageBoxEx.cs" />
     <Compile Include="Common\BaseControl\PageNumberControl.xaml.cs">
       <DependentUpon>PageNumberControl.xaml</DependentUpon>
     </Compile>
@@ -280,6 +290,9 @@
     <Compile Include="Common\PropertyControl\PDFFont\CPDFFontUI.xaml.cs">
       <DependentUpon>CPDFFontUI.xaml</DependentUpon>
     </Compile>
+    <Compile Include="Common\PropertyControl\PDFLineStyle\CPDFCloudStyleControl.xaml.cs">
+      <DependentUpon>CPDFCloudStyleControl.xaml</DependentUpon>
+    </Compile>
     <Compile Include="Common\PropertyControl\PDFLocation\CPDFLocationControl.xaml.cs">
       <DependentUpon>CPDFLocationControl.xaml</DependentUpon>
     </Compile>
@@ -310,6 +323,9 @@
     <Compile Include="Common\PropertyControl\WritableComboBoxControl.xaml.cs">
       <DependentUpon>WritableComboBoxControl.xaml</DependentUpon>
     </Compile>
+    <Compile Include="Compress\CompressDialog.xaml.cs">
+      <DependentUpon>CompressDialog.xaml</DependentUpon>
+    </Compile>
     <Compile Include="DigitalSignature\AddCertificationControl\AddCertificationControl.xaml.cs">
       <DependentUpon>AddCertificationControl.xaml</DependentUpon>
     </Compile>
@@ -383,6 +399,12 @@
     <Compile Include="Edit\PDFImageEdit\PDFImageUI\CPDFImageRotateUI.xaml.cs">
       <DependentUpon>CPDFImageRotateUI.xaml</DependentUpon>
     </Compile>
+    <Compile Include="Edit\PDFPathEdit\PDFPathEditControl\PDFPathEditControl.xaml.cs">
+      <DependentUpon>PDFPathEditControl.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="Edit\PDFTextEdit\PDFTextEditUI\CPDFTextMarkupUI.xaml.cs">
+      <DependentUpon>CPDFTextMarkupUI.xaml</DependentUpon>
+    </Compile>
     <Compile Include="Edit\PDFTextEdit\PDFTextEditControl\PDFTextEditControl.xaml.cs">
       <DependentUpon>PDFTextEditControl.xaml</DependentUpon>
     </Compile>
@@ -567,6 +589,14 @@
     <Compile Include="PDFView\PDFScaling\PDFScalingUI\CPDFScalingUI.xaml.cs">
       <DependentUpon>CPDFScalingUI.xaml</DependentUpon>
     </Compile>
+    <Compile Include="Snapshot\SnapshotMenu.xaml.cs">
+      <DependentUpon>SnapshotMenu.xaml</DependentUpon>
+    </Compile>
+    <Compile Include="Strings\Compress.Designer.cs">
+      <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
+      <DependentUpon>Compress.resx</DependentUpon>
+    </Compile>
     <Compile Include="Watermark\AddWatermark\FileGridListWithPageRangeControl.xaml.cs">
       <DependentUpon>FileGridListWithPageRangeControl.xaml</DependentUpon>
     </Compile>
@@ -651,6 +681,13 @@
     <EmbeddedResource Include="Strings\Common.zh.resx">
       <DependentUpon>Common.resx</DependentUpon>
     </EmbeddedResource>
+    <EmbeddedResource Include="Strings\Compress.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Compress.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+    <EmbeddedResource Include="Strings\Compress.zh.resx">
+      <DependentUpon>Compress.resx</DependentUpon>
+    </EmbeddedResource>
     <EmbeddedResource Include="Strings\DocEditor.resx">
       <Generator>ResXFileCodeGenerator</Generator>
       <LastGenOutput>DocEditor.Designer.cs</LastGenOutput>
@@ -781,6 +818,10 @@
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
     </Page>
+    <Page Include="Annotation\PDFAnnotationPanel\PDFAnnotationUI\CPDFCloudUI.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
     <Page Include="Annotation\PDFAnnotationPanel\PDFAnnotationUI\CPDFFreehandUI.xaml">
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
@@ -976,6 +1017,10 @@
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
     </Page>
+    <Page Include="Common\PropertyControl\PDFLineStyle\CPDFCloudStyleControl.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
     <Page Include="Common\PropertyControl\PDFLocation\CPDFLocationControl.xaml">
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
@@ -1016,6 +1061,10 @@
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
     </Page>
+    <Page Include="Compress\CompressDialog.xaml">
+      <Generator>MSBuild:Compile</Generator>
+      <SubType>Designer</SubType>
+    </Page>
     <Page Include="DigitalSignature\AddCertificationControl\AddCertificationControl.xaml">
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
@@ -1097,6 +1146,14 @@
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
     </Page>
+    <Page Include="Edit\PDFPathEdit\PDFPathEditControl\PDFPathEditControl.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
+    <Page Include="Edit\PDFTextEdit\PDFTextEditUI\CPDFTextMarkupUI.xaml">
+      <SubType>Designer</SubType>
+      <Generator>MSBuild:Compile</Generator>
+    </Page>
     <Page Include="Edit\PDFTextEdit\PDFTextEditControl\PDFTextEditControl.xaml">
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>
@@ -1303,6 +1360,10 @@
       <Generator>MSBuild:Compile</Generator>
     </Page>
     <Page Include="PDFView\RegularViewerControl.xaml" />
+    <Page Include="Snapshot\SnapshotMenu.xaml">
+      <Generator>MSBuild:Compile</Generator>
+      <SubType>Designer</SubType>
+    </Page>
     <Page Include="Watermark\AddWatermark\FileGridListWithPageRangeControl.xaml">
       <SubType>Designer</SubType>
       <Generator>MSBuild:Compile</Generator>

+ 447 - 0
Demo/Examples/Compdfkit.Controls/Compress/CompressDialog.xaml

@@ -0,0 +1,447 @@
+<Window x:Class="ComPDFKit.Controls.Compress.CompressDialog"
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+        xmlns:local="clr-namespace:ComPDFKit.Controls.Compress"
+        mc:Ignorable="d"
+        Title="CompressWPFDialog" Height="450" Width="890" ResizeMode="NoResize"
+        ShowInTaskbar="False"
+        WindowStartupLocation="CenterOwner"
+        WindowStyle="SingleBorderWindow">
+	<Window.Resources>
+		<ResourceDictionary>
+			<local:MaxWidthToTextTrimmingConverter x:Key="MaxWidthToTextTrimmingConverter" />
+			<Style x:Key="LeftAlignedHeaderStyle" TargetType="{x:Type GridViewColumnHeader}">
+				<Setter Property="HorizontalContentAlignment" Value="Left" />
+			</Style>
+            
+            <Style x:Key="DisabledButtonStyle" TargetType="{x:Type Button}">
+                <Setter Property="BorderThickness" Value="1" />
+                <Setter Property="Padding" Value="5" />
+                <Setter Property="Width" Value="100" />
+                <Setter Property="Height" Value="40" />
+                <Style.Triggers>
+                    <Trigger Property="IsEnabled" Value="False">
+                        <Setter Property="Foreground" Value="Gray" />
+                    </Trigger>
+                </Style.Triggers>
+            </Style>
+            
+			<Style x:Key="ResizableGridViewColumnHeaderStyle" TargetType="{x:Type GridViewColumnHeader}">
+				<Setter Property="Template">
+					<Setter.Value>
+						<ControlTemplate TargetType="GridViewColumnHeader">
+							<Grid x:Name="Root" Background="Transparent">
+								<Grid.ColumnDefinitions>
+									<ColumnDefinition Width="*" />
+									<ColumnDefinition Width="Auto" />
+								</Grid.ColumnDefinitions>
+								<ContentPresenter Grid.Column="0" VerticalAlignment="Center" />
+								<Thumb
+                                 x:Name="PART_HeaderGripper"
+                                 Grid.Column="1"
+                                 Width="5"
+                                 HorizontalAlignment="Right"
+                                 Cursor="SizeWE"
+                                 DragDelta="PART_HeaderGripper_DragDelta" />
+							</Grid>
+						</ControlTemplate>
+					</Setter.Value>
+				</Setter>
+			</Style>
+            
+			<Style x:Key="RoundButtonStyle" TargetType="{x:Type Button}">
+				<Setter Property="Background" Value="White" />
+				<Setter Property="BorderBrush" Value="Black" />
+				<Setter Property="BorderThickness" Value="1" />
+				<Setter Property="Padding" Value="5" />
+				<Setter Property="Margin" Value="12,8" />
+				<Setter Property="Width" Value="100" />
+				<Setter Property="Height" Value="40" />
+				<Setter Property="Template">
+					<Setter.Value>
+						<ControlTemplate TargetType="{x:Type Button}">
+							<Border
+                             x:Name="border"
+                             Background="{TemplateBinding Background}"
+                             BorderBrush="{TemplateBinding BorderBrush}"
+                             BorderThickness="{TemplateBinding BorderThickness}"
+                             CornerRadius="0">
+								<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
+							</Border>
+							<ControlTemplate.Triggers>
+								<Trigger Property="IsPressed" Value="True">
+									<Setter TargetName="border" Property="Background" Value="White" />
+									<Setter TargetName="border" Property="BorderBrush" Value="LightGray" />
+								</Trigger>
+								<Trigger Property="IsEnabled" Value="False">
+									<Setter TargetName="border" Property="Opacity" Value="0.5" />
+								</Trigger>
+							</ControlTemplate.Triggers>
+						</ControlTemplate>
+					</Setter.Value>
+				</Setter>
+			</Style>
+
+			<Style x:Key="HeadStyle" TargetType="{x:Type GridViewColumnHeader}">
+				<Setter Property="OverridesDefaultStyle" Value="False" />
+				<Setter Property="HorizontalContentAlignment" Value="Left" />
+
+				<Setter Property="FontSize" Value="14" />
+				<Setter Property="Template">
+					<Setter.Value>
+						<ControlTemplate TargetType="{x:Type GridViewColumnHeader}">
+							<Grid Name="g" Background="Transparent">
+								<Border Name="bd" Padding="{TemplateBinding Padding}">
+									<Grid>
+										<!--  Gripper 控件  -->
+										<Thumb
+                                         x:Name="PART_HeaderGripper"
+                                         Width="5"
+                                         HorizontalAlignment="Right"
+                                         Background="White"
+                                         BorderBrush="LightGray"
+                                         Cursor="SizeWE"
+                                         Visibility="Collapsed" />
+										<ContentPresenter Margin="5,3,0,3" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" />
+									</Grid>
+								</Border>
+							</Grid>
+							<ControlTemplate.Triggers>
+								<Trigger Property="IsMouseOver" Value="True">
+									<Setter TargetName="g" Property="Background" Value="LightGray" />
+									<Setter TargetName="g" Property="Opacity" Value="0.7" />
+									<Setter TargetName="PART_HeaderGripper" Property="Visibility" Value="Visible" />
+									<Setter TargetName="PART_HeaderGripper" Property="Background" Value="LightGray" />
+									<Setter TargetName="PART_HeaderGripper" Property="Opacity" Value="0.5" />
+								</Trigger>
+							</ControlTemplate.Triggers>
+						</ControlTemplate>
+					</Setter.Value>
+				</Setter>
+			</Style>
+            
+            <Style x:Key="ListViewItemStyle" TargetType="{x:Type ListViewItem}">
+                <Style.Setters>
+                    <Setter Property="HorizontalAlignment" Value="Stretch" />
+                    <Setter Property="SnapsToDevicePixels" Value="True" />
+                    <Setter Property="Foreground" Value="Black" />
+                    <Setter Property="Template">
+                        <Setter.Value>
+                            <ControlTemplate TargetType="{x:Type ListViewItem}">
+                                <Border
+                        x:Name="bd"
+                        Padding="{TemplateBinding Padding}"
+                        BorderBrush="LightGray"
+                                    Background="Transparent"
+                        BorderThickness="1"
+                        SnapsToDevicePixels="True">
+                                    <GridViewRowPresenter
+                            Margin="0,2"
+                            Columns="{TemplateBinding GridView.ColumnCollection}"
+                            Content="{TemplateBinding Content}" />
+                                </Border>
+                                <ControlTemplate.Triggers>
+                                    <Trigger Property="IsSelected" Value="True">
+                                        <Trigger.Setters>
+                                            <Setter TargetName="bd" Property="Background" Value="LightGray" />
+                                            <Setter TargetName="bd" Property="Opacity" Value="0.8" />
+                                        </Trigger.Setters>
+                                    </Trigger>
+                                    <Trigger Property="IsMouseOver" Value="True">
+                                        <Trigger.Setters>
+                                            <Setter TargetName="bd" Property="Background" Value="LightGray" />
+                                            <Setter TargetName="bd" Property="Opacity" Value="0.7" />
+                                            <Setter TargetName="bd" Property="BorderBrush" Value="LightGray" />
+                                        </Trigger.Setters>
+                                    </Trigger>
+                                </ControlTemplate.Triggers>
+                            </ControlTemplate>
+                        </Setter.Value>
+                    </Setter>
+                </Style.Setters>
+            </Style>
+
+            <Style x:Key="BigCustomRadioButtonStyle" TargetType="{x:Type RadioButton}">
+                <Setter Property="Template">
+                    <Setter.Value>
+                        <ControlTemplate TargetType="{x:Type RadioButton}">
+                            <Grid>
+                                <Border x:Name="border">
+                                    <Grid Background="Transparent">
+                                        <Grid.ColumnDefinitions>
+                                            <ColumnDefinition Width="Auto"/>
+                                            <ColumnDefinition Width="*"/>
+                                        </Grid.ColumnDefinitions>
+                                        <Border x:Name="radioButtonBorder" Grid.Column="0" BorderBrush="Black" Width="18" Height="18" Margin="0"  BorderThickness="1.4" CornerRadius="20" SnapsToDevicePixels="True">
+                                            <Path x:Name="checkMark" Fill="Black" StrokeThickness="2" Visibility="Collapsed" Data="M0 5C0 2.23858 2.23858 0 5 0C7.76142 0 10 2.23858 10 5C10 7.76142 7.76142 10 5 10C2.23858 10 0 7.76142 0 5Z" HorizontalAlignment="Center" VerticalAlignment="Center"/>
+                                        </Border>
+                                        <ContentPresenter Grid.Column="1" Margin="5,0,0,0" VerticalAlignment="Center" RecognizesAccessKey="True"/>
+                                    </Grid>
+                                </Border>
+                            </Grid>
+                            <ControlTemplate.Triggers>
+                                <Trigger Property="IsChecked" Value="True">
+                                    <Setter TargetName="checkMark" Property="Visibility" Value="Visible"/>
+                                </Trigger>
+                                <Trigger Property="IsMouseOver" Value="True">
+                                    <Setter TargetName="radioButtonBorder" Property="Background" Value="#E1E1E1"/>
+                                </Trigger>
+                                <Trigger Property="IsPressed" Value="True">
+                                    <Setter TargetName="radioButtonBorder" Property="Background" Value="#E1E1E1"/>
+                                </Trigger>
+                                <Trigger Property="IsEnabled" Value="False">
+                                    <Setter TargetName="radioButtonBorder" Property="Opacity" Value="0.3"/>
+                                </Trigger>
+                            </ControlTemplate.Triggers>
+                        </ControlTemplate>
+                    </Setter.Value>
+                </Setter>
+            </Style>
+        </ResourceDictionary>
+	</Window.Resources>
+    <Grid>
+        <Grid>
+            <Grid.RowDefinitions>
+                <RowDefinition Height="50" />
+                <RowDefinition Height="*" />
+                <RowDefinition Height="50" />
+            </Grid.RowDefinitions>
+            <Grid.ColumnDefinitions>
+                <ColumnDefinition Width="640" />
+                <ColumnDefinition Width="*" />
+            </Grid.ColumnDefinitions>
+            <DockPanel LastChildFill="True">
+                <Button
+                    Margin="12,0,0,0"
+        Name="btnAddFile"
+        MinWidth="112"
+Padding="8,0,8,0"
+        Height="32"
+        Click="btnAddFile_Click"
+        Content=" Add File"
+        DockPanel.Dock="Left"
+        BorderBrush="#33000000" Background="#E1E1E1" BorderThickness="1"  Style="{StaticResource DisabledButtonStyle}" />
+                <StackPanel Name="flowLayoutPanel2" DockPanel.Dock="Right">
+                    <Label
+            Name="lbTotalFiles"
+            Width="120"
+            Height="32"
+            Margin="0,5"
+            HorizontalAlignment="Right"
+            VerticalContentAlignment="Center"
+            Content="Total 10 Files" />
+                </StackPanel>
+            </DockPanel>
+            <StackPanel Name="panel1" Grid.Row="1" >
+
+                <ListView
+             VerticalContentAlignment="Top"
+                    HorizontalAlignment="Left"
+                    Margin="12,0,0,0"
+        Name="CompressListView"
+        Width="620"
+        Height="250"
+        AllowDrop="True"
+        DragOver="ConverterListView_DragOver"
+        Drop="ConverterListView_Drop"
+        ItemContainerStyle="{StaticResource ListViewItemStyle}"
+                    Loaded="ConverterListView_Loaded"
+                    PreviewMouseLeftButtonDown="ConverterListView_PreviewMouseLeftButtonDown"
+                    SizeChanged="ConverterListView_SizeChanged"
+        MouseMove="ConverterListView_MouseMove"
+        PreviewMouseUp="ConverterListView_PreviewMouseUp"
+        SelectionChanged="ConverterListView_SelectionChanged">
+
+                    <ListView.View>
+                        <GridView AllowsColumnReorder="False" ColumnHeaderContainerStyle="{StaticResource HeadStyle}">
+                            <GridViewColumn
+                    x:Name="FileName"
+                    Width="180"
+                    Header="Name">
+                                <GridViewColumn.CellTemplate>
+                                    <DataTemplate>
+                                        <StackPanel HorizontalAlignment="Left" Orientation="Horizontal">
+                                            <Image
+                                    Width="20"
+                                    Height="20"
+                                    Margin="5"
+                                    Source="../../Resources/Image/PDFicon.png"/>
+                                            <TextBlock
+                                    x:Name="TxbName"
+                                    HorizontalAlignment="Center"
+                                    VerticalAlignment="Center"
+                                    SizeChanged="TxbName_SizeChanged"
+                                    Text="{Binding Name}"
+                                    TextAlignment="Left" TextTrimming="CharacterEllipsis">
+                                                <TextBlock.ToolTip>
+                                                    <ToolTip>
+                                                        <TextBlock Text="{Binding Name}" />
+                                                    </ToolTip>
+                                                </TextBlock.ToolTip>
+                                            </TextBlock>
+                                        </StackPanel>
+                                    </DataTemplate>
+                                </GridViewColumn.CellTemplate>
+                            </GridViewColumn>
+                            <GridViewColumn
+    x:Name="SizeHeader"
+    Width="80"
+    Header="Size">
+                                <GridViewColumn.CellTemplate>
+                                    <DataTemplate>
+                                        <TextBlock Text="{Binding Size}" TextTrimming="CharacterEllipsis">
+                                            <TextBlock.ToolTip>
+                                                <ToolTip>
+                                                    <TextBlock Text="{Binding Size}" />
+                                                </ToolTip>
+                                            </TextBlock.ToolTip>
+                                            
+                                        </TextBlock>
+                                    </DataTemplate>
+                                </GridViewColumn.CellTemplate>
+                            </GridViewColumn>
+                            <GridViewColumn
+    x:Name="PathHeader"
+    Width="250"
+    Header="Path">
+                                <GridViewColumn.CellTemplate>
+                                    <DataTemplate>
+                                        <TextBlock
+                HorizontalAlignment="Left"
+                VerticalAlignment="Center"
+                Text="{Binding Path}"
+                TextAlignment="Left" TextTrimming="CharacterEllipsis">
+                                            <TextBlock.ToolTip>
+                                                <ToolTip>
+                                                    <TextBlock Text="{Binding Path}" />
+                                                </ToolTip>
+                                            </TextBlock.ToolTip>
+                                        </TextBlock>
+                                    </DataTemplate>
+                                </GridViewColumn.CellTemplate>
+                            </GridViewColumn>
+
+                            <GridViewColumn
+    x:Name="ProgressHeader"
+    Width="50"
+    Header="Progress">
+                                <GridViewColumn.CellTemplate>
+                                    <DataTemplate>
+                                        <TextBlock Text="{Binding Progress}" />
+                                    </DataTemplate>
+                                </GridViewColumn.CellTemplate>
+                            </GridViewColumn>
+                        </GridView>
+                    </ListView.View>
+                </ListView>
+                <WrapPanel Margin="0,12,0,0">
+                    <Button
+                        Margin="12,0,0,0"
+            Name="btnRemove"
+            MinWidth="112"
+            Padding="8,0,8,0"
+            Height="32"
+            Click="btnRemove_Click"
+            Content="Delete"
+                        BorderBrush="#33000000" Background="#E1E1E1" BorderThickness="1"  Style="{StaticResource DisabledButtonStyle}"
+             />
+                    <Button
+Name="btnMoveUp"
+Width="150"
+Height="32"
+Margin="10,5"
+Content="MoveUp"
+IsEnabled="False" Style="{StaticResource DisabledButtonStyle}"
+BorderBrush="#33000000" Background="#E1E1E1" BorderThickness="1" Click="btnMoveUp_Click" Visibility="Collapsed"/>
+                    <Button
+            Name="btnMoveDown"
+            Width="150"
+            Height="32"
+            Margin="10,5"
+            Content="Move Down"
+            IsEnabled="False"
+            BorderBrush="#33000000" Background="#E1E1E1" BorderThickness="1" Click="btnMoveDown_Click" Style="{StaticResource DisabledButtonStyle}"  Visibility="Collapsed"/>
+
+                </WrapPanel>
+            </StackPanel>
+            <GroupBox
+                Grid.Row="0"
+                Grid.RowSpan="2"
+                Grid.Column="1"
+                Margin="8,40,20,0"
+     Name="groupBox1"
+     Width="200"
+     Height="262"
+                VerticalAlignment="Top">
+                <GroupBox.Header>
+                    <TextBlock Name="groupBox1Text" Text="Optimization Quality" FontWeight="DemiBold"></TextBlock>
+                </GroupBox.Header>
+                <StackPanel>
+                    <RadioButton
+             Name="rbtnLow"
+             Margin="8,8,0,0"
+             Checked="rbtnAllPage_Checked"
+             Content="Low"
+             GroupName="GroupPageRange" Style="{StaticResource BigCustomRadioButtonStyle}"/>
+                    <RadioButton
+             Name="rbtnMedium"
+             Margin="8,8"
+             Checked="rbtnCurrentPage_Checked"
+             Content="Medium"
+             GroupName="GroupPageRange" Style="{StaticResource BigCustomRadioButtonStyle}"/>
+                    <RadioButton
+             Name="rbtnHigh"
+             Margin="8,0"
+             Checked="rbtnOldPageOnly_Checked"
+             Content="High"
+             GroupName="GroupPageRange" Style="{StaticResource BigCustomRadioButtonStyle}"/>
+                    <StackPanel Orientation="Horizontal">
+                        <RadioButton
+				 Name="rbtnCustom"
+				 Margin="8,8"
+				 Checked="RbtnEvenPageOnly_Checked"
+				 Content="Custom"
+				 GroupName="GroupPageRange" Style="{StaticResource BigCustomRadioButtonStyle}"/>
+                        <StackPanel Orientation="Horizontal" IsEnabled="{Binding ElementName=rbtnCustom,Path=IsChecked}">
+                            <TextBox Name="txtQuality" Width="50" Height="28"  PreviewTextInput="TextBox_PreviewTextInput" TextChanged="TextBox_TextChanged" InputMethod.IsInputMethodEnabled="False" Padding="0,5,0,0" Text="100"></TextBox>
+                            <TextBlock Height="15" Margin="8,0,0,0">%</TextBlock>
+                        </StackPanel>
+                    </StackPanel>
+                </StackPanel>
+            </GroupBox>
+            <WrapPanel
+    Width="300"
+    HorizontalAlignment="Right"
+    DockPanel.Dock="Right" Grid.Row="2" Grid.ColumnSpan="2">
+                <Button
+        Name="btnCompress"
+                    Style="{StaticResource DisabledButtonStyle}"
+        BorderBrush="#FA477EDE" Background="#E1E1E1" BorderThickness="1"
+        MinWidth="112"
+Padding="8,0,8,0"
+        Height="32"
+        Margin="30,0,2,0"
+        HorizontalAlignment="Right"
+        VerticalContentAlignment="Center"
+        IsEnabled="False"
+        Click="btnCompress_Click">
+                    Compress
+                </Button>
+                <Button
+        Name="btnCancel"
+        MinWidth="112"
+Padding="8,0,8,0"
+        Height="32"
+        Margin="10,0,10,0"
+        HorizontalAlignment="Right"
+        VerticalContentAlignment="Center"
+        Click="btnCancel_Click" Style="{StaticResource DisabledButtonStyle}"
+        BorderBrush="#33000000" Background="#E1E1E1" BorderThickness="1">
+                    Cancel
+                </Button>
+            </WrapPanel>
+        </Grid>
+    </Grid>
+</Window>

+ 778 - 0
Demo/Examples/Compdfkit.Controls/Compress/CompressDialog.xaml.cs

@@ -0,0 +1,778 @@
+using ComPDFKit.Controls.Common;
+using ComPDFKit.Controls.Helper;
+using ComPDFKit.PDFDocument;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.ComponentModel;
+using System.Drawing;
+using System.IO;
+using System.Text.RegularExpressions;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+using System.Windows.Forms;
+using System.Windows.Input;
+using System.Windows.Interop;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using DragEventArgs = System.Windows.DragEventArgs;
+using Microsoft.WindowsAPICodePack.Dialogs;
+using System.Threading.Tasks;
+using System.Globalization;
+using System.Windows.Data;
+
+namespace ComPDFKit.Controls.Compress
+{
+    public partial class CompressDialog : Window
+    {
+        private CPDFDocument tempDocument;
+        private List<string> pathlist = new List<string>();
+        private float quality = 45;
+        private int compressindex = -1;
+        private IntPtr compressingIntpr = IntPtr.Zero;
+        private string compressingfilepath = "";
+        private CPDFDocument.GetPageIndexDelegate indexDelegate = null;
+        private delegate void RefreshPageIndex(int pageIndex);
+        private bool stopClose = false;
+        private bool isCanceled = false;
+
+        public ObservableCollection<CompressDataItem> CompressDatas { get; set; }
+        
+        public CompressDialog()
+        {
+            InitializeComponent();
+            SetLangText();
+            rbtnMedium.IsChecked = true;
+            CompressDatas = new ObservableCollection<CompressDataItem>();
+            CompressListView.ItemsSource = CompressDatas;
+        }
+
+        private BitmapSource GetImagePath(string filePath, out IntPtr bitmapHandle)
+        {
+            try
+            {
+                Icon ico = System.Drawing.Icon.ExtractAssociatedIcon(filePath);
+                Bitmap bitmap = ico.ToBitmap();
+
+                bitmapHandle = bitmap.GetHbitmap();
+                BitmapSource bitmapSource = Imaging.CreateBitmapSourceFromHBitmap(bitmapHandle, IntPtr.Zero, System.Windows.Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions());
+                return bitmapSource;
+            }
+            catch
+            {
+                bitmapHandle = IntPtr.Zero;
+                return null;
+            }
+        }
+
+        private void SetLangText()
+        {
+            this.Title = LanguageHelper.CompressManager.GetString("CompressStr");
+            btnAddFile.Content = LanguageHelper.CompressManager.GetString("Main_AddFile");
+
+            btnRemove.Content = LanguageHelper.CompressManager.GetString("Main_RemoveAll");
+            btnMoveUp.Content = LanguageHelper.CompressManager.GetString("Merge_MoveUp");
+            btnMoveDown.Content = LanguageHelper.CompressManager.GetString("Merge_MoveDown");
+            btnCompress.Content = LanguageHelper.CompressManager.GetString("CompressStr");
+            btnCancel.Content = LanguageHelper.CompressManager.GetString("Main_Cancel");
+
+            groupBox1Text.Text = LanguageHelper.CompressManager.GetString("Compress_OptimizationQuality");
+            rbtnLow.Content = LanguageHelper.CompressManager.GetString("Compress_Low");
+            rbtnMedium.Content = LanguageHelper.CompressManager.GetString("Compress_Medium");
+            rbtnMedium.IsChecked = true;
+            rbtnHigh.Content = LanguageHelper.CompressManager.GetString("Compress_High");
+            rbtnCustom.Content = LanguageHelper.CompressManager.GetString("Compress_Custom");
+
+            PathHeader.Header = LanguageHelper.CompressManager.GetString("FileInfo_Location");
+            ProgressHeader.Header = LanguageHelper.CompressManager.GetString("Convert_Progress");
+            FileName.Header = LanguageHelper.CompressManager.GetString("Main_FileName");
+            SizeHeader.Header = LanguageHelper.CompressManager.GetString("FileInfo_Size");
+
+            lbTotalFiles.Content = string.Format(LanguageHelper.CompressManager.GetString("Merge_TotalPage"), 0);
+        }
+
+        private void btnAddFile_Click(object sender, RoutedEventArgs e)
+        {
+            OpenFileDialog file = new OpenFileDialog();
+            file.Multiselect = true;
+            file.Filter = "PDF Files (*.pdf)|*.pdf";
+            if (file.ShowDialog() == System.Windows.Forms.DialogResult.OK)
+            {
+                var files = file.FileNames;
+                for (int i = 0; i < files.Length; i++)
+                {
+                    AddFiletoList(files[i]);
+                }
+
+                UpdateMoveButtonState();
+            }
+        }
+
+        private void AddFiletoList(string filePath)
+        {
+            string password = "";
+            if (pathlist.Contains(filePath) || Path.GetExtension(filePath).ToLower() != ".pdf")
+            {
+                return;
+            }
+
+            CPDFDocument doc = CPDFDocument.InitWithFilePath(filePath);
+            if (doc == null)
+            {
+                MessageBoxEx.Show(LanguageHelper.CompressManager.GetString("Main_OpenFileFailedWarning"));
+                return;
+            }
+
+            if (doc.IsLocked)
+            {
+                PasswordWindow passwordWindow = new PasswordWindow();
+                passwordWindow.InitDocument(doc);
+                passwordWindow.Owner = Window.GetWindow(this);
+                passwordWindow.PasswordDialog.SetShowText(filePath + " is encrypted.");
+                passwordWindow.ShowDialog();
+                if (doc.IsLocked)
+                {
+                    doc.Release();
+                    return;
+                }
+
+                password = passwordWindow.Password;
+            }
+
+            pathlist.Add(filePath);
+            BitmapSource bitmapSource = GetImagePath(doc.FilePath, out IntPtr bitmapHandle);
+            CompressDataItem newdata = new CompressDataItem()
+            {
+                Name = doc.FileName,
+                Size = CommonHelper.GetFileSize(filePath),
+                Progress = "0/" + doc.PageCount,
+                Path = doc.FilePath,
+                PageCount = doc.PageCount,
+                ImagePath = bitmapSource
+
+            };
+            AddListViewItem(newdata, password);
+            doc.Release();
+            UpdateTotalCount();
+        }
+
+        private void UpdateTotalCount()
+        {
+            lbTotalFiles.Content = string.Format(LanguageHelper.CompressManager.GetString("Merge_TotalPage"), CompressListView.Items.Count);
+            if (CompressListView.Items.Count == 0)
+                btnCompress.IsEnabled = false;
+            else
+                btnCompress.IsEnabled = true;
+        }
+
+        private void AddListViewItem(CompressDataItem data, string password)
+        {
+            if (!string.IsNullOrEmpty(password))
+                data.PassWord = password;
+
+            CompressDatas.Add(data);
+            UpdateTotalCount();
+        }
+
+        private void btnRemove_Click(object sender, RoutedEventArgs e)
+        {
+            if (CompressListView.SelectedItems.Count > 0)
+            {
+                List<int> pages = new List<int>();
+                foreach (var selectedItem in CompressListView.SelectedItems)
+                {
+                    var imageItem = (CompressDataItem)selectedItem;
+                    int index = CompressListView.Items.IndexOf(imageItem);
+                    pages.Add(index);
+                }
+                pages.Sort();
+
+                for (int i = pages.Count - 1; i >= 0; i--)
+                {
+                    int index = pages[i];
+                    string path = ((CompressDataItem)CompressListView.Items[index]).Path;
+                    pathlist.Remove(path);
+                    CompressDatas.RemoveAt(index);
+                }
+            }
+            else
+            {
+                CompressDatas.Clear();
+                pathlist.Clear();
+            }
+            UpdateTotalCount();
+        }
+
+        private void btnChoosePage_Click(object sender, RoutedEventArgs e)
+        {
+
+        }
+
+        private async void btnCompress_Click(object sender, RoutedEventArgs e)
+        {
+            if ((bool)rbtnLow.IsChecked)
+                quality = 10;
+            else if ((bool)rbtnMedium.IsChecked)
+                quality = 40;
+            else if ((bool)rbtnHigh.IsChecked)
+                quality = 80;
+            else
+            {
+                int q = 0;
+                bool r = int.TryParse(txtQuality.Text, out q);
+                if (!r || q > 100 || q < 0)
+                {
+                    MessageBoxEx.Show(LanguageHelper.CompressManager.GetString("Compress_NumberErrorWarning"));
+                    txtQuality.Focus();
+                    return;
+                }
+                quality = q;
+            }
+
+            CommonOpenFileDialog commonFileDialog = new CommonOpenFileDialog(LanguageHelper.CompressManager.GetString("Main_OpenFolderNoteWarning"));
+            commonFileDialog.IsFolderPicker = true;
+            if (commonFileDialog.ShowDialog() == CommonFileDialogResult.Ok)
+            {
+                if (string.IsNullOrEmpty(commonFileDialog.FileName))
+                {
+                    MessageBoxEx.Show(LanguageHelper.CompressManager.GetString("Main_NoSelectedFilesWarning"),
+                        LanguageHelper.CompressManager.GetString("Main_HintWarningTitle"),
+                        MessageBoxButtons.OKCancel, MessageBoxIcon.Warning);
+                    return;
+                }
+            }
+            else
+                return;
+
+            stopClose = true;
+            groupBox1.IsEnabled = false;
+            btnAddFile.IsEnabled = false;
+            btnCompress.IsEnabled = false;
+            btnRemove.Content = LanguageHelper.CompressManager.GetString("Main_RemoveAll");
+            btnRemove.IsEnabled = false;
+            btnMoveDown.IsEnabled = false;
+            btnMoveUp.IsEnabled = false;
+            bool isFailed = false;
+            string selectedFile = "";
+            for (int i = 0; i < CompressListView.Items.Count; i++)
+            {
+                var item = (CompressDataItem)CompressListView.Items[i];
+                string path = item.Path;
+                if (isCanceled)
+                {
+                    item.Progress = LanguageHelper.CompressManager.GetString("Main_Interrupt");
+                    continue;
+                }
+
+                CPDFDocument doc = CPDFDocument.InitWithFilePath(path);
+                if (doc.IsLocked && item.PassWord != null && !string.IsNullOrEmpty(item.PassWord))
+                {
+                    doc.UnlockWithPassword(item.PassWord.ToString());
+                }
+
+                var filename = doc.FileName + " compressed";
+                var filepath = commonFileDialog.FileName + "\\" + filename + ".pdf";
+                filepath = CommonHelper.CreateFilePath(filepath);
+                selectedFile = compressingfilepath = filepath;
+
+                indexDelegate += GetIndex;
+                compressingIntpr = doc.CompressFile_Init(quality, indexDelegate);
+                GC.KeepAlive(indexDelegate);
+                compressindex = i;
+                tempDocument = doc;
+                var r = await Task.Run<bool>(() => { return doc.CompressFile_Start(compressingIntpr, filepath); });
+                if (!r)
+                {
+                    item.Progress = LanguageHelper.CompressManager.GetString("Main_FailedState");
+                    doc.Release();
+                    if (File.Exists(filepath))
+                        File.Delete(filepath);
+                    isFailed = true;
+                    continue;
+                }
+                compressingfilepath = "";
+                doc.Release();
+            }
+
+            int itemCount = CompressListView.Items.Count;
+            if (!isFailed)
+            {
+                System.Diagnostics.Process.Start("explorer", "/select,\"" + selectedFile + "\"");
+            }
+
+            isCanceled = false;
+            compressindex = -1;
+            stopClose = false;
+            btnAddFile.IsEnabled = true;
+            btnCompress.IsEnabled = true;
+            btnRemove.Content = LanguageHelper.CompressManager.GetString("Main_Delete");
+            btnRemove.IsEnabled = true;
+            btnMoveDown.IsEnabled = true;
+            btnMoveUp.IsEnabled = true;
+            groupBox1.IsEnabled = true;
+        }
+
+        private int GetIndex(int pageindex)
+        {
+            try
+            {
+                if (Dispatcher.CheckAccess() == false)
+                {
+                    return Dispatcher.Invoke(new CPDFDocument.GetPageIndexDelegate(delegate (int s)
+                    {
+                        if (CompressListView.Items.Count >= compressindex)
+                        {
+                            if (CompressListView.Items[compressindex] is CompressDataItem dataItem)
+                            {
+                                dataItem.Progress = pageindex + "/" + dataItem.PageCount;
+                                if (pageindex == dataItem.PageCount - 1)
+                                {
+                                    dataItem.Progress = LanguageHelper.CompressManager.GetString("Main_CompletedState");
+                                }
+                            }
+                        }
+                        return 0;
+                    }), pageindex).ToString().Length;
+                }
+                else
+                {
+                    if (CompressListView.Items.Count >= compressindex)
+                    {
+                        if (CompressListView.Items[compressindex] is CompressDataItem dataItem)
+                        {
+                            dataItem.Progress = pageindex + "/" + dataItem.PageCount;
+                            if (pageindex == dataItem.PageCount - 1)
+                            {
+                                dataItem.Progress = LanguageHelper.CompressManager.GetString("Main_CompletedState");
+                            }
+                        }
+                    }
+                    return 0;
+                }
+            }
+            catch { return -1; }
+        }
+
+        private void btnCancel_Click(object sender, RoutedEventArgs e)
+        {
+            try
+            {
+                if (compressindex != -1 && !compressingIntpr.Equals(IntPtr.Zero))
+                {
+                    if (MessageBoxEx.Show(LanguageHelper.CompressManager.GetString("CompressInterruptWarning"), "", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes && tempDocument != null)
+                    {
+                        tempDocument.CompressFile_Cancel(compressingIntpr);
+                        isCanceled = true;
+                        if (File.Exists(compressingfilepath))
+                            File.Delete(compressingfilepath);
+                    }
+                }
+                else
+                {
+                    this.Close();
+                    this.DialogResult = false;
+                }
+            }
+            catch { }
+        }
+
+        private void ConverterListView_DragOver(object sender, DragEventArgs e)
+        {
+            var files = (Array)e.Data.GetData(System.Windows.DataFormats.FileDrop);
+            int count = 0;
+            string pdf = "pdf";
+            foreach (string file in files)
+            {
+                string text = Path.GetExtension(file);
+                if (text.IndexOf(pdf, StringComparison.OrdinalIgnoreCase) >= 0)
+                {
+                    count++;
+                }
+            }
+            if (count < 1)
+            {
+                e.Effects = System.Windows.DragDropEffects.None;
+                Mouse.SetCursor(System.Windows.Input.Cursors.No);
+            }
+            else
+            {
+                e.Effects = System.Windows.DragDropEffects.Copy;
+                Mouse.SetCursor(System.Windows.Input.Cursors.Arrow);
+            }
+
+            return;
+        }
+
+        private void ConverterListView_Drop(object sender, DragEventArgs e)
+        {
+            var files = (Array)e.Data.GetData(System.Windows.DataFormats.FileDrop);
+            if (files != null && files.Length > 0)
+            {
+                var Files = (string[])files;
+                for (int i = 0; i < Files.Length; i++)
+                {
+                    AddFiletoList(Files[i]);
+                }
+            }
+        }
+
+        private void ConverterListView_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
+        {
+
+        }
+
+        private void ConverterListView_PreviewMouseUp(object sender, MouseButtonEventArgs e)
+        {
+            DependencyObject element = (DependencyObject)e.OriginalSource;
+            if (element is Thumb thumb)
+            {
+                GridViewColumnHeader gridViewColumnHeader = CommonHelper.ViewportHelper.FindVisualParent<GridViewColumnHeader>(thumb);
+                if (gridViewColumnHeader != null && gridViewColumnHeader.Content != null)
+                {
+                    GridViewColumn column = FindGridViewColumn(gridViewColumnHeader.Content.ToString(), CompressListView);
+                    if (column != null)
+                    {
+                        if (column.Header == LanguageHelper.CompressManager.GetString("Main_FileName") && column.ActualWidth > 240)
+                        {
+                            TextBlock textBlock = FindTextBlockInCellTemplate(column);
+                            if (textBlock != null)
+                            {
+                                textBlock.MaxWidth = textBlock.Width = column.ActualWidth - 20;
+                                TxbName_SizeChanged(textBlock, null);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+
+        private TextBlock FindTextBlockInCellTemplate(GridViewColumn column)
+        {
+            DataTemplate dataTemplate = column.CellTemplate;
+            if (dataTemplate != null)
+            {
+                FrameworkElement frameworkElement = dataTemplate.LoadContent() as FrameworkElement;
+                if (frameworkElement != null)
+                {
+                    return CommonHelper.ViewportHelper.FindVisualChild<TextBlock>(frameworkElement);
+                }
+            }
+
+            return null;
+        }
+
+        private GridViewColumn FindGridViewColumn(string columnHeader, System.Windows.Controls.ListView listView)
+        {
+            GridView gridView = listView.View as GridView;
+            if (gridView != null)
+            {
+                foreach (var column in gridView.Columns)
+                {
+                    GridViewColumn gvColumn = column as GridViewColumn;
+                    if (gvColumn != null && gvColumn.Header.ToString() == columnHeader)
+                    {
+                        return gvColumn;
+                    }
+                }
+            }
+
+            return null;
+        }
+
+        private void UpdateMoveButtonState()
+        {
+            if (compressindex != -1 && !compressingIntpr.Equals(IntPtr.Zero))
+            {
+                return;
+            }
+
+            if (CompressListView.Items.Count > 0 && CompressListView.SelectedItems.Count > 0)
+            {
+                btnRemove.Content = LanguageHelper.CompressManager.GetString("Main_Delete"); ;
+                int count = CompressListView.Items.Count;
+                if (CompressListView.SelectedItems.Contains(CompressListView.Items[CompressListView.Items.Count - 1]))
+                {
+                    btnMoveDown.IsEnabled = false;
+                }
+                else
+                    btnMoveDown.IsEnabled = true;
+                if (CompressListView.SelectedItems.Contains(CompressListView.Items[0]))
+                    btnMoveUp.IsEnabled = false;
+                else
+                    btnMoveUp.IsEnabled = true;
+            }
+            else
+            {
+                btnRemove.Content = LanguageHelper.CompressManager.GetString("Main_RemoveAll");
+                btnMoveDown.IsEnabled = false;
+                btnMoveUp.IsEnabled = false;
+            }
+        }
+
+        private void ConverterListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
+        {
+            UpdateMoveButtonState();
+        }
+        private void UpdateColumnsWidth(System.Windows.Controls.ListView listView)
+        {
+            int autoFillColumnIndex = (listView.View as System.Windows.Controls.GridView).Columns.Count - 1;
+            if (listView.ActualWidth == Double.NaN)
+            {
+                listView.Measure(new System.Windows.Size(Double.PositiveInfinity, Double.PositiveInfinity));
+            }
+            double remainingSpace = listView.ActualWidth;
+            for (int i = 0; i < (listView.View as System.Windows.Controls.GridView).Columns.Count; i++)
+            {
+                if (i != autoFillColumnIndex)
+                {
+                    remainingSpace -= (listView.View as System.Windows.Controls.GridView).Columns[i].ActualWidth;
+                    (listView.View as System.Windows.Controls.GridView).Columns[autoFillColumnIndex].Width = remainingSpace >= 0 ? remainingSpace : 0;
+                }
+            }
+        }
+
+        private void ConverterListView_Loaded(object sender, RoutedEventArgs e)
+        {
+            UpdateColumnsWidth(sender as System.Windows.Controls.ListView);
+        }
+
+        private void ConverterListView_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
+        {
+            var pos = e.GetPosition(CompressListView);
+            var result = VisualTreeHelper.HitTest(CompressListView, pos);
+            if (result != null)
+            {
+                var listBoxItem = CommonHelper.ViewportHelper.FindVisualParent<ListBoxItem>(result.VisualHit);
+                if (listBoxItem == null)
+                {
+                    CompressListView.SelectedItems.Clear();
+                }
+            }
+            CompressListView.Focus();
+        }
+
+        private void ConverterListView_SizeChanged(object sender, SizeChangedEventArgs e)
+        {
+            UpdateColumnsWidth(sender as System.Windows.Controls.ListView);
+        }
+
+        private void TxbName_SizeChanged(object sender, SizeChangedEventArgs e)
+        {
+
+        }
+
+        private void PART_HeaderGripper_DragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
+        {
+
+        }
+
+        private void rbtnAllPage_Checked(object sender, RoutedEventArgs e)
+        {
+
+        }
+
+        private void rbtnCurrentPage_Checked(object sender, RoutedEventArgs e)
+        {
+
+        }
+
+        private void rbtnOldPageOnly_Checked(object sender, RoutedEventArgs e)
+        {
+
+        }
+
+        private void RbtnEvenPageOnly_Checked(object sender, RoutedEventArgs e)
+        {
+
+        }
+
+        public class CompressDataItem : INotifyPropertyChanged
+        {
+            public event PropertyChangedEventHandler PropertyChanged;
+
+            protected virtual void OnPropertyChanged(string propertyName)
+            {
+                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
+            }
+
+            private string passWord;
+
+            public string PassWord { get; set; }
+
+            public BitmapSource ImagePath { get; set; }
+
+            public string Name { get; set; }
+            public string Size { get; set; }
+
+            public string Path { get; set; }
+            public int PageCount { get; set; }
+
+            private string progress;
+
+            public string Progress
+            {
+                get { return progress; }
+                set
+                {
+                    progress = value;
+                    OnPropertyChanged("Progress");
+                }
+            }
+        }
+
+        private void btnMoveDown_Click(object sender, RoutedEventArgs e)
+        {
+            try
+            {
+                var items = CompressListView.SelectedItems;
+                if (items.Count > 0)
+                {
+                    List<int> indexs = new List<int>();
+                    foreach (var selectedItem in CompressListView.SelectedItems)
+                    {
+                        var imageItem = (CompressDataItem)selectedItem;
+                        int index = CompressListView.Items.IndexOf(imageItem);
+                        indexs.Add(index);
+                    }
+
+                    indexs.Sort();
+                    for (int i = 0; i < indexs.Count; i++)
+                    {
+                        var index = indexs[indexs.Count - 1 - i];
+                        var item = CompressDatas[index];
+                        CompressDatas.RemoveAt(index);
+                        CompressDatas.Insert(index + 1, item);
+                    }
+
+                    CompressListView.SelectedItems.Clear();
+
+                    for (int i = 0; i < indexs.Count; i++)
+                    {
+                        CompressListView.SelectedItems.Add(CompressListView.Items[indexs[i] + 1]);
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+            }
+        }
+
+        private void btnMoveUp_Click(object sender, RoutedEventArgs e)
+        {
+            try
+            {
+                var items = CompressListView.SelectedItems; 
+                if (items.Count > 0)
+                {
+                    List<int> indexs = new List<int>();
+                    foreach (var selectedItem in CompressListView.SelectedItems)
+                    {
+                        var imageItem = (CompressDataItem)selectedItem;
+                        int index = CompressListView.Items.IndexOf(imageItem);
+                        indexs.Add(index);
+                    }
+                    indexs.Sort();
+
+                    for (int i = 0; i < indexs.Count; i++)
+                    {
+                        var index = indexs[i];
+                        var item = CompressDatas[index];
+                        CompressDatas.RemoveAt(index);
+                        CompressDatas.Insert(index - 1, item);
+                    }
+
+                    CompressListView.SelectedItems.Clear();
+
+                    for (int i = 0; i < indexs.Count; i++)
+                    {
+                        CompressListView.SelectedItems.Add(CompressListView.Items[indexs[i] - 1]);
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+
+            }
+        }
+
+        private void TextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
+        {
+            Regex regex = new Regex("[^0-9]+");
+            if (regex.IsMatch(e.Text))
+            {
+                e.Handled = true;
+            }
+        }
+
+        private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
+        {
+            if (sender is System.Windows.Controls.TextBox textBox)
+            {
+                if (!string.IsNullOrEmpty(textBox.Text))
+                {
+                    int value = int.Parse(textBox.Text);
+
+                    if (value < 1)
+                    {
+                        textBox.Text = "1";
+                        textBox.Select(textBox.Text.Length, 0);
+                    }
+                    else if (value > 100)
+                    {
+                        textBox.Text = "100";
+                        textBox.Select(textBox.Text.Length, 0);
+                    }
+                }
+                else
+                {
+                    textBox.Text = "1";
+                    textBox.Select(textBox.Text.Length, 0);
+                }
+            }
+        }
+    }
+
+    public class MaxWidthToTextTrimmingConverter : IMultiValueConverter
+    {
+        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
+        {
+            if (values.Length == 2 && values[0] is double maxWidth && values[1] is string text)
+            {
+                if (maxWidth >= MeasureTextWidth(text))
+                {
+                    return TextTrimming.None;
+                }
+                else
+                {
+                    return TextTrimming.CharacterEllipsis;
+                }
+            }
+
+            return TextTrimming.None;
+        }
+
+        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+        {
+            throw new NotSupportedException();
+        }
+
+        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
+        {
+            throw new NotImplementedException();
+        }
+
+        private double MeasureTextWidth(string text)
+        {
+            var formattedText = new FormattedText(
+            text,
+            CultureInfo.CurrentCulture,
+            System.Windows.FlowDirection.LeftToRight,
+            new Typeface("Arial"),
+            12,
+            System.Windows.Media.Brushes.Black);
+
+            return formattedText.WidthIncludingTrailingWhitespace;
+        }
+    }
+}

+ 209 - 82
Demo/Examples/Compdfkit.Controls/Edit/ContentEditCOntrol/ContentEditControl.xaml.cs

@@ -28,6 +28,7 @@ using MenuItem = System.Windows.Controls.MenuItem;
 using OpenFileDialog = Microsoft.Win32.OpenFileDialog;
 using UserControl = System.Windows.Controls.UserControl;
 using System.Linq;
+using ComPDFKit.Tool.UndoManger;
 
 namespace ComPDFKit.Controls.PDFControl
 {
@@ -152,7 +153,7 @@ namespace ComPDFKit.Controls.PDFControl
             }
 
             PdfViewControl.PDFToolManager.SetCreateContentEditType(CPDFEditType.None);
-            PdfViewControl.PDFViewTool.SetCurrentEditType(CPDFEditType.EditText | CPDFEditType.EditImage);
+            PdfViewControl.PDFViewTool.SetCurrentEditType(CPDFEditType.EditText | CPDFEditType.EditImage | CPDFEditType.EditPath);
             PdfViewControl.PDFViewTool.GetCPDFViewer().SetIsVisibleCustomMouse(false);
             PdfViewControl.PDFViewTool.GetCPDFViewer().SetIsShowStampMouse(false);
             PdfViewControl.PDFViewTool.SelectedEditAreaForIndex(-1, -1);
@@ -253,33 +254,69 @@ namespace ComPDFKit.Controls.PDFControl
                 return;
             }
 
+            Rect oldRect = DataConversionForWPF.CRectConversionForRect(textArea.GetFrame());
+            if (Keyboard.Modifiers.HasFlag(ModifierKeys.Control) && Keyboard.Modifiers.HasFlag(ModifierKeys.Alt))
+            {
+                if(e.Key == Key.S)
+                {
+                    bool result = textArea.AddStrikethrough();
+                    if (result)
+                    {
+                        PDFEditHistory editHistory = new PDFEditHistory();
+                        CPDFPage page = PdfViewControl.PDFViewTool.GetCPDFViewer().GetDocument().PageAtIndex(pageIndex);
+                        editHistory.EditPage = page.GetEditPage();
+                        editHistory.PageIndex = pageIndex;
+                        PdfViewControl.PDFViewTool.GetCPDFViewer().UndoManager.AddHistory(editHistory);
+                        UpdateEditArea(oldRect, textArea);
+                    }
+
+                    e.Handled = true;
+                }
+            }
+
             if (Keyboard.Modifiers == ModifierKeys.Control)
             {
                 if (e.Key == Key.Left)
                 {
                     textArea.GetPreWordCharPlace();
-                    UpdateTextArea(textArea);
+                    UpdateEditArea(oldRect, textArea);
                     e.Handled = true;
                 }
 
                 if (e.Key == Key.Right)
                 {
                     textArea.GetNextWordCharPlace();
-                    UpdateTextArea(textArea);
+                    UpdateEditArea(oldRect, textArea);
                     e.Handled = true;
                 }
 
                 if (e.Key == Key.Up)
                 {
                     textArea.GetSectionBeginCharPlace();
-                    UpdateTextArea(textArea);
+                    UpdateEditArea(oldRect, textArea);
                     e.Handled = true;
                 }
 
                 if (e.Key == Key.Down)
                 {
                     textArea.GetSectionEndCharPlace();
-                    UpdateTextArea(textArea);
+                    UpdateEditArea(oldRect, textArea);
+                    e.Handled = true;
+                }
+
+                if (e.Key == Key.U)
+                {
+                    bool result = textArea.AddUnderline();
+                    if(result)
+                    {
+                        PDFEditHistory editHistory = new PDFEditHistory();
+                        CPDFPage page = PdfViewControl.PDFViewTool.GetCPDFViewer().GetDocument().PageAtIndex(pageIndex);
+                        editHistory.EditPage = page.GetEditPage();
+                        editHistory.PageIndex = pageIndex;
+                        PdfViewControl.PDFViewTool.GetCPDFViewer().UndoManager.AddHistory(editHistory);
+                        UpdateEditArea(oldRect, textArea);
+                    }
+
                     e.Handled = true;
                 }
             }
@@ -296,7 +333,7 @@ namespace ComPDFKit.Controls.PDFControl
                     textArea.GetPrevCharPlace();
                     endPoint = GetPoint(textArea);
                     textArea.GetSelectChars(startPoint, endPoint);
-                    UpdateTextArea(textArea);
+                    UpdateEditArea(oldRect, textArea);
                     e.Handled = true;
                 }
 
@@ -305,7 +342,7 @@ namespace ComPDFKit.Controls.PDFControl
                     textArea.GetNextCharPlace();
                     endPoint = GetPoint(textArea);
                     textArea.GetSelectChars(startPoint, endPoint);
-                    UpdateTextArea(textArea);
+                    UpdateEditArea(oldRect, textArea);
                     e.Handled = true;
                 }
 
@@ -314,7 +351,7 @@ namespace ComPDFKit.Controls.PDFControl
                     textArea.GetUpCharPlace();
                     endPoint = GetPoint(textArea);
                     textArea.GetSelectChars(startPoint, endPoint);
-                    UpdateTextArea(textArea);
+                    UpdateEditArea(oldRect, textArea);
                     e.Handled = true;
                 }
 
@@ -323,7 +360,7 @@ namespace ComPDFKit.Controls.PDFControl
                     textArea.GetDownCharPlace();
                     endPoint = GetPoint(textArea);
                     textArea.GetSelectChars(startPoint, endPoint);
-                    UpdateTextArea(textArea);
+                    UpdateEditArea(oldRect, textArea);
                     e.Handled = true;
                 }
             }
@@ -333,14 +370,14 @@ namespace ComPDFKit.Controls.PDFControl
                 if (e.SystemKey == Key.Up)
                 {
                     textArea.GetLineBeginCharPlace();
-                    UpdateTextArea(textArea);
+                    UpdateEditArea(oldRect, textArea);
                     e.Handled = true;
                 }
 
                 if (e.SystemKey == Key.Down)
                 {
                     textArea.GetLineEndCharPlace();
-                    UpdateTextArea(textArea);
+                    UpdateEditArea(oldRect, textArea);
                     e.Handled = true;
                 }
             }
@@ -390,7 +427,7 @@ namespace ComPDFKit.Controls.PDFControl
                     textArea.GetPreWordCharPlace();
                     endPoint = GetPoint(textArea);
                     textArea.GetSelectChars(startPoint, endPoint);
-                    UpdateTextArea(textArea);
+                    UpdateEditArea(oldRect, textArea);
                     e.Handled = true;
                 }
 
@@ -399,7 +436,7 @@ namespace ComPDFKit.Controls.PDFControl
                     textArea.GetNextWordCharPlace();
                     endPoint = GetPoint(textArea);
                     textArea.GetSelectChars(startPoint, endPoint);
-                    UpdateTextArea(textArea);
+                    UpdateEditArea(oldRect, textArea);
                     e.Handled = true;
                 }
 
@@ -408,7 +445,7 @@ namespace ComPDFKit.Controls.PDFControl
                     textArea.GetSectionBeginCharPlace();
                     endPoint = GetPoint(textArea);
                     textArea.GetSelectChars(startPoint, endPoint);
-                    UpdateTextArea(textArea);
+                    UpdateEditArea(oldRect, textArea);
                     e.Handled = true;
                 }
 
@@ -417,7 +454,7 @@ namespace ComPDFKit.Controls.PDFControl
                     textArea.GetSectionEndCharPlace();
                     endPoint = GetPoint(textArea);
                     textArea.GetSelectChars(startPoint, endPoint);
-                    UpdateTextArea(textArea);
+                    UpdateEditArea(oldRect, textArea);
                     e.Handled = true;
                 }
             }
@@ -594,21 +631,11 @@ namespace ComPDFKit.Controls.PDFControl
         }
 
         /// <summary>
-        /// Update the text appearance after the text area is changed
-        /// </summary> 
-        private void UpdateTextArea(CPDFEditTextArea textArea)
-        {
-            Rect oldRect = DataConversionForWPF.CRectConversionForRect(textArea.GetFrame());
-            PdfViewControl.PDFViewTool.UpdateRender(oldRect, textArea);
-        }
-
-        /// <summary>
-        /// Update the image appearance after the image area is changed
+        /// Update the edit area appearance after the edit area is changed
         /// </summary> 
-        private void UpdateImageArea(CPDFEditImageArea imageArea)
+        private void UpdateEditArea(Rect oldRect, CPDFEditArea editArea)
         {
-            Rect oldRect = DataConversionForWPF.CRectConversionForRect(imageArea.GetFrame());
-            PdfViewControl.PDFViewTool.UpdateRender(oldRect, imageArea);
+            PdfViewControl.PDFViewTool.UpdateRender(oldRect, editArea);
         }
 
         private void PdfViewControl_MouseRightButtonDownHandler(object sender, MouseEventObject e)
@@ -626,6 +653,9 @@ namespace ComPDFKit.Controls.PDFControl
                 case MouseHitTestType.ImageEdit:
                     CreateImageEditMenu(sender, ref ContextMenu);
                     break;
+                case MouseHitTestType.PathEdit:
+                    CreatePathEditMenu(sender, ref ContextMenu);
+                    break;
                 case MouseHitTestType.Unknown:
                     List<int> pageInts = new List<int>();
                     List<CPDFEditArea> editAreas = PdfViewControl.PDFToolManager.GetSelectedEditAreaListObject(ref pageInts);
@@ -669,11 +699,15 @@ namespace ComPDFKit.Controls.PDFControl
 
         private void AppendOpacityMenu(MenuItem parentMenu, CPDFEditArea editArea, CPDFEditType editType)
         {
+            if (editArea == null)
+                return;
+
             List<int> opacityList = new List<int>()
             {
                 25,50,75,100
             };
 
+            Rect oldRect = DataConversionForWPF.CRectConversionForRect(editArea.GetFrame());
             foreach (int opacity in opacityList)
             {
                 MenuItem opacityMenu = new MenuItem();
@@ -685,16 +719,22 @@ namespace ComPDFKit.Controls.PDFControl
                         CPDFEditImageArea editImageArea = editArea as CPDFEditImageArea;
                         editImageArea?.SetImageTransparency((byte)Math.Ceiling(opacity * 255 / 100D));
                         pdfContentEditControl.RefreshThumb();
-                        UpdateImageArea(editImageArea);
+                        UpdateEditArea(oldRect, editImageArea);
                     }
                     else if (editArea != null && editType == CPDFEditType.EditText)
                     {
                         CPDFEditTextArea editTextArea = editArea as CPDFEditTextArea;
                         editTextArea?.SetCharsFontTransparency((byte)Math.Ceiling(opacity * 255 / 100D));
-                        pdfContentEditControl.RefreshThumb();
-                        UpdateTextArea(editTextArea);
+                        UpdateEditArea(oldRect, editTextArea);
+                    }
+                    else if (editArea != null && editType == CPDFEditType.EditPath)
+                    {
+                        CPDFEditPathArea editPathArea = editArea as CPDFEditPathArea;
+                        editPathArea?.SetTransparency((byte)Math.Ceiling(opacity * 255 / 100D));
+                        UpdateEditArea(oldRect, editPathArea);
                     }
                 };
+
                 parentMenu.Items.Add(opacityMenu);
             }
         }
@@ -732,6 +772,9 @@ namespace ComPDFKit.Controls.PDFControl
             else if (editAreas != null && editAreas.Count != 0)
             {
                 List<CPDFEditTextArea> editTextAreas = editAreas.OfType<CPDFEditTextArea>().ToList();
+                List<CPDFEditImageArea> editImageAreas = editAreas.OfType<CPDFEditImageArea>().ToList();
+                List<CPDFEditPathArea> editPathAreas = editAreas.OfType<CPDFEditPathArea>().ToList();
+
                 editTextAreas.ForEach(textArea => textArea.SelectAllChars());
                 if (editAreas.Count == editTextAreas.Count)
                 {
@@ -741,14 +784,22 @@ namespace ComPDFKit.Controls.PDFControl
                     pdfContentEditControl.SetPDFTextEditData(editParams, true);
                     PropertyContainer.Child = pdfContentEditControl;
                 }
-                else if (editTextAreas.Count == 0)
+                else if (editAreas.Count == editImageAreas.Count)
                 {
-                    List<ImageEditParam> editParams = editAreas.
+                    List<ImageEditParam> editParams = editImageAreas.
                         Select(area => ParamConverter.CPDFDataConverterToPDFEitParam(PdfViewControl.PDFToolManager.GetDocument(), area, pageInts.FirstOrDefault())).
                         Cast<ImageEditParam>().ToList();
                     pdfContentEditControl.SetPDFImageEditData(editParams);
                     PropertyContainer.Child = pdfContentEditControl;
                 }
+                else if (editAreas.Count == editPathAreas.Count)
+                {
+                    List<PathEditParam> editParams = editPathAreas.
+                        Select(area => ParamConverter.CPDFDataConverterToPDFEitParam(PdfViewControl.PDFToolManager.GetDocument(), area, pageInts.FirstOrDefault())).
+                        Cast<PathEditParam>().ToList();
+                    pdfContentEditControl.SetPDFPathEditData(editParams);
+                    PropertyContainer.Child = pdfContentEditControl;
+                }
                 else
                 {
                     pdfContentEditControl.ClearContentControl();
@@ -787,8 +838,7 @@ namespace ComPDFKit.Controls.PDFControl
                     pdfContentEditControl.SetPDFTextEditData(new List<TextEditParam> { (TextEditParam)pDFEditParam }, true);
                     PropertyContainer.Child = pdfContentEditControl;
                 }
-
-                else if (editAreaArea.Type == CPDFEditType.EditImage && PdfViewControl != null)
+                else if (editAreaArea.Type == CPDFEditType.EditImage)
                 {
                     UIElement pageView = sender as UIElement;
                     if (pageView != null)
@@ -800,10 +850,17 @@ namespace ComPDFKit.Controls.PDFControl
                     pdfContentEditControl.SetPDFImageEditData(new List<ImageEditParam> { (ImageEditParam)pDFEditParam });
                     PropertyContainer.Child = pdfContentEditControl;
                 }
-
-                else
+                else if (editAreaArea.Type == CPDFEditType.EditPath)
                 {
-
+                    UIElement pageView = sender as UIElement;
+                    if (pageView != null)
+                    {
+                        pageView.MouseLeftButtonUp -= PageView_MouseLeftButtonUp;
+                        pageView.MouseLeftButtonUp += PageView_MouseLeftButtonUp;
+                    }
+                    PDFEditParam pDFEditParam = ParamConverter.CPDFDataConverterToPDFEitParam(PdfViewControl.PDFToolManager.GetDocument(), editAreaArea, pageIndex);
+                    pdfContentEditControl.SetPDFPathEditData(new List<PathEditParam> { (PathEditParam)pDFEditParam });
+                    PropertyContainer.Child = pdfContentEditControl;
                 }
             }
         }
@@ -841,6 +898,7 @@ namespace ComPDFKit.Controls.PDFControl
             if (PdfViewControl != null && PdfViewControl.PDFViewTool != null && CanUndo)
             {
                 PdfViewControl.PDFViewTool.GetCPDFViewer()?.UndoManager?.Undo();
+                PdfViewControl.PDFViewTool.GetCPDFViewer().UpdateRenderFrame();
             }
         }
 
@@ -849,6 +907,7 @@ namespace ComPDFKit.Controls.PDFControl
             if (PdfViewControl != null && PdfViewControl.PDFViewTool != null && CanRedo)
             {
                 PdfViewControl.PDFViewTool.GetCPDFViewer()?.UndoManager?.Redo();
+                PdfViewControl.PDFViewTool.GetCPDFViewer().UpdateRenderFrame();
             }
         }
 
@@ -878,17 +937,22 @@ namespace ComPDFKit.Controls.PDFControl
         {
             int index = -1;
             CPDFEditImageArea imageArea = PdfViewControl.PDFToolManager.GetSelectedEditAreaObject(ref index) as CPDFEditImageArea;
+            if (imageArea == null)
+                return;
+
+            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 });
 
             MenuItem rotateLeftMenu = new MenuItem();
             rotateLeftMenu.Header = LanguageHelper.CommonManager.GetString("Menu_RotateLeft");
             rotateLeftMenu.Click += (o, p) =>
             {
-                if (imageArea != null)
-                {
-                    imageArea.Rotate(-90);
-                    pdfContentEditControl.RefreshThumb();
-                    UpdateImageArea(imageArea);
-                }
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(imageArea.GetFrame());
+                imageArea.Rotate(90);
+                pdfContentEditControl.RefreshThumb();
+                UpdateEditArea(oldRect,imageArea);
             };
             menu.Items.Add(rotateLeftMenu);
 
@@ -896,12 +960,10 @@ namespace ComPDFKit.Controls.PDFControl
             rotateRightMenu.Header = LanguageHelper.CommonManager.GetString("Menu_RotateRight");
             rotateRightMenu.Click += (o, p) =>
             {
-                if (imageArea != null)
-                {
-                    imageArea.Rotate(90);
+                    Rect oldRect = DataConversionForWPF.CRectConversionForRect(imageArea.GetFrame());
+                    imageArea.Rotate(-90);
                     pdfContentEditControl.RefreshThumb();
-                    UpdateImageArea(imageArea);
-                }
+                    UpdateEditArea(oldRect, imageArea);
             };
             menu.Items.Add(rotateRightMenu);
 
@@ -909,42 +971,40 @@ namespace ComPDFKit.Controls.PDFControl
             replaceMenu.Header = LanguageHelper.CommonManager.GetString("Menu_Replace");
             replaceMenu.Click += (o, p) =>
             {
-                if (imageArea != null)
+                OpenFileDialog openFileDialog = new OpenFileDialog();
+                openFileDialog.Filter = "Image Files(*.jpg;*.jpeg;*.png;*.bmp)|*.jpg;*.jpeg;*.png;*.bmp;";
+                if (openFileDialog.ShowDialog() == true)
                 {
-                    OpenFileDialog openFileDialog = new OpenFileDialog();
-                    openFileDialog.Filter = "Image Files(*.jpg;*.jpeg;*.png;*.bmp)|*.jpg;*.jpeg;*.png;*.bmp;";
-                    if (openFileDialog.ShowDialog() == true)
-                    {
-                        int imageWidth = 0;
-                        int imageHeight = 0;
-                        byte[] imageData = null;
+                    int imageWidth = 0;
+                    int imageHeight = 0;
+                    byte[] imageData = null;
 
-                        BitmapFrame frame = null;
-                        BitmapDecoder decoder = BitmapDecoder.Create(new Uri(openFileDialog.FileName), BitmapCreateOptions.None, BitmapCacheOption.Default);
-                        if (decoder.Frames.Count > 0)
+                    BitmapFrame frame = null;
+                    BitmapDecoder decoder = BitmapDecoder.Create(new Uri(openFileDialog.FileName), BitmapCreateOptions.None, BitmapCacheOption.Default);
+                    if (decoder.Frames.Count > 0)
+                    {
+                        frame = decoder.Frames[0];
+                    }
+                    if (frame != null)
+                    {
+                        imageData = new byte[frame.PixelWidth * frame.PixelHeight * 4];
+                        if (frame.Format != PixelFormats.Bgra32)
                         {
-                            frame = decoder.Frames[0];
+                            FormatConvertedBitmap covert = new FormatConvertedBitmap(frame, PixelFormats.Bgra32, frame.Palette, 0);
+                            covert.CopyPixels(imageData, frame.PixelWidth * 4, 0);
                         }
-                        if (frame != null)
+                        else
                         {
-                            imageData = new byte[frame.PixelWidth * frame.PixelHeight * 4];
-                            if (frame.Format != PixelFormats.Bgra32)
-                            {
-                                FormatConvertedBitmap covert = new FormatConvertedBitmap(frame, PixelFormats.Bgra32, frame.Palette, 0);
-                                covert.CopyPixels(imageData, frame.PixelWidth * 4, 0);
-                            }
-                            else
-                            {
-                                frame.CopyPixels(imageData, frame.PixelWidth * 4, 0);
-                            }
-                            imageWidth = frame.PixelWidth;
-                            imageHeight = frame.PixelHeight;
+                            frame.CopyPixels(imageData, frame.PixelWidth * 4, 0);
                         }
-
-                        imageArea.ReplaceImageArea(imageArea.GetFrame(), imageData, imageWidth, imageHeight);
-                        pdfContentEditControl.RefreshThumb();
-                        UpdateImageArea(imageArea);
+                        imageWidth = frame.PixelWidth;
+                        imageHeight = frame.PixelHeight;
                     }
+
+                    Rect oldRect = DataConversionForWPF.CRectConversionForRect(imageArea.GetFrame());
+                    imageArea.ReplaceImageArea(imageArea.GetFrame(), imageData, imageWidth, imageHeight);
+                    pdfContentEditControl.RefreshThumb();
+                    UpdateEditArea(oldRect, imageArea);
                 }
             };
             menu.Items.Add(replaceMenu);
@@ -989,9 +1049,10 @@ namespace ComPDFKit.Controls.PDFControl
             horizonMirror.Header = LanguageHelper.CommonManager.GetString("Menu_HFlip");
             horizonMirror.Click += (o, p) =>
             {
-                imageArea?.HorizontalMirror();
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(imageArea.GetFrame());
+                imageArea.HorizontalMirror();
                 pdfContentEditControl.RefreshThumb();
-                UpdateImageArea(imageArea);
+                UpdateEditArea(oldRect, imageArea);
             };
             menu.Items.Add(horizonMirror);
 
@@ -1001,9 +1062,10 @@ namespace ComPDFKit.Controls.PDFControl
             {
                 if (imageArea != null)
                 {
-                    imageArea?.VerticalMirror();
+                    Rect oldRect = DataConversionForWPF.CRectConversionForRect(imageArea.GetFrame());
+                    imageArea.VerticalMirror();
                     pdfContentEditControl.RefreshThumb();
-                    UpdateImageArea(imageArea);
+                    UpdateEditArea(oldRect, imageArea);
                 }
             };
             menu.Items.Add(verticalMirror);
@@ -1017,12 +1079,77 @@ namespace ComPDFKit.Controls.PDFControl
                     PdfViewControl.PDFViewTool.SetCropMode(!PdfViewControl.PDFViewTool.GetIsCropMode());
                 }
             };
+
             menu.Items.Add(cropMenu);
+        }
+
+        private void CreatePathEditMenu(object sender, ref ContextMenu menu)
+        {
+            int index = -1;
+            CPDFEditPathArea pathArea = PdfViewControl.PDFToolManager.GetSelectedEditAreaObject(ref index) as CPDFEditPathArea;
+            if (pathArea == null)
+                return;
 
             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 });
+
+            MenuItem rotateLeftMenu = new MenuItem();
+            rotateLeftMenu.Header = LanguageHelper.CommonManager.GetString("Menu_RotateLeft");
+            rotateLeftMenu.Click += (o, p) =>
+            {
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(pathArea.GetFrame());
+                pathArea.Rotate(90);
+                UpdateEditArea(oldRect, pathArea);
+            };
+            menu.Items.Add(rotateLeftMenu);
+
+            MenuItem rotateRightMenu = new MenuItem();
+            rotateRightMenu.Header = LanguageHelper.CommonManager.GetString("Menu_RotateRight");
+            rotateRightMenu.Click += (o, p) =>
+            {
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(pathArea.GetFrame());
+                pathArea.Rotate(-90);
+                UpdateEditArea(oldRect, pathArea);
+            };
+            menu.Items.Add(rotateRightMenu);
+
+            MenuItem opacityMenu = new MenuItem();
+            opacityMenu.Header = LanguageHelper.CommonManager.GetString("Menu_Opacity");
+            menu.Items.Add(opacityMenu);
+            AppendOpacityMenu(opacityMenu, pathArea, CPDFEditType.EditPath);
+
+            MenuItem horizonMirror = new MenuItem();
+            horizonMirror.Header = LanguageHelper.CommonManager.GetString("Menu_HFlip");
+            horizonMirror.Click += (o, p) =>
+            {
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(pathArea.GetFrame());
+                pathArea.HorizontalMirror();
+                UpdateEditArea(oldRect, pathArea);
+            };
+            menu.Items.Add(horizonMirror);
+
+            MenuItem verticalMirror = new MenuItem();
+            verticalMirror.Header = LanguageHelper.CommonManager.GetString("Menu_VFlip");
+            verticalMirror.Click += (o, p) =>
+            {
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(pathArea.GetFrame());
+                pathArea.VerticalMirror();
+                UpdateEditArea(oldRect, pathArea);
+            };
+            menu.Items.Add(verticalMirror);
+
+            MenuItem cropMenu = new MenuItem();
+            cropMenu.Header = LanguageHelper.CommonManager.GetString("Menu_Crop");
+            cropMenu.Click += (o, p) =>
+            {
+                if (pathArea != null)
+                {
+                    PdfViewControl.PDFViewTool.SetCropMode(!PdfViewControl.PDFViewTool.GetIsCropMode());
+                }
+            };
+            menu.Items.Add(cropMenu);
         }
 
         private void CreateMultiTextEditMenu(object sender, ref ContextMenu menu)

+ 9 - 3
Demo/Examples/Compdfkit.Controls/Edit/PDFContentEditControl.xaml.cs

@@ -8,9 +8,9 @@ namespace ComPDFKit.Controls.Edit
     public partial class PDFContentEditControl : UserControl
     {
         #region  
-
         private PDFImageEditControl PDFImageEditControl = new PDFImageEditControl();
         private PDFTextEditControl PDFTextEditControl = new PDFTextEditControl();
+        private PDFPathEditControl PDFPathEditControl = new PDFPathEditControl();
 
         public PDFViewControl ViewControl { get; private set; }
         public PDFEditParam EditEvent { get; set; }
@@ -24,10 +24,11 @@ namespace ComPDFKit.Controls.Edit
         public void InitWithPDFViewer(PDFViewControl newPDFView)
         {
             ViewControl = newPDFView;
-            PDFImageEditControl.InitWithPDFViewer(newPDFView.PDFViewTool);
             PDFTextEditControl.InitWithPDFViewer(newPDFView.PDFViewTool);
+            PDFImageEditControl.InitWithPDFViewer(newPDFView.PDFViewTool);
+            PDFPathEditControl.InitWithPDFViewer(newPDFView.PDFViewTool);
         }
-         
+
         public void SetRotationText(float rotation)
         {
             PDFImageEditControl.SetRotationText(rotation);
@@ -66,6 +67,11 @@ namespace ComPDFKit.Controls.Edit
             ContentEditContainer.Child = PDFImageEditControl;
         }
 
+        public void SetPDFPathEditData(List<PathEditParam> editEvent)
+        {
+            PDFPathEditControl.SetPDFPathEditData(editEvent);
+            ContentEditContainer.Child = PDFPathEditControl;
+        }
 
         //public void SetPDFImageMultiEditData(List<PDFEditEvent> editEventList)
         //{

+ 0 - 14
Demo/Examples/Compdfkit.Controls/Edit/PDFImageEdit/PDFImageUI/CPDFImageFlipUI.xaml.cs

@@ -12,20 +12,6 @@ namespace ComPDFKit.Controls.Edit
             InitializeComponent();
         }
 
-        #region Property
-        public Orientation Orientation
-        {
-            get
-            {
-                return ImageFlipUI.Orientation;
-            }
-            set
-            {
-                ImageFlipUI.Orientation = value;
-            }
-        }
-        #endregion
-
         #region UI Event
         private void FlipVertical_Click(object sender, RoutedEventArgs e)
         {

+ 2 - 2
Demo/Examples/Compdfkit.Controls/Edit/PDFImageEdit/PDFImageUI/CPDFImageRotateUI.xaml.cs

@@ -31,12 +31,12 @@ namespace ComPDFKit.Controls.Edit
 
         private void RotateLeftBtn_Click(object sender, RoutedEventArgs e)
         {
-            RotationChanged?.Invoke(this, -90);
+            RotationChanged?.Invoke(this, 90);
         }
 
         private void RotateRightBtn_Click(object sender, RoutedEventArgs e)
         {
-            RotationChanged?.Invoke(this, 90);
+            RotationChanged?.Invoke(this, -90);
         }
 
         #endregion 

+ 122 - 0
Demo/Examples/Compdfkit.Controls/Edit/PDFPathEdit/PDFPathEditControl/PDFPathEditControl.xaml

@@ -0,0 +1,122 @@
+<UserControl x:Class="ComPDFKit.Controls.Edit.PDFPathEditControl"
+             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.Edit"
+             xmlns:common="clr-namespace:ComPDFKit.Controls.Common"
+             mc:Ignorable="d" 
+             d:DesignHeight="720" d:DesignWidth="280" MinWidth="260" Padding="10"
+             Background="#FAFCFF">
+    <UserControl.Resources>
+        <ResourceDictionary>
+            <ResourceDictionary.MergedDictionaries>
+                <ResourceDictionary Source="../../../Asset/Styles/ButtonStyle.xaml"></ResourceDictionary>
+                <ResourceDictionary Source="../../../Asset/Styles/SliderStyle.xaml"></ResourceDictionary>
+            </ResourceDictionary.MergedDictionaries>
+            <common:PropertyPanelResourceConverter x:Key="PropertyPanelResourceConverter"></common:PropertyPanelResourceConverter>
+            <common:CommonResourceConverter x:Key="CommonResourceConverter" />
+        </ResourceDictionary>
+    </UserControl.Resources>
+    <ScrollViewer VerticalScrollBarVisibility="Auto">
+        <StackPanel>
+            <Border Background="White" Height="36">
+                <TextBlock FontSize="14" FontWeight="Bold" HorizontalAlignment="Center" Foreground="#42464D" VerticalAlignment="Center" Text="Path属性"></TextBlock>
+            </Border>
+
+            <StackPanel Grid.Row="1">
+                <TextBlock Margin="0,20,0,0" Foreground="#0E1114" FontSize="14"
+                       Text="边框颜色"></TextBlock>
+                <common:ColorPickerControl x:Name="StrokeColorUI" Grid.Row="1" Margin="0,20,0,0" TransparentBtnProperty="Collapsed"></common:ColorPickerControl>
+                <TextBlock Margin="0,20,0,0" Foreground="#0E1114" FontSize="14"
+                       Text="填充颜色"></TextBlock>
+
+                <common:ColorPickerControl x:Name="FillColorUI" Grid.Row="1" Margin="0,20,0,0" TransparentBtnProperty="Collapsed"></common:ColorPickerControl>
+            </StackPanel>
+
+            <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>
+
+                <Slider Style="{StaticResource SliderStyle}" Grid.Row="1" Width="148" Height="28"
+                    Name="PathOpacitySlider" 
+                    Value="14"  
+                    IsSelectionRangeEnabled="True" 
+                    IsMoveToPointEnabled="True" 
+                    Margin="2,20,2,0"  
+                    Maximum="1" 
+                    Minimum="0" 
+                    TickFrequency="0.01"
+                    IsSnapToTickEnabled="True" 
+                    Thumb.DragCompleted="SliderOpacity_DragCompleted"
+                    Thumb.DragStarted="Slider_DragStarted"
+                    ValueChanged="SliderOpacity_ValueChanged"
+                    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"
+                              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"
+                             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>
+                </Grid>
+            </Grid>
+
+            <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="PathClipBtn" Grid.Column="1" Width="40" Height="25" BorderThickness="0" Click="PathClipBtn_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 
+                                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>
+        </StackPanel>
+    </ScrollViewer>
+</UserControl>

+ 604 - 0
Demo/Examples/Compdfkit.Controls/Edit/PDFPathEdit/PDFPathEditControl/PDFPathEditControl.xaml.cs

@@ -0,0 +1,604 @@
+using ComPDFKit.Import;
+using ComPDFKit.PDFDocument;
+using ComPDFKit.PDFPage;
+using ComPDFKit.PDFPage.Edit;
+using ComPDFKit.Tool;
+using ComPDFKit.Tool.UndoManger;
+using ComPDFKit.Viewer.Helper;
+using ComPDFKitViewer;
+using System;
+using System.Collections.Generic;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+using System.Windows.Input;
+using ComPDFKit.Tool.DrawTool;
+using ComPDFKitViewer.Helper;
+using System.Linq;
+using System.ComponentModel;
+using System.Runtime.CompilerServices;
+using ComPDFKit.Tool.SettingParam;
+using System.Windows.Media;
+
+namespace ComPDFKit.Controls.Edit
+{
+    public partial class PDFPathEditControl : UserControl, INotifyPropertyChanged
+    {
+        #region property
+        public CPDFViewerTool ToolView { get; set; }
+        public List<PathEditParam> EditEvents { get; set; } = new List<PathEditParam>();
+
+        private Visibility _onlySingleVisible = Visibility.Collapsed;
+        public Visibility OnlySingleVisible
+        {
+            get => _onlySingleVisible;
+            set => UpdateProper(ref _onlySingleVisible, value);
+        }
+
+        #endregion 
+
+        public PDFPathEditControl()
+        {
+            DataContext = this;
+            InitializeComponent();
+            Loaded += PDPathEditControl_Loaded;
+            Unloaded += PDFPathEditControl_Unloaded;
+        }
+
+        #region Load unload custom control
+
+        private void PDPathEditControl_Loaded(object sender, RoutedEventArgs e)
+        {
+            RotateUI.RotationChanged -= RotateUI_RotationChanged;
+            FlipUI.FlipChanged -= FlipUI_FlipChanged;
+            RotateUI.RotationChanged += RotateUI_RotationChanged;
+            FlipUI.FlipChanged += FlipUI_FlipChanged;
+            ToolView.SelectedDataChanged -= ToolView_SelectedDataChanged;
+            ToolView.SelectedDataChanged += ToolView_SelectedDataChanged;
+
+            StrokeColorUI.ColorChanged -= StrokeColorUI_ColorChanged;
+            StrokeColorUI.ColorChanged += StrokeColorUI_ColorChanged;
+
+            FillColorUI.ColorChanged -= FillColorUI_ColorChanged;
+            FillColorUI.ColorChanged += FillColorUI_ColorChanged;
+        }
+
+        private void StrokeColorUI_ColorChanged(object sender, EventArgs e)
+        {
+            SolidColorBrush newBrush = StrokeColorUI.Brush as SolidColorBrush;
+            GetPathArea(out List<CPDFEditPathArea> pathAreas, out CPDFPage pdfPage, out CPDFEditPage editPage);
+            if (pathAreas.Count == 0 || pdfPage == null || editPage == null)
+                return;
+
+            if (ToolView.CurrentEditAreaObject() != null)
+            {
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(pathAreas[0].GetFrame());
+                bool result = pathAreas[0].SetStrokeColor(new byte[] { newBrush.Color.R, newBrush.Color.G, newBrush.Color.B});
+                if (result)
+                {
+                    PDFEditHistory editHistory = new PDFEditHistory();
+                    editHistory.EditPage = editPage;
+                    editHistory.PageIndex = pdfPage.PageIndex;
+                    ToolView.GetCPDFViewer().UndoManager.AddHistory(editHistory);
+                    ToolView.UpdateRender(oldRect, pathAreas[0]);
+                }
+            }
+            else
+            {
+                GroupHistory groupHistory = new GroupHistory();
+                foreach (CPDFEditPathArea pathArea in pathAreas)
+                {
+                    if (pathArea.SetStrokeColor(new byte[] { 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(groupHistory);
+                    ToolView.GetCPDFViewer()?.UpdateRenderFrame();
+                }
+            }
+
+            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;
+                EditEvents.FirstOrDefault().StrokeColor = Color;
+                DefaultSettingParam defaultSettingParam = ToolView.GetDefaultSettingParam();
+                defaultSettingParam.SetPDFEditParamm(EditEvents.FirstOrDefault());
+            }
+        }
+
+        private void FillColorUI_ColorChanged(object sender, EventArgs e)
+        {
+            SolidColorBrush newBrush = FillColorUI.Brush as SolidColorBrush;
+            GetPathArea(out List<CPDFEditPathArea> pathAreas, out CPDFPage pdfPage, out CPDFEditPage editPage);
+            if (pathAreas.Count == 0 || pdfPage == null || editPage == null)
+                return;
+
+            if (ToolView.CurrentEditAreaObject() != null)
+            {
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(pathAreas[0].GetFrame());
+                bool result = pathAreas[0].SetFillColor(new byte[] { newBrush.Color.R, newBrush.Color.G, newBrush.Color.B });
+                if (result)
+                {
+                    PDFEditHistory editHistory = new PDFEditHistory();
+                    editHistory.EditPage = editPage;
+                    editHistory.PageIndex = pdfPage.PageIndex;
+                    ToolView.GetCPDFViewer().UndoManager.AddHistory(editHistory);
+                    ToolView.UpdateRender(oldRect, pathAreas[0]);
+                }
+            }
+            else
+            {
+                GroupHistory groupHistory = new GroupHistory();
+                foreach (CPDFEditPathArea pathArea in pathAreas)
+                {
+                    if (pathArea.SetFillColor(new byte[] { 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(groupHistory);
+                    ToolView.GetCPDFViewer()?.UpdateRenderFrame();
+                }
+            }
+
+            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;
+                EditEvents.FirstOrDefault().FillColor = Color;
+                DefaultSettingParam defaultSettingParam = ToolView.GetDefaultSettingParam();
+                defaultSettingParam.SetPDFEditParamm(EditEvents.FirstOrDefault());
+            }
+        }
+
+        private void PDFPathEditControl_Unloaded(object sender, RoutedEventArgs e)
+        {
+            RotateUI.RotationChanged -= RotateUI_RotationChanged;
+            FlipUI.FlipChanged -= FlipUI_FlipChanged;
+        }
+
+        #endregion
+
+        #region Property changed
+
+        private void PathCut()
+        {
+            GetPathArea(out List<CPDFEditPathArea> pathAreas, out CPDFPage pdfPage, out CPDFEditPage editPage);
+            if (pathAreas.Count == 0 || pdfPage == null || editPage == null)
+                return;
+
+            SelectedRect selectedRect = ToolView.GetSelectedRectForEditAreaObject(pathAreas[0]);
+            if (selectedRect == null)
+                return;
+
+            Rect oldRect = DataConversionForWPF.CRectConversionForRect(pathAreas[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 (pathAreas[0].CutWithRect(newCRect))
+            {
+                PDFEditHistory editHistory = new PDFEditHistory();
+                editHistory.EditPage = editPage;
+                editHistory.PageIndex = pdfPage.PageIndex;
+
+                ToolView.GetCPDFViewer().UndoManager.AddHistory(editHistory);
+                ToolView.UpdateRender(oldRect, pathAreas[0]);
+            }
+
+            editPage.EndEdit();
+        }
+
+        private void ToolView_SelectedDataChanged(object sender, SelectedAnnotData e)
+        {
+            if (ToolView.GetIsCropMode())
+            {
+                PathCut();
+            }
+        }
+
+        #endregion
+
+        #region Init PDFViewer
+        public void InitWithPDFViewer(CPDFViewerTool newPDFView)
+        {
+            ToolView = newPDFView;
+        }
+        #endregion
+
+        #region public method
+
+        //public void SetRotationText(float rotation)
+        //{
+        //    RotationTxb.Text = rotation.ToString(CultureInfo.CurrentCulture);
+        //}
+
+        #endregion
+
+        #region Path Edit
+
+        private void SetPathTransparency(double transparency)
+        {
+            PathOpacitySlider.Value = transparency / 255D;
+            OpacityTextBox.Text = string.Format("{0}%", (int)(Math.Round(PathOpacitySlider.Value * 100)));
+        }
+
+        public void SetPDFPathEditData(List<PathEditParam> newEvents)
+        {
+            EditEvents = newEvents.Where(newEvent => newEvent.EditIndex >= 0 && newEvent.EditType == CPDFEditType.EditPath).ToList();
+            if (EditEvents.Count == 0)
+                return;
+
+            PathEditParam defaultEvent = EditEvents.FirstOrDefault();
+
+            SetPathTransparency(defaultEvent.Transparency);
+            RotationTxb.Text = defaultEvent.Rotate.ToString();
+
+            StrokeColorUI.SetCheckedForColor(Color.FromRgb(
+            defaultEvent.StrokeColor[0],
+            defaultEvent.StrokeColor[1],
+            defaultEvent.StrokeColor[2]));
+
+            FillColorUI.SetCheckedForColor(Color.FromRgb(
+            defaultEvent.FillColor[0],
+            defaultEvent.FillColor[1],
+            defaultEvent.FillColor[2]));
+
+            if (EditEvents.Count == 1)
+            {
+                OnlySingleVisible = Visibility.Visible;
+            }
+            else
+            {
+                OnlySingleVisible = Visibility.Collapsed;
+            }
+        }
+
+        #endregion
+
+        #region Property changed
+
+        private void FlipUI_FlipChanged(object sender, bool e)
+        {
+            GetPathArea(out List<CPDFEditPathArea> pathAreas, out CPDFPage pdfPage, out CPDFEditPage editPage);
+            if (pathAreas.Count == 0 || pdfPage == null || editPage == null)
+                return;
+
+            if (ToolView.CurrentEditAreaObject() != null)
+            {
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(pathAreas[0].GetFrame());
+                bool result;
+                if (e)
+                {
+                    result = pathAreas[0].VerticalMirror();
+                }
+                else
+                {
+                    result = pathAreas[0].HorizontalMirror();
+                }
+
+                if (result)
+                {
+                    PDFEditHistory editHistory = new PDFEditHistory();
+                    editHistory.EditPage = editPage;
+                    editHistory.PageIndex = pdfPage.PageIndex;
+                    ToolView.GetCPDFViewer().UndoManager.AddHistory(editHistory);
+                    ToolView.UpdateRender(oldRect, pathAreas[0]);
+                }
+            }
+            else
+            {
+                GroupHistory groupHistory = new GroupHistory();
+                foreach (CPDFEditPathArea pathArea in pathAreas)
+                {
+                    bool result;
+                    if (e)
+                    {
+                        result = pathArea.VerticalMirror();
+                    }
+                    else
+                    {
+                        result = pathArea.HorizontalMirror();
+                    }
+
+                    if (result)
+                    {
+                        PDFEditHistory editHistory = new PDFEditHistory();
+                        editHistory.EditPage = editPage;
+                        editHistory.PageIndex = pdfPage.PageIndex;
+                        groupHistory.Histories.Add(editHistory);
+                    }
+                }
+
+                ToolView.GetCPDFViewer()?.UndoManager.AddHistory(groupHistory);
+                ToolView.GetCPDFViewer()?.UpdateRenderFrame();
+            }
+
+            editPage.EndEdit();
+        }
+
+        private void RotateUI_RotationChanged(object sender, double e)
+        {
+            GetPathArea(out List<CPDFEditPathArea> pathAreas, out CPDFPage pdfPage, out CPDFEditPage editPage);
+            if (pathAreas.Count == 0 || pdfPage == null || editPage == null)
+                return;
+
+            if (ToolView.CurrentEditAreaObject() != null)
+            {
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(pathAreas[0].GetFrame());
+                if (pathAreas[0].Rotate((int)e))
+                {
+                    PDFEditHistory editHistory = new PDFEditHistory();
+                    editHistory.EditPage = editPage;
+                    editHistory.PageIndex = pdfPage.PageIndex;
+                    ToolView.GetCPDFViewer().UndoManager.AddHistory(editHistory);
+                    ToolView.UpdateRender(oldRect, pathAreas[0]);
+                }
+            }
+            else
+            {
+                GroupHistory groupHistory = new GroupHistory();
+                foreach (CPDFEditPathArea pathArea in pathAreas)
+                {
+                    if (pathArea.Rotate((int)e))
+                    {
+                        PDFEditHistory editHistory = new PDFEditHistory();
+                        editHistory.EditPage = editPage;
+                        editHistory.PageIndex = pdfPage.PageIndex;
+                        groupHistory.Histories.Add(editHistory);
+                    }
+                }
+
+                ToolView.GetCPDFViewer()?.UndoManager.AddHistory(groupHistory);
+                ToolView.GetCPDFViewer()?.UpdateRenderFrame();
+            }
+
+            editPage.EndEdit();
+            RotationTxb.Text = pathAreas.FirstOrDefault().GetRotation().ToString();
+        }
+
+        private void Slider_DragStarted(object sender, DragStartedEventArgs e)
+        {
+            Slider slider = sender as Slider;
+            if (slider != null)
+            {
+                slider.Tag = "false";
+            }
+        }
+
+        private void SliderOpacity_DragCompleted(object sender, DragCompletedEventArgs e)
+        {
+            Slider slider = sender as Slider;
+            if (slider != null)
+            {
+                slider.Tag = "true";
+            }
+
+            GetPathArea(out List<CPDFEditPathArea> pathAreas, out CPDFPage pdfPage, out CPDFEditPage editPage);
+            if (pathAreas.Count == 0 || pdfPage == null || editPage == null)
+                return;
+
+            if (ToolView.CurrentEditAreaObject() != null)
+            {
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(pathAreas[0].GetFrame());
+                if (pathAreas[0].SetTransparency((byte)(PathOpacitySlider.Value * 255)))
+                {
+                    PDFEditHistory editHistory = new PDFEditHistory();
+                    editHistory.EditPage = editPage;
+                    editHistory.PageIndex = pdfPage.PageIndex;
+                    ToolView.GetCPDFViewer().UndoManager.AddHistory(editHistory);
+                    ToolView.UpdateRender(oldRect, pathAreas[0]);
+                }
+            }
+            else
+            {
+                GroupHistory groupHistory = new GroupHistory();
+                foreach (CPDFEditPathArea pathArea in pathAreas)
+                {
+                    if (pathArea.SetTransparency((byte)(PathOpacitySlider.Value * 255)))
+                    {
+                        PDFEditHistory editHistory = new PDFEditHistory();
+                        editHistory.EditPage = editPage;
+                        editHistory.PageIndex = pdfPage.PageIndex;
+                        groupHistory.Histories.Add(editHistory);
+                    }
+                }
+
+                ToolView.GetCPDFViewer()?.UndoManager.AddHistory(groupHistory);
+                ToolView.GetCPDFViewer()?.UpdateRenderFrame();
+            }
+
+            editPage.EndEdit();
+        }
+
+        private void SliderOpacity_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
+        {
+            Slider slider = sender as Slider;
+            if (OpacityTextBox != null)
+            {
+                OpacityTextBox.Text = string.Format("{0}%", (int)(PathOpacitySlider.Value * 100));
+            }
+
+            if (slider != null && slider.Tag != null && slider.Tag.ToString() == "false")
+            {
+                return;
+            }
+
+            GetPathArea(out List<CPDFEditPathArea> pathAreas, out CPDFPage pdfPage, out CPDFEditPage editPage);
+            if (pathAreas.Count == 0 || pdfPage == null || editPage == null)
+                return;
+
+            if (ToolView.CurrentEditAreaObject() != null)
+            {
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(pathAreas[0].GetFrame());
+                if (pathAreas[0].SetTransparency((byte)(PathOpacitySlider.Value * 255)))
+                {
+                    PDFEditHistory editHistory = new PDFEditHistory();
+                    editHistory.EditPage = editPage;
+                    editHistory.PageIndex = pdfPage.PageIndex;
+                    ToolView.GetCPDFViewer().UndoManager.AddHistory(editHistory);
+                    ToolView.UpdateRender(oldRect, pathAreas[0]);
+                }
+            }
+            else
+            {
+                GroupHistory groupHistory = new GroupHistory();
+                foreach (CPDFEditPathArea pathArea in pathAreas)
+                {
+                    if (pathArea.SetTransparency((byte)(PathOpacitySlider.Value * 255)))
+                    {
+                        PDFEditHistory editHistory = new PDFEditHistory();
+                        editHistory.EditPage = editPage;
+                        editHistory.PageIndex = pdfPage.PageIndex;
+                        groupHistory.Histories.Add(editHistory);
+                    }
+                }
+
+                ToolView.GetCPDFViewer()?.UndoManager.AddHistory(groupHistory);
+                ToolView.GetCPDFViewer()?.UpdateRenderFrame();
+            }
+
+            editPage.EndEdit();
+        }
+
+        private void PathClipBtn_Click(object sender, RoutedEventArgs e)
+        {
+            ToolView.SetCropMode(!ToolView.GetIsCropMode());
+        }
+
+        private void OpacityComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
+        {
+            ComboBoxItem selectItem = OpacityComboBox.SelectedItem as ComboBoxItem;
+            if (selectItem != null && selectItem.Content != null)
+            {
+                if (double.TryParse(selectItem.Content.ToString().TrimEnd('%'), out double newOpacity))
+                {
+                    OpacityTextBox.Text = selectItem.Content.ToString();
+                    PathOpacitySlider.Value = newOpacity / 100.0;
+                }
+            }
+        }
+
+        private void GetPathArea(out List<CPDFEditPathArea> pathAreas, out CPDFPage pdfPage, out CPDFEditPage editPage)
+        {
+            pathAreas = new List<CPDFEditPathArea>();
+            editPage = null;
+            pdfPage = null;
+            if (ToolView == null || EditEvents.Count == 0)
+            {
+                return;
+            }
+
+            try
+            {
+                foreach (var EditEvent in EditEvents)
+                {
+                    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)
+                    {
+                        pathAreas.Add(editAreas[EditEvent.EditIndex] as CPDFEditPathArea);
+                    }
+                }
+            }
+            catch (Exception ex)
+            {
+
+            }
+        }
+
+        private void SetAbsRotation(double absRotation)
+        {
+            GetPathArea(out List<CPDFEditPathArea> pathAreas, out CPDFPage pdfPage, out CPDFEditPage editPage);
+            if (pathAreas.Count == 0 || pdfPage == null || editPage == null)
+                return;
+
+            if (ToolView.CurrentEditAreaObject() != null)
+            {
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(pathAreas[0].GetFrame());
+                int rotation = (int)absRotation - pathAreas[0].GetRotation();
+                if (pathAreas[0].Rotate(rotation))
+                {
+                    PDFEditHistory editHistory = new PDFEditHistory();
+                    editHistory.EditPage = editPage;
+                    editHistory.PageIndex = pdfPage.PageIndex;
+                    ToolView.GetCPDFViewer().UndoManager.AddHistory(editHistory);
+                    ToolView.UpdateRender(oldRect, pathAreas[0]);
+                }
+            }
+            else
+            {
+                GroupHistory groupHistory = new GroupHistory();
+                foreach (CPDFEditPathArea pathArea in pathAreas)
+                {
+                    int rotation = (int)absRotation - pathArea.GetRotation();
+                    if (pathArea.Rotate(rotation))
+                    {
+                        PDFEditHistory editHistory = new PDFEditHistory();
+                        editHistory.EditPage = editPage;
+                        editHistory.PageIndex = pdfPage.PageIndex;
+                        groupHistory.Histories.Add(editHistory);
+                    }
+                }
+
+                ToolView.GetCPDFViewer()?.UndoManager.AddHistory(groupHistory);
+                ToolView.GetCPDFViewer()?.UpdateRenderFrame();
+            }
+
+            editPage.EndEdit();
+        }
+
+        private void RotationTxb_LostFocus(object sender, RoutedEventArgs e)
+        {
+            if (!double.TryParse(RotationTxb.Text, out double rotation))
+            {
+                return;
+            }
+            SetAbsRotation(rotation);
+        }
+
+        private void RotationTxb_PreviewKeyDown(object sender, KeyEventArgs e)
+        {
+            if (e.Key == Key.Enter)
+            {
+                RotationTxb_LostFocus(null, null);
+            }
+        }
+        #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));
+    }
+}

+ 5 - 4
Demo/Examples/Compdfkit.Controls/Edit/PDFTextEdit/PDFTextEditControl/PDFTextEditControl.xaml

@@ -93,12 +93,13 @@
 
                 <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:CPDFTextMarkupUI x:Name="TextMarkupUI" Grid.Row="4" FontSize="16" Margin="0,20,0,0" Width="200" HorizontalAlignment="Left"></local:CPDFTextMarkupUI>
 
-                    <CheckBox x:Name="chkEditPen" IsChecked="{Binding ShowBorder}" Content="Show Border" Margin="0,10,0,0" Click="chkEditPen_Click"></CheckBox>
+                <local:CPDFTextAlignUI x:Name="TextAlignUI" Grid.Row="5" FontSize="16" Margin="0,20,0,0" Width="150" HorizontalAlignment="Left"></local:CPDFTextAlignUI>
 
+                <StackPanel Grid.Row="6" Margin="0,20,0,0">
+                    <CheckBox x:Name="chkMulti" IsChecked="{Binding IsMultiSelected}" Content="Multi Selected" Click="chkMulti_Click"></CheckBox>
+                    <CheckBox x:Name="chkEditPen" IsChecked="{Binding ShowBorder}" Content="Show Border" Margin="0,10,0,0" Click="chkEditPen_Click"></CheckBox>
                 </StackPanel>
             </Grid>
         </Grid>

+ 131 - 29
Demo/Examples/Compdfkit.Controls/Edit/PDFTextEdit/PDFTextEditControl/PDFTextEditControl.xaml.cs

@@ -24,7 +24,6 @@ namespace ComPDFKit.Controls.Edit
         public CPDFViewerTool ToolView { get; private set; }
         public List<TextEditParam> EditEvents { get; set; }
 
-
         public event PropertyChangedEventHandler PropertyChanged;
 
         private bool _isMultiSelected = true;
@@ -53,7 +52,6 @@ namespace ComPDFKit.Controls.Edit
             DataContext = this;
             InitializeComponent();
             Loaded += PDFTextEditControl_Loaded;
-
         }
 
         #region Init PDFView
@@ -92,8 +90,11 @@ namespace ComPDFKit.Controls.Edit
                 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.Tag = "false";
                 FontOpacitySlider.Value = ((int)(Math.Ceiling(defaultEvent.Transparency * 100 / 255D))) / 100D;
+                FontOpacitySlider.Tag = "true";
+
                 TextAlignUI.SetFontAlign(defaultEvent.TextAlign);
                 if (defaultEvent.FontColor != null && defaultEvent.FontColor.Length == 3)
                 {
@@ -143,12 +144,7 @@ namespace ComPDFKit.Controls.Edit
 
         private void SliderOpacity_DragCompleted(object sender, DragCompletedEventArgs e)
         {
-            Slider slider = sender as Slider;
-            if (slider != null)
-            {
-                slider.Tag = "true";
-            }
-
+            FontOpacitySlider.Tag = "true";
             GetTextArea(out List<CPDFEditTextArea> textAreas, out CPDFPage pdfPage, out CPDFEditPage editPage);
             if (textAreas.Count == 0 || pdfPage == null || editPage == null)
                 return;
@@ -211,13 +207,12 @@ namespace ComPDFKit.Controls.Edit
 
         private void SliderOpacity_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
         {
-            Slider slider = sender as Slider;
             if (OpacityTextBox != null && FontOpacitySlider != null)
             {
-                OpacityTextBox.Text = string.Format("{0}%", (int)(FontOpacitySlider.Value * 100));
+                OpacityTextBox.Text = string.Format("{0}%", (int)(FontOpacitySlider.Value * 100D));
             }
 
-            if (slider != null && slider.Tag != null && slider.Tag.ToString() == "false")
+            if (FontOpacitySlider.Tag == null || FontOpacitySlider.Tag.ToString() == "false")
             {
                 return;
             }
@@ -284,24 +279,21 @@ namespace ComPDFKit.Controls.Edit
 
         private void Slider_DragStarted(object sender, DragStartedEventArgs e)
         {
-            Slider slider = sender as Slider;
-            if (slider != null)
-            {
-                slider.Tag = "false";
-            }
+            FontOpacitySlider.Tag = "false";
         }
         #endregion
 
         #region Loaded
         private void PDFTextEditControl_Loaded(object sender, RoutedEventArgs e)
         {
-
             TextStyleUI.TextFontChanged -= TextStyleUI_TextFontChanged;
             TextStyleUI.TextBoldChanged -= TextStyleUI_TextBoldChanged;
             TextStyleUI.TextItalicChanged -= TextStyleUI_TextItalicChanged;
             TextStyleUI.TextSizeChanged -= TextStyleUI_TextSizeChanged;
             TextAlignUI.TextAlignChanged -= TextAlignUI_TextAlignChanged;
             FontColorUI.ColorChanged -= FontColorUI_ColorChanged;
+            TextMarkupUI.TextUnderlineChanged -= TextMarkupUI_TextUnderlineChanged;
+            TextMarkupUI.TextStrikethroughChanged -= TextMarkupUI_TextStrikethroughChanged;
 
             TextStyleUI.TextFontChanged += TextStyleUI_TextFontChanged;
             TextStyleUI.TextBoldChanged += TextStyleUI_TextBoldChanged;
@@ -309,6 +301,8 @@ namespace ComPDFKit.Controls.Edit
             TextStyleUI.TextSizeChanged += TextStyleUI_TextSizeChanged;
             TextAlignUI.TextAlignChanged += TextAlignUI_TextAlignChanged;
             FontColorUI.ColorChanged += FontColorUI_ColorChanged;
+            TextMarkupUI.TextUnderlineChanged += TextMarkupUI_TextUnderlineChanged;
+            TextMarkupUI.TextStrikethroughChanged += TextMarkupUI_TextStrikethroughChanged;
 
             IsMultiSelected = ToolView.GetIsMultiSelected();
             ShowBorder = ToolView.GetEditPen() == null || ToolView.GetEditPen().Thickness != 0;
@@ -317,7 +311,6 @@ namespace ComPDFKit.Controls.Edit
         #endregion
 
         #region Property changed
-
         private void TextStyleUI_TextSizeChanged(object sender, double e)
         {
             GetTextArea(out List<CPDFEditTextArea> textAreas, out CPDFPage pdfPage, out CPDFEditPage editPage);
@@ -750,12 +743,129 @@ namespace ComPDFKit.Controls.Edit
             {
                 if (double.TryParse(selectItem.Content.ToString().TrimEnd('%'), out double newOpacity))
                 {
-                    OpacityTextBox.Text = selectItem.Content.ToString();
                     FontOpacitySlider.Value = newOpacity / 100.0;
                 }
             }
         }
 
+        private void TextMarkupUI_TextUnderlineChanged(object sender, bool e)
+        {
+            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;
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(textAreas[0].GetFrame());
+                if(e)
+                {
+                    result = textAreas[0].AddUnderline();
+                }
+                else
+                {
+                    result = textAreas[0].RemoveUnderline();
+                }
+
+                if (result)
+                {
+                    PDFEditHistory editHistory = new PDFEditHistory();
+                    editHistory.EditPage = editPage;
+                    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 (e)
+                    {
+                        result = textArea.AddUnderline();
+                    }
+                    else
+                    {
+                        result = textArea.RemoveUnderline();
+                    }
+
+                    if (result)
+                    {
+                        PDFEditHistory editHistory = new PDFEditHistory();
+                        editHistory.EditPage = editPage;
+                        editHistory.PageIndex = pdfPage.PageIndex;
+                        groupHistory.Histories.Add(editHistory);
+                    }
+                }
+
+                ToolView.GetCPDFViewer()?.UndoManager.AddHistory(groupHistory);
+                ToolView.GetCPDFViewer()?.UpdateRenderFrame();
+            }
+
+            editPage.EndEdit();
+        }
+
+        private void TextMarkupUI_TextStrikethroughChanged(object sender, bool e)
+        {
+            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;
+                Rect oldRect = DataConversionForWPF.CRectConversionForRect(textAreas[0].GetFrame());
+                if (e)
+                {
+                    result = textAreas[0].AddStrikethrough();
+                }
+                else
+                {
+                    result = textAreas[0].RemoveStrikethrough();
+                }
+
+                if (result)
+                {
+                    PDFEditHistory editHistory = new PDFEditHistory();
+                    editHistory.EditPage = editPage;
+                    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 (e)
+                    {
+                        result = textArea.AddStrikethrough();
+                    }
+                    else
+                    {
+                        result = textArea.RemoveStrikethrough();
+                    }
+
+                    if (result)
+                    {
+                        PDFEditHistory editHistory = new PDFEditHistory();
+                        editHistory.EditPage = editPage;
+                        editHistory.PageIndex = pdfPage.PageIndex;
+                        groupHistory.Histories.Add(editHistory);
+                    }
+                }
+
+                ToolView.GetCPDFViewer()?.UndoManager.AddHistory(groupHistory);
+                ToolView.GetCPDFViewer()?.UpdateRenderFrame();
+            }
+
+            editPage.EndEdit();
+        }
+
         #endregion
 
         #region Text Edit
@@ -768,6 +878,7 @@ namespace ComPDFKit.Controls.Edit
             {
                 return;
             }
+
             if (EditEvents != null && EditEvents.Count>0 )
             {
                 try
@@ -790,15 +901,6 @@ namespace ComPDFKit.Controls.Edit
 
                 }
             }
-            else
-            {
-                CPDFViewer pdfViewer = ToolView.GetCPDFViewer();
-                CPDFDocument pdfDoc = pdfViewer.GetDocument();
-                pdfPage = pdfDoc.PageAtIndex(0);
-                editPage = pdfPage.GetEditPage();
-                editPage.BeginEdit(CPDFEditType.EditText);
-                editPage.EndEdit();
-            }
         }
         #endregion
 

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 58 - 0
Demo/Examples/Compdfkit.Controls/Edit/PDFTextEdit/PDFTextEditUI/CPDFTextMarkupUI.xaml


+ 37 - 0
Demo/Examples/Compdfkit.Controls/Edit/PDFTextEdit/PDFTextEditUI/CPDFTextMarkupUI.xaml.cs

@@ -0,0 +1,37 @@
+using System;
+using System.Windows;
+using System.Windows.Controls;
+
+namespace ComPDFKit.Controls.Edit
+{
+    public partial class CPDFTextMarkupUI : UserControl
+    {
+        public event EventHandler<bool> TextUnderlineChanged;
+        public event EventHandler<bool> TextStrikethroughChanged;
+
+        public CPDFTextMarkupUI()
+        {
+            InitializeComponent();
+        }
+
+        private void AddUnderline_Click(object sender, RoutedEventArgs e)
+        {
+            TextUnderlineChanged?.Invoke(this, true);
+        }
+
+        private void RemoveUnderline_Click(object sender, RoutedEventArgs e)
+        {
+            TextUnderlineChanged?.Invoke(this, false);
+        }
+
+        private void AddStrikethrough_Click(object sender, RoutedEventArgs e)
+        {
+            TextStrikethroughChanged?.Invoke(this, true);
+        }
+
+        private void RemoveStrikethrough_Click(object sender, RoutedEventArgs e)
+        {
+            TextStrikethroughChanged?.Invoke(this, false);
+        }
+    }
+}

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

@@ -26,31 +26,33 @@ namespace ComPDFKit.Controls.Measure
     public partial class MeasureControl : UserControl
     {
         public MeasurePropertyControl measurePropertyControl = new MeasurePropertyControl();
+
         private CPDFDisplaySettingsControl displaySettingsControl;
 
         private PDFViewControl PdfViewControl = new PDFViewControl();
 
         private PanelState panelState = PanelState.GetInstance();
-        
+
         private CPDFAnnotation currentAnnot = null;
 
         public event EventHandler ExpandEvent;
         public event EventHandler OnAnnotEditHandler;
 
-
         public MeasureControl()
         {
             InitializeComponent();
         }
-        
+
         #region Init PDFViewer
 
         public void InitWithPDFViewer(PDFViewControl pdfViewControl)
         {
             PdfViewControl = pdfViewControl;
-            //PdfViewControl.PDFView = pdfViewer;
+            //PdfViewControl.PDFView = pdfViewer; 
+            measurePropertyControl.InitWithPDFViewer(pdfViewControl);
             PDFMeasureTool.InitWithPDFViewer(pdfViewControl, measurePropertyControl, this);
             FloatPageTool.InitWithPDFViewer(pdfViewControl);
+
             PDFGrid.Child = PdfViewControl;
 
             panelState.PropertyChanged -= PanelState_PropertyChanged;
@@ -65,9 +67,9 @@ namespace ComPDFKit.Controls.Measure
             PdfViewControl.MouseLeftButtonUpHandler += PDFToolManager_MouseLeftButtonUpHandler;
             PdfViewControl.MouseMoveHandler += PDFToolManager_MouseMoveHandler;
             pdfViewControl.MouseRightButtonDownHandler += PDFToolManager_MouseRightButtonDownHandler;
-            panelState.PropertyChanged += PanelState_PropertyChanged; 
+            panelState.PropertyChanged += PanelState_PropertyChanged;
             SetInfoPanelVisble(false, false);
-            SettingPanel.PdfViewControl= pdfViewControl;
+            SettingPanel.PdfViewControl = pdfViewControl;
         }
 
         private void MeasureSetting_MeasureChanged(object sender, MeasureEventArgs e)
@@ -102,7 +104,7 @@ namespace ComPDFKit.Controls.Measure
             }
             PdfViewControl.SetRightMenu(ContextMenu);
         }
-        
+
         private void CreateAnnotContextMenu(object sender, ref ContextMenu menu, C_ANNOTATION_TYPE annotType)
         {
             switch (annotType)
@@ -130,11 +132,11 @@ namespace ComPDFKit.Controls.Measure
                     break;
             }
         }
-        
+
         private void CreateMeasureContextMenu(object sender, ref ContextMenu menu)
         {
             menu.Items.Add(new MenuItem() { Header = LanguageHelper.CommonManager.GetString("Menu_Delete"), Command = ApplicationCommands.Delete, CommandTarget = (UIElement)sender });
-            
+
             MenuItem menuItem = new MenuItem();
             menuItem.Header = "Measurement Settings";
             menuItem.Click += (item, param) =>
@@ -146,7 +148,7 @@ namespace ComPDFKit.Controls.Measure
                 SetInfoPanelVisble(false, true);
             };
             menu.Items.Add(menuItem);
-            
+
             MenuItem propertyItem = new MenuItem();
             propertyItem.Header = "Properties";
             propertyItem.Click += (item, param) =>
@@ -155,12 +157,12 @@ namespace ComPDFKit.Controls.Measure
             };
             menu.Items.Add(propertyItem);
         }
-        
+
         private void CreateSelectTextContextMenu(object sender, ref ContextMenu menu)
         {
             menu.Items.Add(new MenuItem() { Header = LanguageHelper.CommonManager.GetString("Menu_Copy"), Command = ApplicationCommands.Copy, CommandTarget = (UIElement)sender });
         }
-        
+
         private void CreateSelectImageContextMenu(object sender, ref ContextMenu menu)
         {
             if (menu == null)
@@ -253,6 +255,7 @@ namespace ComPDFKit.Controls.Measure
 
         private void PDFToolManager_MouseMoveHandler(object sender, MouseEventObject e)
         {
+
         }
 
         private void PDFToolManager_MouseLeftButtonUpHandler(object sender, MouseEventObject e)
@@ -270,23 +273,23 @@ namespace ComPDFKit.Controls.Measure
             {
                 AnnotData annotData = baseAnnot.GetAnnotData();
                 AnnotParam annotParam = ParamConverter.CPDFDataConverterToAnnotParam(
-                    PdfViewControl.GetCPDFViewer().GetDocument(), annotData.PageIndex, annotData.Annot);
+                PdfViewControl.GetCPDFViewer().GetDocument(), annotData.PageIndex, annotData.Annot);
                 measurePropertyControl.SetPropertyForMeasureCreate(annotParam, annotData.Annot, PdfViewControl);
                 SetMeasureInfoPanel(annotData.Annot, annotParam);
                 currentAnnot = annotData.Annot;
-            }
+            } 
 
             panelState.RightPanel = PanelState.RightPanelState.PropertyPanel;
-            // measurePropertyControl.SetPropertyForMeasureCreate(LineArgs, e);
             SetInfoPanelVisble(true, false);
         }
 
-        private void SetMeasureInfoPanel(CPDFAnnotation annot,AnnotParam param = null)
+        private void SetMeasureInfoPanel(CPDFAnnotation annot, AnnotParam param = null)
         {
-            if (annot == null)
+            if (annot == null || !annot.IsValid())
             {
                 return;
             }
+
             try
             {
                 if (annot.Type == C_ANNOTATION_TYPE.C_ANNOTATION_LINE)
@@ -308,8 +311,8 @@ namespace ComPDFKit.Controls.Measure
                         SetMeasureInfoType(CPDFMeasureType.CPDF_PERIMETER_MEASURE);
                     }
                 }
-                
-                if(annot.Type== C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON)
+
+                if (annot.Type == C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON)
                 {
                     CPDFPolygonAnnotation Annot = annot as CPDFPolygonAnnotation;
                     CPDFAreaMeasure polygonMeasure = Annot.GetAreaMeasure();
@@ -317,7 +320,7 @@ namespace ComPDFKit.Controls.Measure
                     CPDFCaptionType CaptionType = measureInfo.CaptionType;
                     bool IsArea = false;
                     bool IsLength = false;
-                    if ((CaptionType& CPDFCaptionType.CPDF_CAPTION_AREA)== CPDFCaptionType.CPDF_CAPTION_AREA)
+                    if ((CaptionType & CPDFCaptionType.CPDF_CAPTION_AREA) == CPDFCaptionType.CPDF_CAPTION_AREA)
                     {
                         IsArea = true;
                     }
@@ -501,7 +504,7 @@ namespace ComPDFKit.Controls.Measure
             }
             SettingPanel.ReturnToInfoPanel = true;
             SetInfoPanelVisble(false, true);
-            if(currentAnnot != null)
+            if (currentAnnot != null)
             {
                 AnnotParam annotParam = ParamConverter.CPDFDataConverterToAnnotParam(
                     PdfViewControl.GetCPDFViewer().GetDocument(), currentAnnot.Page.PageIndex, currentAnnot);
@@ -511,7 +514,7 @@ namespace ComPDFKit.Controls.Measure
 
         private CPDFMeasureInfo GetMeasureInfoFromParam(AnnotParam param)
         {
-            if(param is LineMeasureParam lineParam)
+            if (param is LineMeasureParam lineParam)
             {
                 return lineParam.measureInfo;
             }
@@ -548,7 +551,7 @@ namespace ComPDFKit.Controls.Measure
         {
             InfoPanel?.SetMeasureType(measureType);
         }
-        
+
         public void SetBOTAContainer(CPDFBOTABarControl botaControl)
         {
             this.BotaContainer.Child = botaControl;
@@ -556,7 +559,7 @@ namespace ComPDFKit.Controls.Measure
 
         public void SetMeasureScale(CPDFMeasureType measureType, string scale)
         {
-            InfoPanel?.SetMeasureScale(measureType,scale);
+            InfoPanel?.SetMeasureScale(measureType, scale);
         }
     }
 }

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

@@ -2,20 +2,12 @@
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
-using System.Drawing.Drawing2D;
 using System.Globalization;
 using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 using System.Windows;
 using System.Windows.Controls;
-using System.Windows.Data;
-using System.Windows.Documents;
 using System.Windows.Input;
 using System.Windows.Media;
-using System.Windows.Media.Imaging;
-using System.Windows.Navigation;
-using System.Windows.Shapes;
 using ComPDFKit.Controls.Helper;
 using ComPDFKit.PDFAnnotation;
 using ComPDFKit.Tool;
@@ -92,7 +84,6 @@ namespace ComPDFKit.Controls.Measure
                 TypeConverter typeCovert = TypeDescriptor.GetConverter(typeof(Geometry));
                 MeasureIcon.Data = PathGeometry.CreateFromGeometry((Geometry)typeCovert.ConvertFrom(IconsDict.ElementAt(iconIndex).Value));
                 MeasureTitelText.Text = IconsDict.ElementAt(iconIndex).Key;
-
                 switch(newType)
                 {
                     case CPDFMeasureType.CPDF_DISTANCE_MEASURE:
@@ -136,6 +127,9 @@ namespace ComPDFKit.Controls.Measure
 
         public void SetMeasureInfo(CPDFAnnotation annot)
         {
+            if (annot == null || !annot.IsValid())
+                return;
+
             if (annot is CPDFLineAnnotation lineAnnot)
             {
                 SetLineMeasureInfo(lineAnnot);

+ 1 - 1
Demo/Examples/Compdfkit.Controls/Measure/MeasurePropertyControl.xaml

@@ -6,7 +6,7 @@
              xmlns:local="clr-namespace:ComPDFKit.Controls.Measure"
              xmlns:common="clr-namespace:ComPDFKit.Controls.Common"
              mc:Ignorable="d" 
-             d:DesignHeight="450" d:DesignWidth="800" Background="#FAFCFF">
+             d:DesignHeight="800" d:DesignWidth="300" Background="#FAFCFF">
     <Grid>
         <Grid.Resources>
             <common:PropertyPanelResourceConverter x:Key="PropertyPanelResourceConverter" />

+ 146 - 10
Demo/Examples/Compdfkit.Controls/Measure/MeasurePropertyControl.xaml.cs

@@ -16,15 +16,55 @@ using System.Windows.Media;
 using System.Windows.Media.Imaging;
 using System.Windows.Navigation;
 using System.Windows.Shapes;
+using ComPDFKitViewer;
 
 namespace ComPDFKit.Controls.Measure
 {
     public partial class MeasurePropertyControl : UserControl
     {
+        StraightnessProperty straightnessProperty = new StraightnessProperty();
+        MultilineProperty multilineProperty = new MultilineProperty();
+        PolygonalProperty polygonProperty = new PolygonalProperty();
+        AnnotParam currentParam = null;
+
+        public event EventHandler<LineMeasureParam> LineMeasureParamChanged;
+        public event EventHandler<PolyLineMeasureParam> PolyLineMeasureParamChanged;
+        public event EventHandler<PolygonMeasureParam> PolygonMeasureParamChanged;
+
+        public C_ANNOTATION_TYPE CurrentCreateType
+        {
+            get;
+            set;
+        } = C_ANNOTATION_TYPE.C_ANNOTATION_NONE;
+
         private UIElement currentPanel = null;
+
+        PDFViewControl pdfViewerControl;
+
+
+
         public MeasurePropertyControl()
         {
             InitializeComponent();
+            straightnessProperty.LineMeasureParamChanged -= StraightnessProperty_LineMeasureParamChanged;
+            multilineProperty.PolyLineMeasureParamChanged -= MultilineProperty_PolyLineMeasureParamChanged;
+            polygonProperty.PolygonMeasureParamChanged -= PolygonProperty_PolygonMeasureParamChanged;
+
+
+            multilineProperty.PolyLineMeasureParamChanged += MultilineProperty_PolyLineMeasureParamChanged;
+            straightnessProperty.LineMeasureParamChanged += StraightnessProperty_LineMeasureParamChanged;
+            polygonProperty.PolygonMeasureParamChanged += PolygonProperty_PolygonMeasureParamChanged; 
+        }
+
+        private void PolygonProperty_PolygonMeasureParamChanged(object sender, PolygonMeasureParam e)
+        {
+            PolygonMeasureParamChanged?.Invoke(this, e);
+        }
+
+        private void MultilineProperty_PolyLineMeasureParamChanged(object sender, PolyLineMeasureParam e)
+        {
+             PolyLineMeasureParamChanged?.Invoke(this, e);
+
         }
 
         public void SetPropertyForMeasureCreate(AnnotParam param, CPDFAnnotation annot, PDFViewControl viewControl)
@@ -34,41 +74,59 @@ namespace ComPDFKit.Controls.Measure
                 ClearMeasurePanel();
                 return;
             }
+            
+            if(annot == null)
+            {
+                CurrentCreateType = param.CurrentType;
+                currentParam = param;
+            }
 
             switch (param.CurrentType)
             {
                 case C_ANNOTATION_TYPE.C_ANNOTATION_LINE:
-                    StraightnessProperty straightnessProperty = new StraightnessProperty();
-                    if(param is LineMeasureParam lineMeasureParam)
                     {
-                        straightnessProperty.SetAnnotParam(lineMeasureParam, annot, viewControl);
+                        if (param is LineMeasureParam lineMeasureParam)
+                        {
+                            straightnessProperty.SetAnnotParam(lineMeasureParam, annot, viewControl);
+                            SetMeasurePanel(straightnessProperty);
+                            return;
+                        }
                     }
-                    currentPanel = straightnessProperty;
                     break;
+
                 case C_ANNOTATION_TYPE.C_ANNOTATION_POLYLINE:
-                    MultilineProperty multilineProperty = new MultilineProperty();
                     if (param is PolyLineMeasureParam polyLineMeasureParam)
                     {
                         multilineProperty.SetAnnotParam(polyLineMeasureParam, annot, viewControl);
+                        SetMeasurePanel(multilineProperty);
+                        return;
                     }
-                    currentPanel = multilineProperty;
                     break;
+
                 case C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON:
-                    PolygonalProperty polygonProperty = new PolygonalProperty();
-                    if (param is PolygonMeasureParam polygonMeasureParam)
+                    if (param is PolygonMeasureParam polygonMeasureParam && (annot ==null || (annot as CPDFPolygonAnnotation).IsMeasured()))
                     {
                         polygonProperty.SetAnnotParam(polygonMeasureParam, annot, viewControl);
+                        SetMeasurePanel(polygonProperty);
+                        return;
                     }
-                    currentPanel = polygonProperty;
                     break;
+
                 default:
                     break;
             }
-            SetMeasurePanel(currentPanel);
+
+            ClearMeasurePanel();
+        }
+
+        private void StraightnessProperty_LineMeasureParamChanged(object sender, LineMeasureParam e)
+        {
+            LineMeasureParamChanged?.Invoke(this, e);
         }
 
         private void SetMeasurePanel(UIElement newChild)
         {
+            currentPanel = newChild;
             MeasurePropertyPanel.Child = newChild;
         }
 
@@ -78,6 +136,84 @@ namespace ComPDFKit.Controls.Measure
             MeasurePropertyPanel.Child = null;
         }
 
+        internal void InitWithPDFViewer(PDFViewControl pdfViewControl)
+        {
+            if (this.pdfViewerControl != null)
+            {
+                UnLoadPDFViewHandler();
+            }
+            this.pdfViewerControl = pdfViewControl;
+            LoadPDFViewHandler();
+        }
+
+        private void LoadPDFViewHandler()
+        {
+            if (pdfViewerControl != null)
+            {
+                pdfViewerControl.MouseLeftButtonDown -= PdfViewerControl_MouseLeftButtonDown;
+                pdfViewerControl.MouseLeftButtonDown += PdfViewerControl_MouseLeftButtonDown; 
+            }
+        }
+
+        private void PdfViewerControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
+        {
+            SetAnnotEventData();
+        }
+
+        private void SetAnnotEventData()
+        {
+            if (pdfViewerControl.GetCacheHitTestAnnot() == null)
+            {
+                if (pdfViewerControl != null && (pdfViewerControl.PDFToolManager.GetToolType() == ToolType.CreateAnnot))
+                {
+                    switch (CurrentCreateType)
+                    {
+                        case  C_ANNOTATION_TYPE.C_ANNOTATION_LINE:
+                            straightnessProperty.Annotation = null;
+                            straightnessProperty.SetAnnotParam(currentParam as LineMeasureParam, null, pdfViewerControl);
+                            break;
+                        case C_ANNOTATION_TYPE.C_ANNOTATION_POLYLINE:
+                            multilineProperty.Annotation = null;
+                            multilineProperty.SetAnnotParam(currentParam as PolyLineMeasureParam, null, pdfViewerControl);
+                            break;
+                        case C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON:
+                            polygonProperty.Annotation = null;
+                            polygonProperty.SetAnnotParam(currentParam as PolygonMeasureParam, null, pdfViewerControl);
+                            break;
+                    }
+                    ShowCreateAnnotPanel();
+                }
+                else
+                {
+                    ClearMeasurePanel();
+                }
+            }
+        }
+
+        private void ShowCreateAnnotPanel()
+        {
+            switch (CurrentCreateType)
+            {
+                case C_ANNOTATION_TYPE.C_ANNOTATION_NONE:
+                    break;
+                case C_ANNOTATION_TYPE.C_ANNOTATION_LINE:
+                    currentPanel = straightnessProperty;
+                    break;
+                case C_ANNOTATION_TYPE.C_ANNOTATION_POLYGON:
+                    currentPanel = polygonProperty;
+                    break;
+                case C_ANNOTATION_TYPE.C_ANNOTATION_POLYLINE:
+                    currentPanel = multilineProperty;
+                    break;
+            }
+            SetMeasurePanel(currentPanel); 
+        }
+
+        private void UnLoadPDFViewHandler()
+        {
+
+        }
+
         //public void SetPorpertyForMeasureModify(AnnotAttribEvent annotEvent)
         //{
 

+ 2 - 1
Demo/Examples/Compdfkit.Controls/Measure/Property/MultilineProperty.xaml

@@ -7,6 +7,7 @@
              mc:Ignorable="d" 
              Loaded="UserControl_Loaded"
              Unloaded="UserControl_Unloaded"
+             d:DesignHeight="800" d:DesignWidth="300"
              >
     <UserControl.Resources>
         <ResourceDictionary>
@@ -20,7 +21,7 @@
         <Grid Background="#FAFCFF">
             <StackPanel Orientation="Vertical">
                 <Border BorderThickness="1" BorderBrush="#1A000000">
-                    <Grid  Height="40" Background="White" >
+                    <Grid Height="40" Background="White" >
                         <TextBlock x:Name="TitleTextBlock" Text="{Binding Converter={StaticResource PropertyPanelResourceConverter},ConverterParameter=Title_Appearance_M}"  HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="16" FontWeight="Bold" FontFamily="Segoe UI"></TextBlock>
                     </Grid>
                 </Border>

+ 101 - 37
Demo/Examples/Compdfkit.Controls/Measure/Property/MultilineProperty.xaml.cs

@@ -19,6 +19,8 @@ using System.Windows.Shapes;
 using ComPDFKit.Controls.PDFControl;
 using ComPDFKit.Tool;
 using CFontNameHelper = ComPDFKit.PDFAnnotation.CTextAttribute.CFontNameHelper;
+using System.Runtime.CompilerServices;
+using System.IO.Ports;
 
 namespace ComPDFKit.Controls.Measure.Property
 {
@@ -32,13 +34,14 @@ namespace ComPDFKit.Controls.Measure.Property
         };
 
         bool IsLoadedData = false;
-        
+
         private PolyLineMeasureParam polyLineMeasureParam;
-        
-        public CPDFPolylineAnnotation Annotation{ get; set; }
-        
-        public PDFViewControl ViewControl{ get; set; }
 
+        public CPDFPolylineAnnotation Annotation { get; set; }
+
+        public PDFViewControl ViewControl { get; set; }
+
+        public event EventHandler<PolyLineMeasureParam> PolyLineMeasureParamChanged;
         public MultilineProperty()
         {
             InitializeComponent();
@@ -48,6 +51,11 @@ namespace ComPDFKit.Controls.Measure.Property
         {
             if (IsLoadedData)
             {
+                if (Annotation == null)
+                {
+                    polyLineMeasureParam.Content = NoteTextBox.Text;
+                    PolyLineMeasureParamChanged?.Invoke(sender, polyLineMeasureParam);
+                }
                 if (Annotation != null && ViewControl != null)
                 {
                     Annotation.SetContent(NoteTextBox.Text);
@@ -85,7 +93,14 @@ namespace ComPDFKit.Controls.Measure.Property
                 default:
                     break;
             }
-            if(Annotation != null)
+            if (Annotation == null)
+            {
+                polyLineMeasureParam.IsBold = isBold;
+                polyLineMeasureParam.IsItalic = isItalic;
+                PolyLineMeasureParamChanged?.Invoke(sender, polyLineMeasureParam);
+            }
+
+            if (Annotation != null)
             {
                 CTextAttribute textAttribute = Annotation.GetTextAttribute();
                 var fontType = CFontNameHelper.GetFontType((FontCombox.SelectedItem as ComboBoxItem).Content.ToString());
@@ -101,9 +116,16 @@ namespace ComPDFKit.Controls.Measure.Property
         {
             if (IsLoadedData)
             {
+                ComboBoxItem selectItem = FontCombox.SelectedItem as ComboBoxItem;
+                if (Annotation == null)
+                {
+                    var fontType = CFontNameHelper.GetFontType(selectItem.Content.ToString());
+                    string FontName = CFontNameHelper.ObtainFontName(fontType, polyLineMeasureParam.IsBold, polyLineMeasureParam.IsItalic);
+                    polyLineMeasureParam.FontName = FontName;
+                    PolyLineMeasureParamChanged?.Invoke(sender, polyLineMeasureParam);
+                } 
                 if (Annotation != null && ViewControl != null)
                 {
-                    ComboBoxItem selectItem = FontCombox.SelectedItem as ComboBoxItem;
                     if (selectItem != null && selectItem.Content != null)
                     {
                         CTextAttribute textAttr = Annotation.GetTextAttribute();
@@ -125,6 +147,11 @@ namespace ComPDFKit.Controls.Measure.Property
             {
                 if (FontSizeComboBox.SelectedItem != null)
                 {
+                    if (Annotation == null)
+                    {
+                        polyLineMeasureParam.FontSize = (float)Convert.ToDouble(FontSizeComboBox.SelectedItem);
+                        PolyLineMeasureParamChanged?.Invoke(sender, polyLineMeasureParam);
+                    }
                     if (Annotation != null && ViewControl != null)
                     {
                         CTextAttribute textAttribute = Annotation.GetTextAttribute();
@@ -141,12 +168,18 @@ namespace ComPDFKit.Controls.Measure.Property
         {
             if (IsLoadedData)
             {
+                SolidColorBrush checkBrush = BorderColorPickerControl.GetBrush() as SolidColorBrush;
+                byte[] color = { checkBrush.Color.R, checkBrush.Color.G, checkBrush.Color.B };
+
+                if (Annotation == null)
+                {
+                    polyLineMeasureParam.LineColor = color;
+                    PolyLineMeasureParamChanged?.Invoke(sender, polyLineMeasureParam);
+                }
                 if (Annotation != null && ViewControl != null)
                 {
-                    SolidColorBrush checkBrush = BorderColorPickerControl.GetBrush() as SolidColorBrush;
                     if (checkBrush != null)
                     {
-                        byte[] color = { checkBrush.Color.R, checkBrush.Color.G, checkBrush.Color.B };
                         Annotation.SetLineColor(color);
                         Annotation.UpdateAp();
                         ViewControl.UpdateAnnotFrame();
@@ -159,9 +192,15 @@ namespace ComPDFKit.Controls.Measure.Property
         {
             if (IsLoadedData)
             {
+                double opacity = CPDFOpacityControl.OpacityValue / 100.0;
+
+                if (Annotation == null)
+                {
+                    polyLineMeasureParam.Transparency = (byte)(opacity * 255);
+                    PolyLineMeasureParamChanged?.Invoke(sender, polyLineMeasureParam);
+                }
                 if (Annotation != null && ViewControl != null)
                 {
-                    double opacity = CPDFOpacityControl.OpacityValue / 100.0;
                     if (opacity > 0 && opacity <= 1)
                     {
                         opacity = opacity * 255;
@@ -180,6 +219,11 @@ namespace ComPDFKit.Controls.Measure.Property
         {
             if (IsLoadedData)
             {
+                if (Annotation == null)
+                {
+                    polyLineMeasureParam.LineWidth = (byte)CPDFThicknessControl.Thickness;
+                    PolyLineMeasureParamChanged?.Invoke(sender, polyLineMeasureParam);
+                }
                 if (Annotation != null && ViewControl != null)
                 {
                     Annotation.SetLineWidth(CPDFThicknessControl.Thickness);
@@ -192,25 +236,35 @@ namespace ComPDFKit.Controls.Measure.Property
         private void CPDFLineStyleControl_LineStyleChanged(object sender, EventArgs e)
         {
             if (!IsLoadedData) return;
-            if (Annotation != null && ViewControl != null)
+            float[] dashArray = null;
+            C_BORDER_STYLE borderStyle;
+            if (CPDFLineStyleControl.DashStyle == DashStyles.Solid || CPDFLineStyleControl.DashStyle == null)
             {
-                float[] dashArray = null;
-                C_BORDER_STYLE borderStyle;
-                if (CPDFLineStyleControl.DashStyle == DashStyles.Solid || CPDFLineStyleControl.DashStyle == null)
+                dashArray = new float[0];
+                borderStyle = C_BORDER_STYLE.BS_SOLID;
+            }
+            else
+            {
+                List<float> floatArray = new List<float>();
+                foreach (double num in CPDFLineStyleControl.DashStyle.Dashes)
                 {
-                    dashArray = new float[0];
-                    borderStyle = C_BORDER_STYLE.BS_SOLID;
-                }
-                else
-                {
-                    List<float> floatArray = new List<float>();
-                    foreach (double num in CPDFLineStyleControl.DashStyle.Dashes)
-                    {
-                        floatArray.Add((float)num);
-                    }
-                    dashArray = floatArray.ToArray();
-                    borderStyle = C_BORDER_STYLE.BS_DASHDED;
+                    floatArray.Add((float)num);
                 }
+                dashArray = floatArray.ToArray();
+                borderStyle = C_BORDER_STYLE.BS_DASHDED;
+            }
+
+            if (Annotation == null)
+            {
+                polyLineMeasureParam.BorderStyle = borderStyle;
+                polyLineMeasureParam.LineDash = dashArray;
+
+                PolyLineMeasureParamChanged?.Invoke(sender, polyLineMeasureParam);
+            }
+
+            if (Annotation != null && ViewControl != null)
+            {
+
                 Annotation.SetBorderStyle(borderStyle, dashArray);
                 Annotation.UpdateAp();
                 ViewControl.UpdateAnnotFrame();
@@ -221,20 +275,30 @@ namespace ComPDFKit.Controls.Measure.Property
         {
             if (!IsLoadedData) return;
             SolidColorBrush checkBrush = FontColorPickerControl.GetBrush() as SolidColorBrush;
-            if (checkBrush != null && Annotation != null && ViewControl != null)
+            if (checkBrush != null)
             {
                 byte[] color = { checkBrush.Color.R, checkBrush.Color.G, checkBrush.Color.B };
-                if (Annotation != null)
+
+                if (Annotation == null)
                 {
-                    CTextAttribute textAttribute = Annotation.GetTextAttribute();
-                    textAttribute.FontColor = color;
-                    Annotation.SetTextAttribute(textAttribute);
-                    Annotation.UpdateAp();
-                    ViewControl.UpdateAnnotFrame();
+                    polyLineMeasureParam.FontColor = color;
+                    PolyLineMeasureParamChanged?.Invoke(sender, polyLineMeasureParam);
+                }
+
+                if (Annotation != null && ViewControl != null)
+                {
+                    if (Annotation != null)
+                    {
+                        CTextAttribute textAttribute = Annotation.GetTextAttribute();
+                        textAttribute.FontColor = color;
+                        Annotation.SetTextAttribute(textAttribute);
+                        Annotation.UpdateAp();
+                        ViewControl.UpdateAnnotFrame();
+                    }
                 }
             }
         }
-        
+
         public void SetFontStyle(bool isBold, bool isItalic)
         {
             if (isBold == false && isItalic == false)
@@ -266,7 +330,7 @@ namespace ComPDFKit.Controls.Measure.Property
             int index = SizeList.IndexOf((int)size);
             FontSizeComboBox.SelectedIndex = index;
         }
-        
+
         public void SetFontName(string fontName)
         {
             foreach (ComboBoxItem item in FontCombox.Items)
@@ -302,7 +366,7 @@ namespace ComPDFKit.Controls.Measure.Property
             {
                 return;
             }
-            
+
             Color lineColor = Color.FromRgb(param.LineColor[0], param.LineColor[1], param.LineColor[2]);
             BorderColorPickerControl.SetCheckedForColor(lineColor);
             CPDFThicknessControl.Thickness = (int)param.LineWidth;
@@ -323,7 +387,7 @@ namespace ComPDFKit.Controls.Measure.Property
             CPDFOpacityControl.OpacityValue = (int)Math.Ceiling(opacity);
             NoteTextBox.Text = param.Content;
             SetFontSize(param.FontSize);
-            SetFontStyle(param.IsBold,param.IsItalic);
+            SetFontStyle(param.IsBold, param.IsItalic);
             SetFontName(param.FontName);
         }
     }

+ 150 - 47
Demo/Examples/Compdfkit.Controls/Measure/Property/PolygonalProperty.xaml.cs

@@ -19,6 +19,7 @@ using ComPDFKit.Controls.PDFControl;
 using ComPDFKit.PDFAnnotation;
 using ComPDFKit.Tool;
 using CFontNameHelper = ComPDFKit.PDFAnnotation.CTextAttribute.CFontNameHelper;
+using System.Runtime.CompilerServices;
 
 namespace ComPDFKit.Controls.Measure.Property
 {
@@ -30,15 +31,16 @@ namespace ComPDFKit.Controls.Measure.Property
         };
 
         bool IsLoadedData = false;
-        
+
         private PolygonMeasureParam polygonMeasureParam;
-        
-        public CPDFPolygonAnnotation Annotation{ get; set; }
-        
-        public PDFViewControl ViewControl{ get; set; }
 
+        public CPDFPolygonAnnotation Annotation { get; set; }
+
+        public PDFViewControl ViewControl { get; set; }
 
         //private AnnotAttribEvent PolygonalEvent { get; set; }
+        public event EventHandler<PolygonMeasureParam> PolygonMeasureParamChanged;
+
 
         public PolygonalProperty()
         {
@@ -49,6 +51,11 @@ namespace ComPDFKit.Controls.Measure.Property
         {
             if (IsLoadedData)
             {
+                if (Annotation == null)
+                {
+                    polygonMeasureParam.Content = NoteTextBox.Text;
+                    PolygonMeasureParamChanged?.Invoke(sender, polygonMeasureParam);
+                }
                 if (Annotation != null && ViewControl != null)
                 {
                     Annotation.SetContent(NoteTextBox.Text);
@@ -86,7 +93,15 @@ namespace ComPDFKit.Controls.Measure.Property
                 default:
                     break;
             }
-            if(Annotation != null)
+
+            if (Annotation == null)
+            {
+                polygonMeasureParam.IsBold = isBold;
+                polygonMeasureParam.IsItalic = isItalic;
+                PolygonMeasureParamChanged?.Invoke(sender, polygonMeasureParam);
+            }
+
+            if (Annotation != null)
             {
                 CTextAttribute textAttribute = Annotation.GetTextAttribute();
                 var fontType = CFontNameHelper.GetFontType((FontCombox.SelectedItem as ComboBoxItem).Content.ToString());
@@ -104,6 +119,11 @@ namespace ComPDFKit.Controls.Measure.Property
             {
                 if (FontSizeComboBox.SelectedItem != null)
                 {
+                    if (Annotation == null)
+                    {
+                        polygonMeasureParam.FontSize = (float)Convert.ToDouble(FontSizeComboBox.SelectedItem);
+                        PolygonMeasureParamChanged?.Invoke(sender, polygonMeasureParam);
+                    }
                     if (Annotation != null && ViewControl != null)
                     {
                         CTextAttribute textAttribute = Annotation.GetTextAttribute();
@@ -120,9 +140,16 @@ namespace ComPDFKit.Controls.Measure.Property
         {
             if (IsLoadedData)
             {
+                ComboBoxItem selectItem = FontCombox.SelectedItem as ComboBoxItem;
+                if (Annotation == null)
+                {
+                    var fontType = CFontNameHelper.GetFontType(selectItem.Content.ToString());
+                    string FontName = CFontNameHelper.ObtainFontName(fontType, polygonMeasureParam.IsBold, polygonMeasureParam.IsItalic);
+                    polygonMeasureParam.FontName = FontName;
+                    PolygonMeasureParamChanged?.Invoke(sender, polygonMeasureParam);
+                }
                 if (Annotation != null && ViewControl != null)
                 {
-                    ComboBoxItem selectItem = FontCombox.SelectedItem as ComboBoxItem;
                     if (selectItem != null && selectItem.Content != null)
                     {
                         CTextAttribute textAttr = Annotation.GetTextAttribute();
@@ -156,12 +183,17 @@ namespace ComPDFKit.Controls.Measure.Property
         {
             if (IsLoadedData)
             {
-                if (Annotation != null && ViewControl != null)
+                if (BorderColorPickerControl.GetBrush() is SolidColorBrush checkBrush)
                 {
-                    SolidColorBrush checkBrush = BorderColorPickerControl.GetBrush() as SolidColorBrush;
-                    if (checkBrush != null)
+                    byte[] color = { checkBrush.Color.R, checkBrush.Color.G, checkBrush.Color.B };
+
+                    if (Annotation == null)
+                    {
+                        polygonMeasureParam.LineColor = color;
+                        PolygonMeasureParamChanged?.Invoke(sender, polygonMeasureParam);
+                    }
+                    if (Annotation != null && ViewControl != null)
                     {
-                        byte[] color = { checkBrush.Color.R, checkBrush.Color.G, checkBrush.Color.B };
                         Annotation.SetLineColor(color);
                         Annotation.UpdateAp();
                         ViewControl.UpdateAnnotFrame();
@@ -174,13 +206,33 @@ namespace ComPDFKit.Controls.Measure.Property
         {
             if (IsLoadedData)
             {
-                if (Annotation != null && ViewControl != null)
+                SolidColorBrush checkBrush = FillColorPickerControl.GetBrush() as SolidColorBrush;
+                if (checkBrush != null)
                 {
-                    SolidColorBrush checkBrush = FillColorPickerControl.GetBrush() as SolidColorBrush;
-                    if (checkBrush != null)
+                    byte[] color = { checkBrush.Color.R, checkBrush.Color.G, checkBrush.Color.B };
+                    if (Annotation == null)
                     {
-                        byte[] color = { checkBrush.Color.R, checkBrush.Color.G, checkBrush.Color.B };
-                        Annotation.SetBgColor(color);
+                        polygonMeasureParam.FillColor = color;
+                        if (checkBrush.Color != Colors.Transparent)
+                        {
+                            polygonMeasureParam.HasFillColor = true;
+                        }
+                        else
+                        {
+                            polygonMeasureParam.HasFillColor = false;
+                        }
+                        PolygonMeasureParamChanged?.Invoke(sender, polygonMeasureParam);
+                    }
+                    if (Annotation != null && ViewControl != null)
+                    {
+                        if (checkBrush.Color == Colors.Transparent)
+                        {
+                            Annotation.ClearBgColor();
+                        }
+                        else
+                        {
+                            Annotation.SetBgColor(color);
+                        }
                         Annotation.UpdateAp();
                         ViewControl.UpdateAnnotFrame();
                     }
@@ -192,13 +244,19 @@ namespace ComPDFKit.Controls.Measure.Property
         {
             if (IsLoadedData)
             {
+                double opacity = CPDFOpacityControl.OpacityValue / 100.0;
+                if (opacity > 0 && opacity <= 1)
+                {
+                    opacity = opacity * 255;
+                }
+
+                if (Annotation == null)
+                {
+                    polygonMeasureParam.Transparency = (byte)opacity;
+                    PolygonMeasureParamChanged?.Invoke(sender, polygonMeasureParam);
+                }
                 if (Annotation != null && ViewControl != null)
                 {
-                    double opacity = CPDFOpacityControl.OpacityValue / 100.0;
-                    if (opacity > 0 && opacity <= 1)
-                    {
-                        opacity = opacity * 255;
-                    }
                     if (Math.Abs(opacity - Annotation.GetTransparency()) > 0.01)
                     {
                         Annotation.SetTransparency((byte)opacity);
@@ -212,25 +270,33 @@ namespace ComPDFKit.Controls.Measure.Property
         private void CPDFLineStyleControl_LineStyleChanged(object sender, EventArgs e)
         {
             if (!IsLoadedData) return;
-            if (Annotation != null && ViewControl != null)
+            float[] dashArray = null;
+            C_BORDER_STYLE borderStyle;
+            if (CPDFLineStyleControl.DashStyle == DashStyles.Solid || CPDFLineStyleControl.DashStyle == null)
             {
-                float[] dashArray = null;
-                C_BORDER_STYLE borderStyle;
-                if (CPDFLineStyleControl.DashStyle == DashStyles.Solid || CPDFLineStyleControl.DashStyle == null)
-                {
-                    dashArray = new float[0];
-                    borderStyle = C_BORDER_STYLE.BS_SOLID;
-                }
-                else
+                dashArray = new float[0];
+                borderStyle = C_BORDER_STYLE.BS_SOLID;
+            }
+            else
+            {
+                List<float> floatArray = new List<float>();
+                foreach (double num in CPDFLineStyleControl.DashStyle.Dashes)
                 {
-                    List<float> floatArray = new List<float>();
-                    foreach (double num in CPDFLineStyleControl.DashStyle.Dashes)
-                    {
-                        floatArray.Add((float)num);
-                    }
-                    dashArray = floatArray.ToArray();
-                    borderStyle = C_BORDER_STYLE.BS_DASHDED;
+                    floatArray.Add((float)num);
                 }
+                dashArray = floatArray.ToArray();
+                borderStyle = C_BORDER_STYLE.BS_DASHDED;
+            }
+            if (Annotation == null)
+            {
+                polygonMeasureParam.BorderStyle = borderStyle;
+                polygonMeasureParam.LineDash = dashArray;
+
+                PolygonMeasureParamChanged?.Invoke(sender, polygonMeasureParam);
+            }
+            if (Annotation != null && ViewControl != null)
+            {
+
                 Annotation.SetBorderStyle(borderStyle, dashArray);
                 Annotation.UpdateAp();
                 ViewControl.UpdateAnnotFrame();
@@ -241,16 +307,26 @@ namespace ComPDFKit.Controls.Measure.Property
         {
             if (!IsLoadedData) return;
             SolidColorBrush checkBrush = FontColorPickerControl.GetBrush() as SolidColorBrush;
-            if (checkBrush != null && Annotation != null && ViewControl != null)
+            if (checkBrush != null)
             {
                 byte[] color = { checkBrush.Color.R, checkBrush.Color.G, checkBrush.Color.B };
-                if (Annotation != null)
+                if (Annotation == null)
                 {
-                    CTextAttribute textAttribute = Annotation.GetTextAttribute();
-                    textAttribute.FontColor = color;
-                    Annotation.SetTextAttribute(textAttribute);
-                    Annotation.UpdateAp();
-                    ViewControl.UpdateAnnotFrame();
+                    polygonMeasureParam.FontColor = color;
+                    PolygonMeasureParamChanged?.Invoke(sender, polygonMeasureParam);
+                }
+
+                if (Annotation != null && ViewControl != null)
+                {
+
+                    if (Annotation != null)
+                    {
+                        CTextAttribute textAttribute = Annotation.GetTextAttribute();
+                        textAttribute.FontColor = color;
+                        Annotation.SetTextAttribute(textAttribute);
+                        Annotation.UpdateAp();
+                        ViewControl.UpdateAnnotFrame();
+                    }
                 }
             }
         }
@@ -286,7 +362,7 @@ namespace ComPDFKit.Controls.Measure.Property
             int index = SizeList.IndexOf((int)size);
             FontSizeComboBox.SelectedIndex = index;
         }
-        
+
         public void SetFontName(string fontName)
         {
             foreach (ComboBoxItem item in FontCombox.Items)
@@ -308,9 +384,36 @@ namespace ComPDFKit.Controls.Measure.Property
             {
                 return;
             }
-            
+
             Color lineColor = Color.FromRgb(param.LineColor[0], param.LineColor[1], param.LineColor[2]);
             BorderColorPickerControl.SetCheckedForColor(lineColor);
+            if(Annotation != null)
+            {
+                if (!Annotation.HasBgColor)
+                {
+                    FillColorPickerControl.SetCheckedForColor(Colors.Transparent);
+                }
+                else
+                {
+                    Color fillColor = Color.FromRgb(param.FillColor[0], param.FillColor[1], param.FillColor[2]);
+                    FillColorPickerControl.SetCheckedForColor(fillColor);
+                }
+            }
+            else
+            {
+                if (!param.HasFillColor)
+                {
+                    FillColorPickerControl.SetCheckedForColor(Colors.Transparent);
+                }
+                else
+                {
+                    Color fillColor = Color.FromRgb(param.FillColor[0], param.FillColor[1], param.FillColor[2]);
+                    FillColorPickerControl.SetCheckedForColor(fillColor);
+                }
+            }
+            Color FontColor = Color.FromRgb(param.FontColor[0], param.FontColor[1], param.FontColor[2]);    
+            FontColorPickerControl.SetCheckedForColor(FontColor);
+
             if (polygonMeasureParam.BorderStyle == C_BORDER_STYLE.BS_SOLID)
             {
                 CPDFLineStyleControl.DashStyle = DashStyles.Solid;
@@ -328,7 +431,7 @@ namespace ComPDFKit.Controls.Measure.Property
             CPDFOpacityControl.OpacityValue = (int)Math.Ceiling(opacity);
             NoteTextBox.Text = param.Content;
             SetFontSize(param.FontSize);
-            SetFontStyle(param.IsBold,param.IsItalic);
+            SetFontStyle(param.IsBold, param.IsItalic);
             SetFontName(param.FontName);
         }
     }

+ 1 - 1
Demo/Examples/Compdfkit.Controls/Measure/Property/StraightnessProperty.xaml

@@ -9,7 +9,7 @@
              mc:Ignorable="d"
              Loaded="UserControl_Loaded"
              Unloaded="UserControl_Unloaded"
-             >
+             d:DesignHeight="800" d:DesignWidth="300">
     <UserControl.Resources>
         <ResourceDictionary>
             <cpdfcommon:PropertyPanelResourceConverter x:Key="PropertyPanelResourceConverter" />

+ 111 - 36
Demo/Examples/Compdfkit.Controls/Measure/Property/StraightnessProperty.xaml.cs

@@ -21,6 +21,7 @@ using System.Windows.Shapes;
 using ComPDFKit.Controls.PDFControl;
 using ComPDFKit.Tool;
 using CFontNameHelper = ComPDFKit.PDFAnnotation.CTextAttribute.CFontNameHelper;
+using System.IO.Ports; 
 
 namespace ComPDFKit.Controls.Measure.Property
 {
@@ -35,10 +36,16 @@ namespace ComPDFKit.Controls.Measure.Property
         bool IsLoadedData = false;
 
         private LineMeasureParam lineMeasureParam;
-        
-        public CPDFLineAnnotation Annotation{ get; set; }
-        
-        public PDFViewControl ViewControl{ get; set; }
+
+        public CPDFLineAnnotation Annotation
+        {
+            get;
+            set;
+        }
+
+        public PDFViewControl ViewControl { get; set; }
+
+        public event EventHandler<LineMeasureParam> LineMeasureParamChanged;
 
         public StraightnessProperty()
         {
@@ -47,8 +54,14 @@ namespace ComPDFKit.Controls.Measure.Property
 
         private void NoteTextBox_TextChanged(object sender, TextChangedEventArgs e)
         {
+
             if (IsLoadedData)
             {
+                if (Annotation == null)
+                {
+                    lineMeasureParam.Content = NoteTextBox.Text;
+                    LineMeasureParamChanged?.Invoke(sender, lineMeasureParam);
+                }
                 if (Annotation != null && ViewControl != null)
                 {
                     Annotation.SetContent(NoteTextBox.Text);
@@ -61,6 +74,7 @@ namespace ComPDFKit.Controls.Measure.Property
         private void FontStyleCombox_SelectionChanged(object sender, SelectionChangedEventArgs e)
         {
             if (!IsLoadedData) return;
+             
             int selectIndex = Math.Max(0, FontStyleCombox.SelectedIndex);
             bool isBold = false;
             bool isItalic = false;
@@ -86,7 +100,13 @@ namespace ComPDFKit.Controls.Measure.Property
                 default:
                     break;
             }
-            if(Annotation != null)
+            if (Annotation == null)
+            {
+                lineMeasureParam.IsBold = isBold;
+                lineMeasureParam.IsItalic = isItalic;
+                LineMeasureParamChanged?.Invoke(sender, lineMeasureParam);
+            }
+            if (Annotation != null)
             {
                 CTextAttribute textAttribute = Annotation.GetTextAttribute();
                 var fontType = CFontNameHelper.GetFontType((FontCombox.SelectedItem as ComboBoxItem).Content.ToString());
@@ -102,8 +122,14 @@ namespace ComPDFKit.Controls.Measure.Property
         {
             if (IsLoadedData)
             {
+
                 if (FontSizeComboBox.SelectedItem != null)
                 {
+                    if (Annotation == null)
+                    {
+                        lineMeasureParam.FontSize = (float)Convert.ToDouble(FontSizeComboBox.SelectedItem);
+                        LineMeasureParamChanged?.Invoke(sender, lineMeasureParam);
+                    }
                     if (Annotation != null && ViewControl != null)
                     {
                         CTextAttribute textAttribute = Annotation.GetTextAttribute();
@@ -119,10 +145,18 @@ namespace ComPDFKit.Controls.Measure.Property
         private void FontCombox_SelectionChanged(object sender, SelectionChangedEventArgs e)
         {
             if (IsLoadedData)
-            {
+            { 
+                ComboBoxItem selectItem = FontCombox.SelectedItem as ComboBoxItem;
+                if (Annotation == null)
+                {
+                    var fontType = CFontNameHelper.GetFontType(selectItem.Content.ToString());
+                    string FontName = CFontNameHelper.ObtainFontName(fontType, lineMeasureParam.IsBold, lineMeasureParam.IsItalic);
+                    lineMeasureParam.FontName = FontName;
+                    LineMeasureParamChanged?.Invoke(sender, lineMeasureParam);
+                }
+
                 if (Annotation != null && ViewControl != null)
                 {
-                    ComboBoxItem selectItem = FontCombox.SelectedItem as ComboBoxItem;
                     if (selectItem != null && selectItem.Content != null)
                     {
                         CTextAttribute textAttr = Annotation.GetTextAttribute();
@@ -140,14 +174,20 @@ namespace ComPDFKit.Controls.Measure.Property
 
         private void BorderColorPickerControl_ColorChanged(object sender, EventArgs e)
         {
+            SolidColorBrush checkBrush = BorderColorPickerControl.GetBrush() as SolidColorBrush;
+            byte[] color = { checkBrush.Color.R, checkBrush.Color.G, checkBrush.Color.B };
+
             if (IsLoadedData)
-            {
+            { 
+                if (Annotation == null)
+                {
+                    lineMeasureParam.LineColor = color;
+                    LineMeasureParamChanged?.Invoke(sender, lineMeasureParam);
+                }
                 if (Annotation != null && ViewControl != null)
                 {
-                    SolidColorBrush checkBrush = BorderColorPickerControl.GetBrush() as SolidColorBrush;
                     if (checkBrush != null)
                     {
-                        byte[] color = { checkBrush.Color.R, checkBrush.Color.G, checkBrush.Color.B };
                         Annotation.SetLineColor(color);
                         Annotation.UpdateAp();
                         ViewControl.UpdateAnnotFrame();
@@ -158,11 +198,18 @@ namespace ComPDFKit.Controls.Measure.Property
 
         private void CPDFOpacityControl_OpacityChanged(object sender, EventArgs e)
         {
+
             if (IsLoadedData)
             {
+                double opacity = CPDFOpacityControl.OpacityValue / 100.0;
+
+                if (Annotation == null)
+                {
+                    lineMeasureParam.Transparency = (byte)(opacity * 255);
+                    LineMeasureParamChanged?.Invoke(sender, lineMeasureParam);
+                }
                 if (Annotation != null && ViewControl != null)
                 {
-                    double opacity = CPDFOpacityControl.OpacityValue / 100.0;
                     if (opacity > 0 && opacity <= 1)
                     {
                         opacity = opacity * 255;
@@ -186,7 +233,7 @@ namespace ComPDFKit.Controls.Measure.Property
             {
                 return;
             }
-            
+
             Color lineColor = Color.FromRgb(param.LineColor[0], param.LineColor[1], param.LineColor[2]);
             BorderColorPickerControl.SetCheckedForColor(lineColor);
             CPDFThicknessControl.Thickness = (int)param.LineWidth;
@@ -213,10 +260,10 @@ namespace ComPDFKit.Controls.Measure.Property
             CPDFOpacityControl.OpacityValue = (int)Math.Ceiling(opacity);
             NoteTextBox.Text = param.Content;
             SetFontSize(param.FontSize);
-            SetFontStyle(param.IsBold,param.IsItalic);
+            SetFontStyle(param.IsBold, param.IsItalic);
             SetFontName(param.FontName);
         }
-        
+
         public void SetFontName(string fontName)
         {
             foreach (ComboBoxItem item in FontCombox.Items)
@@ -263,6 +310,11 @@ namespace ComPDFKit.Controls.Measure.Property
 
         private void CPDFThicknessControl_ThicknessChanged(object sender, EventArgs e)
         {
+            if (Annotation == null)
+            {
+                lineMeasureParam.LineWidth = (byte)CPDFThicknessControl.Thickness;
+                LineMeasureParamChanged?.Invoke(sender, lineMeasureParam);
+            }
             if (IsLoadedData)
             {
                 if (Annotation != null && ViewControl != null)
@@ -276,26 +328,34 @@ namespace ComPDFKit.Controls.Measure.Property
 
         private void CPDFLineStyleControl_LineStyleChanged(object sender, EventArgs e)
         {
+
             if (!IsLoadedData) return;
-            if (Annotation != null && ViewControl != null)
+            float[] dashArray = null;
+            C_BORDER_STYLE borderStyle;
+            if (CPDFLineStyleControl.DashStyle == DashStyles.Solid || CPDFLineStyleControl.DashStyle == null)
             {
-                float[] dashArray = null;
-                C_BORDER_STYLE borderStyle;
-                if (CPDFLineStyleControl.DashStyle == DashStyles.Solid || CPDFLineStyleControl.DashStyle == null)
-                {
-                    dashArray = new float[0];
-                    borderStyle = C_BORDER_STYLE.BS_SOLID;
-                }
-                else
+                dashArray = new float[0];
+                borderStyle = C_BORDER_STYLE.BS_SOLID;
+            }
+            else
+            {
+                List<float> floatArray = new List<float>();
+                foreach (double num in CPDFLineStyleControl.DashStyle.Dashes)
                 {
-                    List<float> floatArray = new List<float>();
-                    foreach (double num in CPDFLineStyleControl.DashStyle.Dashes)
-                    {
-                        floatArray.Add((float)num);
-                    }
-                    dashArray = floatArray.ToArray();
-                    borderStyle = C_BORDER_STYLE.BS_DASHDED;
+                    floatArray.Add((float)num);
                 }
+                dashArray = floatArray.ToArray();
+                borderStyle = C_BORDER_STYLE.BS_DASHDED;
+            }
+
+            if (Annotation == null)
+            {
+                lineMeasureParam.BorderStyle = borderStyle;
+                lineMeasureParam.LineDash = dashArray;
+                LineMeasureParamChanged?.Invoke(sender, lineMeasureParam);
+            }
+            if (Annotation != null && ViewControl != null)
+            { 
                 Annotation.SetBorderStyle(borderStyle, dashArray);
                 Annotation.UpdateAp();
                 ViewControl.UpdateAnnotFrame();
@@ -305,13 +365,22 @@ namespace ComPDFKit.Controls.Measure.Property
         private void CPDFArrowControl_ArrowChanged(object sender, EventArgs e)
         {
             if (!IsLoadedData) return;
+            LineType lineType = new LineType()
+            {
+                HeadLineType = CPDFArrowControl.LineType.HeadLineType,
+                TailLineType = CPDFArrowControl.LineType.TailLineType
+            };
+
+            if (Annotation == null)
+            {
+                lineMeasureParam.HeadLineType = lineType.HeadLineType;
+                lineMeasureParam.TailLineType = lineType.TailLineType;
+                LineMeasureParamChanged?.Invoke(sender, lineMeasureParam);
+            }
+
             if (Annotation != null && ViewControl != null)
             {
-                LineType lineType = new LineType()
-                {
-                    HeadLineType = CPDFArrowControl.LineType.HeadLineType,
-                    TailLineType = CPDFArrowControl.LineType.TailLineType
-                };
+
                 Annotation.SetLineType(lineType.HeadLineType, lineType.TailLineType);
                 Annotation.UpdateAp();
                 ViewControl.UpdateAnnotFrame();
@@ -322,9 +391,15 @@ namespace ComPDFKit.Controls.Measure.Property
         {
             if (!IsLoadedData) return;
             SolidColorBrush checkBrush = FontColorPickerControl.GetBrush() as SolidColorBrush;
+            byte[] color = { checkBrush.Color.R, checkBrush.Color.G, checkBrush.Color.B };
+
+            if (Annotation == null)
+            {
+                lineMeasureParam.FontColor = color; 
+                LineMeasureParamChanged?.Invoke(sender, lineMeasureParam);
+            }
             if (checkBrush != null && Annotation != null && ViewControl != null)
             {
-                byte[] color = { checkBrush.Color.R, checkBrush.Color.G, checkBrush.Color.B };
                 if (Annotation != null)
                 {
                     CTextAttribute textAttribute = Annotation.GetTextAttribute();

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

@@ -289,6 +289,7 @@ namespace ComPDFKit.Controls.PDFControl
                         pdfView.GetDocument().WriteToLoadedPath();
                     }
                 }
+
                 keyWord = e;
                 textSearch.TextSearchDocument = pdfView.GetDocument();
                 SearchResult.ClearSearchResult();
@@ -300,7 +301,19 @@ namespace ComPDFKit.Controls.PDFControl
                 
                 keyWord = e;
                 textSearch.TextSearchDocument = pdfView.GetDocument();
-                textSearch.SearchText(e, C_Search_Options.Search_Case_Insensitive, ViewControl.Password);
+
+                C_Search_Options options = C_Search_Options.Search_Case_Insensitive;
+                if(!CaseChb.IsChecked)
+                {
+                    options |= C_Search_Options.Search_Case_Sensitive;
+                }
+
+                if(MatchChb.IsChecked)
+                {
+                    options |= C_Search_Options.Search_Match_Whole_Word;
+                }
+
+                textSearch.SearchText(e, options, ViewControl.Password);
             }
             else if (ReplaceTog.IsChecked == true)
             {

+ 90 - 19
Demo/Examples/Compdfkit.Controls/PDFView/PDFSearch/PDFSearchUI/CPDFSearchResultUI.xaml.cs

@@ -59,7 +59,7 @@ namespace ComPDFKit.Controls.PDFControlUI
             ResultListControl.Visibility = Visibility.Collapsed;
             NoResultText.Visibility = Visibility.Visible;
         }
-        
+
         public void AddSearchResult(BindSearchResult result)
         {
             if (result == null)
@@ -161,7 +161,7 @@ namespace ComPDFKit.Controls.PDFControlUI
         /// The page rotation angle.
         /// </summary>
         public int PageRotate { get; set; }
-        public object RefData {  get; set; }
+        public object RefData { get; set; }
     }
 
     internal class TextBindData
@@ -203,6 +203,59 @@ namespace ComPDFKit.Controls.PDFControlUI
                     }
                 });
 
+        public static int MapIndexToContent(string a, string b, int indexInA)
+        {
+            if (string.IsNullOrEmpty(a) || string.IsNullOrEmpty(b) || indexInA < 0 || indexInA >= a.Length)
+            {
+                return -1;
+            }
+
+            int indexInB = 0;
+            int aIndexCounter = 0;
+
+            // Iterate over b and match characters to those in a
+            for (int i = 0; i < b.Length; i++)
+            {
+                if (b[i] != ' ')
+                {
+                    if (aIndexCounter == indexInA)
+                    {
+                        indexInB = i;
+                        break;
+                    }
+                    aIndexCounter++;
+                }
+            }
+
+            return indexInB;
+        }
+
+        public static string RestoreStringWithSpaces(string a, string b, int startIndexInB)
+        {
+            if (string.IsNullOrEmpty(a) || string.IsNullOrEmpty(b) || startIndexInB < 0 || startIndexInB >= b.Length)
+            {
+                return string.Empty;
+            }
+            a = Regex.Replace(a, @"[\r\n\s]", "");
+            int aIndex = 0;
+            string result = string.Empty;
+
+            for (int i = startIndexInB; i < b.Length && aIndex < a.Length; i++)
+            {
+                if (b[i] == ' ')
+                {
+                    result += ' ';
+                }
+                else
+                {
+                    result += a[aIndex];
+                    aIndex++;
+                }
+            }
+
+            return result;
+        }
+
         /// <summary>
         /// Get document stream data
         /// </summary>
@@ -216,44 +269,56 @@ namespace ComPDFKit.Controls.PDFControlUI
             Paragraph textPara = new Paragraph();
             Document.Blocks.Add(textPara);
             List<int> indexList = new List<int>();
-            content = Regex.Replace(content, "[\r\n]", " ");
-            if (keyword.Length > 0)
+            content = Regex.Replace(content, @"[\r\n]", " ");
+            int originalIndex = -1; 
+            string contentForMatch = Regex.Replace(content, @"[\r\n\s]", "");
+            string keywordForMatch = Regex.Replace(keyword, @"\s", "");
+
+            if (keywordForMatch.Length > 0)
             {
-                for (int i = 0; i < content.Length && i >= 0;)
+                for (int i = 0, offset = 0; i < contentForMatch.Length && i >= 0;)
                 {
-                    i = content.IndexOf(keyword, i, StringComparison.OrdinalIgnoreCase);
+                    i = contentForMatch.IndexOf(keywordForMatch, i, StringComparison.OrdinalIgnoreCase);
                     if (i == -1)
                     {
                         break;
                     }
-                    if (indexList.Contains(i) == false)
+                     
+                    originalIndex = content.IndexOf(keyword, offset, StringComparison.OrdinalIgnoreCase);
+                    if (originalIndex != -1 && !indexList.Contains(originalIndex))
+                    {
+                        indexList.Add(originalIndex);
+                        offset = originalIndex + keyword.Length;  
+                        i += keywordForMatch.Length;
+                    }
+                    else if(originalIndex == -1)
                     {
-                        indexList.Add(i);
+                        originalIndex = MapIndexToContent(contentForMatch, content, i);
+                        indexList.Add(originalIndex);
+                        offset = originalIndex + keyword.Length;  
+                        i += keywordForMatch.Length;
                     }
-                    i += keyword.Length;
                 }
             }
+            if(originalIndex != -1)
+            {
+                keyword = RestoreStringWithSpaces(keyword, content, originalIndex);
+            }
+             
             List<string> splitList = new List<string>();
             int lastIndex = -1;
             foreach (int index in indexList)
             {
-                string prevStr = string.Empty;
-                if (lastIndex == -1)
-                {
-                    prevStr = content.Substring(0, index);
-                }
-                else
-                {
-                    prevStr = content.Substring(lastIndex + keyword.Length, index - lastIndex - 1);
-                }
+                string prevStr = lastIndex == -1 ? content.Substring(0, index) : content.Substring(lastIndex + keyword.Length, index - lastIndex - keyword.Length);
                 if (prevStr != string.Empty)
                 {
                     splitList.Add(prevStr);
                 }
-
+                 
                 splitList.Add(content.Substring(index, keyword.Length));
                 lastIndex = index;
             }
+             
             if (indexList.Count > 0)
             {
                 lastIndex = indexList[indexList.Count - 1];
@@ -262,6 +327,11 @@ namespace ComPDFKit.Controls.PDFControlUI
                     splitList.Add(content.Substring(lastIndex + keyword.Length));
                 }
             }
+            else
+            {
+                splitList.Add(content);  
+            }
+             
             TextBlock addBlock = new TextBlock();
             foreach (string textappend in splitList)
             {
@@ -278,5 +348,6 @@ namespace ComPDFKit.Controls.PDFControlUI
             return Document;
         }
 
+
     }
 }

+ 130 - 4
Demo/Examples/Compdfkit.Controls/PDFView/PDFViewControl/PDFViewControl.xaml.cs

@@ -14,12 +14,13 @@ using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Input;
 using ComPDFKit.Controls.Helper;
-using ComPDFKit.Tool.DrawTool;
 using SplitMode = ComPDFKit.Controls.PDFControlUI.CPDFViewModeUI.SplitMode;
 using System.Threading;
 using System.Threading.Tasks;
 using ComPDFKitViewer.Annot;
 using System.IO;
+using ComPDFKit.Import;
+using ComPDFKit.PDFPage;
 
 namespace ComPDFKit.Controls.PDFControl
 {
@@ -34,6 +35,7 @@ namespace ComPDFKit.Controls.PDFControl
         public string Password { get; set; } = string.Empty;
 
         public CPDFViewerTool PDFViewTool { get; private set; }
+
         public CPDFToolManager PDFToolManager { get; private set; }
 
         public CPDFViewerTool FocusPDFViewTool { get; private set; }
@@ -44,9 +46,11 @@ namespace ComPDFKit.Controls.PDFControl
         public event EventHandler<MouseEventObject> MouseLeftButtonUpHandler;
         public event EventHandler<MouseEventObject> MouseMoveHandler;
         public event EventHandler<MouseEventObject> MouseRightButtonDownHandler;
-        public event EventHandler<ComPDFKitViewer.MouseWheelZoomArgs> MouseWheelZoomHandler;
+        public event EventHandler<MouseWheelZoomArgs> MouseWheelZoomHandler;
         public event EventHandler DrawChanged;
 
+        public PageSelectedData SnapshotData { get; private set; }
+
         //private ContextMenu RightMenu;
         #region Properties
 
@@ -57,6 +61,7 @@ namespace ComPDFKit.Controls.PDFControl
 
         private double[] zoomLevelList = { 1f, 8f, 12f, 25, 33f, 50, 66f, 75, 100, 125, 150, 200, 300, 400, 600, 800, 1000 };
         #endregion
+
         public PDFViewControl()
         {
             InitializeComponent();
@@ -78,6 +83,7 @@ namespace ComPDFKit.Controls.PDFControl
             PDFViewTool.GetCPDFViewer().MouseWheelZoomHandler -= PDFViewControl_MouseWheelZoomHandler;
             PDFViewTool.GetCPDFViewer().MouseMove -= PDFViewControl_MouseMove;
             PDFViewTool.DrawChanged -= PDFViewTool_DrawChanged;
+            PDFViewTool.PageSelectedChanged -= PDFViewTool_PageSelectedChanged;
             PDFToolManager.MouseLeftButtonDownHandler -= PDFToolManager_MouseLeftButtonDownHandler;
             PDFToolManager.MouseLeftButtonUpHandler -= PDFToolManager_MouseLeftButtonUpHandler;
             PDFToolManager.MouseMoveHandler -= PDFToolManager_MouseMoveHandler;
@@ -87,6 +93,7 @@ namespace ComPDFKit.Controls.PDFControl
             PDFViewTool.GetCPDFViewer().MouseWheelZoomHandler += PDFViewControl_MouseWheelZoomHandler;
             PDFViewTool.GetCPDFViewer().MouseMove += PDFViewControl_MouseMove;
             PDFViewTool.DrawChanged += PDFViewTool_DrawChanged;
+            PDFViewTool.PageSelectedChanged += PDFViewTool_PageSelectedChanged;
             PDFToolManager.MouseLeftButtonDownHandler += PDFToolManager_MouseLeftButtonDownHandler;
             PDFToolManager.MouseLeftButtonUpHandler += PDFToolManager_MouseLeftButtonUpHandler;
             PDFToolManager.MouseMoveHandler += PDFToolManager_MouseMoveHandler;
@@ -95,6 +102,7 @@ namespace ComPDFKit.Controls.PDFControl
             splitViewerTool.SizeChanged -= SplitViewerTool_SizeChanged;
             splitViewerTool.GetCPDFViewer().MouseWheelZoomHandler -= SplitPDFViewControl_MouseWheelZoomHandler;
             splitViewerTool.DrawChanged -= PDFViewTool_DrawChanged;
+            splitViewerTool.PageSelectedChanged -= PDFViewTool_PageSelectedChanged;
             splitToolManager.MouseLeftButtonDownHandler -= PDFToolManager_MouseLeftButtonDownHandler;
             splitToolManager.MouseLeftButtonUpHandler -= PDFToolManager_MouseLeftButtonUpHandler;
             splitToolManager.MouseMoveHandler -= PDFToolManager_MouseMoveHandler;
@@ -103,20 +111,34 @@ namespace ComPDFKit.Controls.PDFControl
             splitViewerTool.SizeChanged += SplitViewerTool_SizeChanged;
             splitViewerTool.GetCPDFViewer().MouseWheelZoomHandler += SplitPDFViewControl_MouseWheelZoomHandler;
             splitViewerTool.DrawChanged += PDFViewTool_DrawChanged;
+            splitViewerTool.PageSelectedChanged += PDFViewTool_PageSelectedChanged;
             splitToolManager.MouseLeftButtonDownHandler += PDFToolManager_MouseLeftButtonDownHandler;
             splitToolManager.MouseLeftButtonUpHandler += PDFToolManager_MouseLeftButtonUpHandler;
             splitToolManager.MouseMoveHandler += PDFToolManager_MouseMoveHandler;
             splitToolManager.MouseRightButtonDownHandler += PDFToolManager_MouseRightButtonDownHandler;
 
+            GetCPDFViewer().OnRenderFinish -= PDFViewControl_OnRenderFinish;
+            GetCPDFViewer().OnRenderFinish += PDFViewControl_OnRenderFinish;
+
             SetCursor();
         }
 
+        private void PDFViewControl_OnRenderFinish(object sender, EventArgs e)
+        {
+            SetCursorStatus();
+        }
+
         private void PDFViewTool_DrawChanged(object sender, EventArgs e)
         {
             FocusPDFViewToolChanged?.Invoke(this, EventArgs.Empty);
             DrawChanged?.Invoke(sender, e);
         }
 
+        private void PDFViewTool_PageSelectedChanged(object sender, PageSelectedData e)
+        {
+            SnapshotData = e;
+        }
+
         public ContextMenu GetRightMenu()
         {
             FocusPDFViewTool.ContextMenu?.Items.Clear();
@@ -312,7 +334,6 @@ namespace ComPDFKit.Controls.PDFControl
 
             viewerTool?.GetCPDFViewer()?.UpdateRenderFrame();
             splitViewerTool?.GetCPDFViewer()?.UpdateRenderFrame();
-
         }
 
         public void SetToolType(ToolType type)
@@ -529,6 +550,38 @@ namespace ComPDFKit.Controls.PDFControl
             }
         }
 
+        private void ReloadDocument()
+        {
+            viewerTool?.GetCPDFViewer()?.UpdateVirtualNodes();
+            splitViewerTool?.GetCPDFViewer()?.UpdateVirtualNodes();
+            viewerTool?.GetCPDFViewer()?.UpdateRenderFrame();
+            splitViewerTool?.GetCPDFViewer()?.UpdateRenderFrame();
+        }
+
+        public void CropPage(CPDFDisplayBox cropBox, Rect cropRect, List<int> pagesList)
+        {
+            bool needLoad = false;
+            CPDFDocument doc = FocusPDFViewTool.GetCPDFViewer().GetDocument();
+
+            foreach (int pageIndex in pagesList)
+            {
+                if (pageIndex < 0 || pageIndex > doc.PageCount)
+                {
+                    continue;
+                }
+                CPDFPage CropPage = doc.PageAtIndex(pageIndex);
+                CRect rect = new CRect((float)cropRect.X, (float)(cropRect.Y + cropRect.Height), (float)(cropRect.X + cropRect.Width), (float)cropRect.Y);
+                CropPage.CropPage(cropBox, rect);
+                CropPage.ReleaseAllAnnotations();
+                needLoad = true;
+            }
+
+            if (needLoad)
+            {
+                ReloadDocument();
+            }
+        }
+
         #region Private Command Methods
         private double CheckZoomLevel(double zoom, bool IsGrowth)
         {
@@ -598,8 +651,80 @@ namespace ComPDFKit.Controls.PDFControl
             }
         }
 
+        private void SetCursorStatus()
+        {
+            List<ToolType> toolTypes = new List<ToolType>
+                {
+                      ToolType.Viewer,
+                      ToolType.Pan
+                };
+
+            ToolType currentMode = PDFViewTool.GetToolType();
+            Cursor newCursor = Cursors.Arrow;
+
+            if (toolTypes.Contains(currentMode))
+            {
+                BaseAnnot hitAnnot = GetCPDFViewer().AnnotHitTest();
+                if (hitAnnot != null)
+                {
+                    if (hitAnnot is LinkAnnot || hitAnnot is BaseWidget)
+                    {
+                        newCursor = Cursors.Hand;
+                    }
+                    else
+                    {
+                        newCursor = annotEditCursor;
+                    }
+                }
+                else
+                {
+                    if (!PDFViewTool.IsSelectRectMousePoint())
+                    {
+                        newCursor = (PDFToolManager.GetToolType() == ToolType.Pan) ? panToolCursor : Cursors.Arrow;
+
+                        if (PDFViewTool.IsText())
+                        {
+                            newCursor = Cursors.IBeam;
+                        }
+                    }
+                }
+
+                if (currentMode == ToolType.CreateAnnot)
+                {
+                    List<C_ANNOTATION_TYPE> annotTypes = new List<C_ANNOTATION_TYPE>
+                    {
+                         C_ANNOTATION_TYPE.C_ANNOTATION_HIGHLIGHT,
+                         C_ANNOTATION_TYPE.C_ANNOTATION_UNDERLINE,
+                         C_ANNOTATION_TYPE.C_ANNOTATION_SQUIGGLY,
+                         C_ANNOTATION_TYPE.C_ANNOTATION_STRIKEOUT
+                    };
+
+                    if (GetCPDFViewer().AnnotHitTest() == null && PDFViewTool.IsText() && annotTypes.Contains(toolManager.GetAnnotType()))
+                    {
+                        newCursor = Cursors.IBeam;
+                    }
+                    else
+                    {
+                        if (newCursor == Cursors.IBeam || newCursor == panToolCursor || newCursor == Cursors.Arrow)
+                        {
+                            newCursor = annotEditCursor;
+                        }
+                    }
+                }
+            }
+
+            GetCPDFViewer().Cursor = newCursor;
+        }
+
         private void PDFViewControl_MouseMove(object sender, MouseEventArgs e)
         {
+            if (GetCPDFViewer().IsRendering)
+            {
+                GetCPDFViewer().Cursor = Cursors.Wait;
+                FocusPDFViewTool.ContextMenu?.Items.Clear();
+                return;
+            }
+
             if (isAutomaticScroll)
             {
                 middleMovePoint = e.GetPosition(this);
@@ -666,7 +791,7 @@ namespace ComPDFKit.Controls.PDFControl
                             {
                                 newCursor = Cursors.IBeam;
                             }
-                            cursorSet = true; 
+                            cursorSet = true;
                         }
                     }
 
@@ -685,6 +810,7 @@ namespace ComPDFKit.Controls.PDFControl
                          C_ANNOTATION_TYPE.C_ANNOTATION_SQUIGGLY,
                          C_ANNOTATION_TYPE.C_ANNOTATION_STRIKEOUT
                     };
+
                     if (GetCPDFViewer().AnnotHitTest() == null && PDFViewTool.IsText() && annotTypes.Contains(toolManager.GetAnnotType()))
                     {
                         newCursor = Cursors.IBeam;

+ 1 - 0
Demo/Examples/Compdfkit.Controls/PageEdit/PDFPageEdit/CPDFPageEditControl.xaml.cs

@@ -1219,6 +1219,7 @@ namespace ComPDFKit.Controls.PDFControl
                 item.VerticalContentAlignment = VerticalAlignment.Center;
                 bindPageList.Add(item);
             }
+
             PageEditListBox.ItemsSource = bindPageList;
         }
          

+ 2 - 2
Demo/Examples/Compdfkit.Controls/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("2.1.0.0")]
-[assembly: AssemblyFileVersion("2.1.0.0")]
+[assembly: AssemblyVersion("2.2.0.0")]
+[assembly: AssemblyFileVersion("2.2.0.0")]

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 142 - 0
Demo/Examples/Compdfkit.Controls/Snapshot/SnapshotMenu.xaml


+ 311 - 0
Demo/Examples/Compdfkit.Controls/Snapshot/SnapshotMenu.xaml.cs

@@ -0,0 +1,311 @@
+using ComPDFKit.Controls.Common;
+using ComPDFKit.Controls.Helper;
+using ComPDFKit.Controls.PDFControl;
+using ComPDFKit.Import;
+using ComPDFKit.PDFDocument;
+using ComPDFKit.PDFPage;
+using ComPDFKit.Tool;
+using ComPDFKitViewer;
+using Microsoft.Win32;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+
+namespace ComPDFKit.Controls.Snapshot
+{
+    public partial class SnapshotMenu : UserControl
+    {
+        public SnapshotEditToolArgs SnapToolArgs { get; set; }
+        public PDFViewControl PdfViewer { get; set; }
+        public event EventHandler<KeyValuePair<string,object>> SnapToolEvent;
+
+        public SnapshotMenu()
+        {
+            InitializeComponent();
+            SetLangText();
+        }
+
+        private void SetLangText()
+        {
+            ToolTipService.SetToolTip(ReSnapshotBtn, LanguageHelper.CompressManager.GetString("ContentSelection_CancelDo"));
+            ToolTipService.SetToolTip(SnapshotPrintBtn, LanguageHelper.CompressManager.GetString("Main_Print"));
+            ToolTipService.SetToolTip(SnapshotSaveBtn, LanguageHelper.CompressManager.GetString("ContentSelection_Output"));
+            ToolTipService.SetToolTip(SnapshotCloseBtn, LanguageHelper.CompressManager.GetString("ContentSelection_Exit"));
+            ToolTipService.SetToolTip(SnapshotCopyBtn, LanguageHelper.CompressManager.GetString("Main_Copy"));
+            ToolTipService.SetToolTip(SnapshotCorpBtn, LanguageHelper.CompressManager.GetString("Main_Crop"));
+            ToolTipService.SetToolTip(SnapshotCorpBtn2, LanguageHelper.CompressManager.GetString("Main_Crop"));
+        }
+
+        private void Button_ReSnapshot(object sender, RoutedEventArgs e)
+        {
+            if(SnapToolArgs!=null)
+            {
+                SnapToolArgs.ReSnapshot();
+            }
+        }
+
+        private void Button_SnapshotClose(object sender, RoutedEventArgs e)
+        {
+            if(SnapToolEvent!=null)
+            {
+                KeyValuePair<string, object> param = new KeyValuePair<string, object>("CloseSnap",null);
+                SnapToolEvent.Invoke(this, param);
+            }
+        }
+
+        private void Button_SnapshotCopy(object sender, RoutedEventArgs e)
+        {
+            if (SnapToolArgs != null)
+            {
+                SnapToolArgs.SaveSnapshotToClipboard();
+                if (SnapToolEvent != null)
+                {
+                    KeyValuePair<string, object> param = new KeyValuePair<string, object>("CloseSnap", null);
+                    SnapToolEvent.Invoke(this, param);
+                }
+            }
+        }
+
+        private int CropPageUI { get; set; }
+       
+        private void Button_SnapshotCorp(object sender, RoutedEventArgs e)
+        {
+            if (MessageBoxEx.Show(LanguageHelper.CompressManager.GetString("Corp_Customize_PRM") + "                                                           ", LanguageHelper.CompressManager.GetString("Corp_Customize"), System.Windows.Forms.MessageBoxButtons.OKCancel, System.Windows.Forms.MessageBoxIcon.Warning) == System.Windows.Forms.DialogResult.OK)
+            {
+                if (SnapToolArgs != null && PdfViewer != null)
+                {
+                    List<int> cropPageList = new List<int>();
+                    Rect rect = SnapToolArgs.GetSnapshotPDFRect(out int pageIndexex);
+                    cropPageList.Add(pageIndexex);
+                    PdfViewer?.CropPage(CPDFDisplayBox.CropBox, rect, cropPageList);
+                    PdfViewer.FocusPDFViewTool.GetCPDFViewer().GoToPage(pageIndexex);
+                    KeyValuePair<string, object> param = new KeyValuePair<string, object>("Save", null);
+                    SnapToolEvent.Invoke(this, param);
+
+                    if (SnapToolEvent != null)
+                    {
+                        param = new KeyValuePair<string, object>("CloseSnap", null);
+                        SnapToolEvent.Invoke(this, param);
+                    }
+                }
+            }
+        }
+
+        private void Button_SnapshotSave(object sender, RoutedEventArgs e)
+        {
+            if (SnapToolArgs != null && PdfViewer != null && PdfViewer.PDFToolManager != null)
+            {
+                SaveFileDialog dlg = new SaveFileDialog();
+                dlg.Filter = "jpg|*.jpg|png|*.png";
+                dlg.FileName = PdfViewer.GetCPDFViewer().GetDocument().FileName;
+                if(dlg.FileName==null ||dlg.FileName.Trim().Length==0)
+                {
+                    dlg.FileName = "Blank" + DateTime.Now.ToString("yyyyMMddHHmmss");
+                }
+
+                if (dlg.ShowDialog() == true)
+                {
+                    string fileName = dlg.FileName;
+                    WriteableBitmap saveBitmap= SnapToolArgs.GetSnapshotImage();
+                    if(saveBitmap!=null)
+                    {
+                        if (dlg.SafeFileName.ToLower().EndsWith(".jpg"))
+                        {
+                            Stream saveStream = dlg.OpenFile();
+                            JpegBitmapEncoder jpgEncoder = new JpegBitmapEncoder();
+                            BitmapFrame frame = BitmapFrame.Create(saveBitmap);
+                            jpgEncoder.Frames.Add(frame);
+                            jpgEncoder.Save(saveStream);
+                            saveStream.Dispose();
+                        }
+                        else if (dlg.SafeFileName.ToLower().EndsWith(".png"))
+                        {
+                            Stream saveStream = dlg.OpenFile();
+                            PngBitmapEncoder pngEncoder = new PngBitmapEncoder();
+                            BitmapFrame frame = BitmapFrame.Create(saveBitmap);
+                            pngEncoder.Frames.Add(frame);
+                            pngEncoder.Save(saveStream);
+                            saveStream.Dispose();
+                        }
+
+                        CommonHelper.ExplorerFile(dlg.FileName);
+                    }
+
+                    if (SnapToolEvent != null)
+                    {
+                        KeyValuePair<string, object> param = new KeyValuePair<string, object>("CloseSnap", null);
+                        SnapToolEvent.Invoke(this, param);
+                    }
+                }
+            }
+        }
+
+        private void Button_PrintSnapshot(object sender, RoutedEventArgs e)
+        {
+            if (SnapToolArgs != null)
+            {
+                try
+                {
+                    WriteableBitmap saveBitmap = SnapToolArgs.GetSnapshotImage();
+                    if (saveBitmap != null)
+                    {
+                        PrintDialog printDlg = new PrintDialog();
+                        if (printDlg.ShowDialog() == true)
+                        {
+                            DrawingVisual visualItem = new DrawingVisual();
+                            DrawingContext drawContext = visualItem.RenderOpen();
+                            drawContext.DrawImage(saveBitmap, new Rect(0, 0, saveBitmap.Width, saveBitmap.Height));
+                            drawContext.Close();
+                            printDlg.PrintVisual(visualItem, "Snapshot");
+                        }
+                    }
+
+                    if (SnapToolEvent != null)
+                    {
+                        KeyValuePair<string, object> param = new KeyValuePair<string, object>("CloseSnap", null);
+                        SnapToolEvent.Invoke(this, param);
+                    }
+                }
+                catch (Exception ex)
+                {
+
+                }
+            }
+        }
+    }
+
+    public class SnapshotToolArgs
+    {
+        public Color LineColor;
+        public Color BgColor;
+        public double LineWidth;
+        public double Transparency;
+        public DashStyle LineDash;
+        public bool HasBgColor;
+
+        public SnapshotToolArgs()
+        {
+            LineDash = new DashStyle();
+            HasBgColor = true;
+            LineColor = Color.FromRgb(49, 106, 197);
+            BgColor = Color.FromRgb(153, 193, 218);
+            LineWidth = 1;
+            Transparency = 0.75;
+        }
+    }
+
+    public class SnapshotEditToolArgs : SnapshotToolArgs
+    {
+        public Color HighLightColor;
+        public Color ControlPointColor;
+        public UserControl ToolPanel;
+        public PDFViewControl Viewer { get; set; }
+
+        public SnapshotEditToolArgs() : base()
+        {
+            HighLightColor = Colors.Transparent;
+            ControlPointColor = Color.FromRgb(71, 126, 222);
+        }
+
+        public void ReSnapshot()
+        {
+            Viewer.FocusPDFViewTool.CleanPageSelectedRect();
+        }
+
+        public void SaveSnapshotToClipboard()
+        {
+            WriteableBitmap snapImage = GetSnapshotImage();
+            if (snapImage != null)
+            {
+                try
+                {
+                    Clipboard.SetImage(snapImage);
+                }
+                catch (Exception ex)
+                {
+
+                }
+            }
+        }
+
+        public WriteableBitmap GetSnapshotImage()
+        {
+            if (Viewer != null && Viewer.SnapshotData != null)
+            {
+                CPDFDocument pdfDoc = Viewer.GetCPDFViewer().GetDocument();
+                PageSelectedData snapData = Viewer.SnapshotData;
+                CPDFViewer pdfViewer = Viewer.GetCPDFViewer();
+                if (snapData.SelectRect.IsEmpty == false)
+                {
+                    try
+                    {
+                        CPDFPage pdfPage = pdfDoc.PageAtIndex(snapData.PageIndex);
+                        double zoom = pdfViewer.GetZoom();
+                        Rect snapRect = snapData.SelectRect;
+                        DrawMode drawMode = pdfViewer.GetDrawModes();
+                        uint bgColor = 0xFFFFFFFF;
+                        int flag = 1;
+                        switch (drawMode)
+                        {
+                            case DrawMode.Soft:
+                                bgColor = 0xFFFFEFB2;
+                                break;
+                            case DrawMode.Green:
+                                bgColor = 0xFFCBE9CE;
+                                break;
+                            case DrawMode.Dark:
+                                bgColor = 0xFF000000;
+                                flag = flag | 0x08 | 0x10000;
+                                break;
+                            case DrawMode.Normal:
+                                bgColor = 0xFFFFFFFF;
+                                break;
+                            case DrawMode.Custom:
+                                bgColor = pdfViewer.GetPDFBackground();
+                                break;
+                            default:
+                                break;
+                        }
+                        byte[] imageData = new byte[(int)snapRect.Width * (int)snapRect.Height * 4];
+                        pdfPage.RenderPageBitmapWithMatrix((float)(zoom * 96D / 72D), new CRect(
+                            (float)snapRect.Left,
+                            (float)snapRect.Bottom,
+                            (float)snapRect.Right,
+                            (float)snapRect.Top),
+                            bgColor,
+                            imageData,
+                            flag,
+                            true);
+                        WriteableBitmap snapBitmap = new WriteableBitmap((int)snapRect.Width, (int)snapRect.Height, 96, 96, PixelFormats.Bgra32, null);
+                        snapBitmap.WritePixels(new Int32Rect(0, 0, (int)snapRect.Width, (int)snapRect.Height), imageData, snapBitmap.BackBufferStride, 0);
+                        return snapBitmap;
+                    }
+                    catch (Exception ex)
+                    {
+
+                    }
+                }
+            }
+
+            return null;
+        }
+
+        public Rect GetSnapshotPDFRect(out int pageIndex)
+        {
+            pageIndex = -1;
+            if (Viewer != null && Viewer.SnapshotData != null)
+            {
+                PageSelectedData snapData = Viewer.SnapshotData;
+
+                pageIndex = snapData.PageIndex;
+                return snapData.RawRect;
+            }
+
+            return Rect.Empty;
+        }
+    }
+}

+ 3 - 0
Demo/Examples/Compdfkit.Controls/Strings/Common.resx

@@ -603,4 +603,7 @@
   <data name="Printer_FitPrintable" xml:space="preserve">
     <value>Fit to Printable Area</value>
   </data>
+  <data name="Tooltip_Select" xml:space="preserve">
+    <value>Content Selection Tool</value>
+  </data>
 </root>

+ 3 - 0
Demo/Examples/Compdfkit.Controls/Strings/Common.zh.resx

@@ -603,4 +603,7 @@
   <data name="Printer_FitPrintable" xml:space="preserve">
     <value>适合可打印区域</value>
   </data>
+  <data name="Tooltip_Select" xml:space="preserve">
+    <value>内容选择工具</value>
+  </data>
 </root>

+ 405 - 0
Demo/Examples/Compdfkit.Controls/Strings/Compress.Designer.cs

@@ -0,0 +1,405 @@
+//------------------------------------------------------------------------------
+// <auto-generated>
+//     This code was generated by a tool.
+//     Runtime Version:4.0.30319.42000
+//
+//     Changes to this file may cause incorrect behavior and will be lost if
+//     the code is regenerated.
+// </auto-generated>
+//------------------------------------------------------------------------------
+
+namespace ComPDFKit.Controls.Strings {
+    using System;
+    
+    
+    /// <summary>
+    ///   A strongly-typed resource class, for looking up localized strings, etc.
+    /// </summary>
+    // This class was auto-generated by the StronglyTypedResourceBuilder
+    // class via a tool like ResGen or Visual Studio.
+    // To add or remove a member, edit your .ResX file then rerun ResGen
+    // with the /str option, or rebuild your VS project.
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+    [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+    internal class Compress {
+        
+        private static global::System.Resources.ResourceManager resourceMan;
+        
+        private static global::System.Globalization.CultureInfo resourceCulture;
+        
+        [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+        internal Compress() {
+        }
+        
+        /// <summary>
+        ///   Returns the cached ResourceManager instance used by this class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ComPDFKit.Controls.Strings.Compress", typeof(Compress).Assembly);
+                    resourceMan = temp;
+                }
+                return resourceMan;
+            }
+        }
+        
+        /// <summary>
+        ///   Overrides the current thread's CurrentUICulture property for all
+        ///   resource lookups using this strongly typed resource class.
+        /// </summary>
+        [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
+                return resourceCulture;
+            }
+            set {
+                resourceCulture = value;
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Custom.
+        /// </summary>
+        internal static string Compress_Custom {
+            get {
+                return ResourceManager.GetString("Compress_Custom", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to High.
+        /// </summary>
+        internal static string Compress_High {
+            get {
+                return ResourceManager.GetString("Compress_High", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Low.
+        /// </summary>
+        internal static string Compress_Low {
+            get {
+                return ResourceManager.GetString("Compress_Low", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Medium.
+        /// </summary>
+        internal static string Compress_Medium {
+            get {
+                return ResourceManager.GetString("Compress_Medium", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to The file size entered is incorrect, try again please.
+        /// </summary>
+        internal static string Compress_NumberErrorWarning {
+            get {
+                return ResourceManager.GetString("Compress_NumberErrorWarning", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Compress files succeeded!.
+        /// </summary>
+        internal static string Compress_OKWarning {
+            get {
+                return ResourceManager.GetString("Compress_OKWarning", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Optimization Options.
+        /// </summary>
+        internal static string Compress_OptimizationQuality {
+            get {
+                return ResourceManager.GetString("Compress_OptimizationQuality", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Are you sure to stop the compressing?.
+        /// </summary>
+        internal static string CompressInterruptWarning {
+            get {
+                return ResourceManager.GetString("CompressInterruptWarning", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Compress.
+        /// </summary>
+        internal static string CompressStr {
+            get {
+                return ResourceManager.GetString("CompressStr", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Undo.
+        /// </summary>
+        internal static string ContentSelection_CancelDo {
+            get {
+                return ResourceManager.GetString("ContentSelection_CancelDo", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Exit.
+        /// </summary>
+        internal static string ContentSelection_Exit {
+            get {
+                return ResourceManager.GetString("ContentSelection_Exit", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Output.
+        /// </summary>
+        internal static string ContentSelection_Output {
+            get {
+                return ResourceManager.GetString("ContentSelection_Output", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Progress.
+        /// </summary>
+        internal static string Convert_Progress {
+            get {
+                return ResourceManager.GetString("Convert_Progress", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Select Area.
+        /// </summary>
+        internal static string Corp_Customize {
+            get {
+                return ResourceManager.GetString("Corp_Customize", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to The page cannot be restored to original state after you have cropped it. Are you sure you want to crop the page?.
+        /// </summary>
+        internal static string Corp_Customize_PRM {
+            get {
+                return ResourceManager.GetString("Corp_Customize_PRM", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Location.
+        /// </summary>
+        internal static string FileInfo_Location {
+            get {
+                return ResourceManager.GetString("FileInfo_Location", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Size.
+        /// </summary>
+        internal static string FileInfo_Size {
+            get {
+                return ResourceManager.GetString("FileInfo_Size", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Add Files.
+        /// </summary>
+        internal static string Main_AddFile {
+            get {
+                return ResourceManager.GetString("Main_AddFile", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Cancel.
+        /// </summary>
+        internal static string Main_Cancel {
+            get {
+                return ResourceManager.GetString("Main_Cancel", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Completed.
+        /// </summary>
+        internal static string Main_CompletedState {
+            get {
+                return ResourceManager.GetString("Main_CompletedState", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Copy.
+        /// </summary>
+        internal static string Main_Copy {
+            get {
+                return ResourceManager.GetString("Main_Copy", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Crop.
+        /// </summary>
+        internal static string Main_Crop {
+            get {
+                return ResourceManager.GetString("Main_Crop", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Delete.
+        /// </summary>
+        internal static string Main_Delete {
+            get {
+                return ResourceManager.GetString("Main_Delete", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Failed.
+        /// </summary>
+        internal static string Main_FailedState {
+            get {
+                return ResourceManager.GetString("Main_FailedState", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to File Name.
+        /// </summary>
+        internal static string Main_FileName {
+            get {
+                return ResourceManager.GetString("Main_FileName", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Hint.
+        /// </summary>
+        internal static string Main_HintWarningTitle {
+            get {
+                return ResourceManager.GetString("Main_HintWarningTitle", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Interrupt.
+        /// </summary>
+        internal static string Main_Interrupt {
+            get {
+                return ResourceManager.GetString("Main_Interrupt", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to About Us.
+        /// </summary>
+        internal static string Main_MenuHelp_About {
+            get {
+                return ResourceManager.GetString("Main_MenuHelp_About", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to No.
+        /// </summary>
+        internal static string Main_No {
+            get {
+                return ResourceManager.GetString("Main_No", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to No file selected.
+        /// </summary>
+        internal static string Main_NoSelectedFilesWarning {
+            get {
+                return ResourceManager.GetString("Main_NoSelectedFilesWarning", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to OK.
+        /// </summary>
+        internal static string Main_Ok {
+            get {
+                return ResourceManager.GetString("Main_Ok", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Please select a folder.
+        /// </summary>
+        internal static string Main_OpenFolderNoteWarning {
+            get {
+                return ResourceManager.GetString("Main_OpenFolderNoteWarning", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Print.
+        /// </summary>
+        internal static string Main_Print {
+            get {
+                return ResourceManager.GetString("Main_Print", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Remove All Files.
+        /// </summary>
+        internal static string Main_RemoveAll {
+            get {
+                return ResourceManager.GetString("Main_RemoveAll", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Yes.
+        /// </summary>
+        internal static string Main_Yes {
+            get {
+                return ResourceManager.GetString("Main_Yes", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Move Down.
+        /// </summary>
+        internal static string Merge_MoveDown {
+            get {
+                return ResourceManager.GetString("Merge_MoveDown", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to Move Up.
+        /// </summary>
+        internal static string Merge_MoveUp {
+            get {
+                return ResourceManager.GetString("Merge_MoveUp", resourceCulture);
+            }
+        }
+        
+        /// <summary>
+        ///   Looks up a localized string similar to {0} file(s) in total.
+        /// </summary>
+        internal static string Merge_TotalPage {
+            get {
+                return ResourceManager.GetString("Merge_TotalPage", resourceCulture);
+            }
+        }
+    }
+}

+ 234 - 0
Demo/Examples/Compdfkit.Controls/Strings/Compress.resx

@@ -0,0 +1,234 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <data name="CompressInterruptWarning" xml:space="preserve">
+    <value>Are you sure to stop the compressing?</value>
+  </data>
+  <data name="CompressStr" xml:space="preserve">
+    <value>Compress</value>
+  </data>
+  <data name="Compress_Custom" xml:space="preserve">
+    <value>Custom</value>
+  </data>
+  <data name="Compress_High" xml:space="preserve">
+    <value>High</value>
+  </data>
+  <data name="Compress_Low" xml:space="preserve">
+    <value>Low</value>
+  </data>
+  <data name="Compress_Medium" xml:space="preserve">
+    <value>Medium</value>
+  </data>
+  <data name="Compress_NumberErrorWarning" xml:space="preserve">
+    <value>The file size entered is incorrect, try again please</value>
+  </data>
+  <data name="Compress_OKWarning" xml:space="preserve">
+    <value>Compress files succeeded!</value>
+  </data>
+  <data name="Compress_OptimizationQuality" xml:space="preserve">
+    <value>Optimization Options</value>
+  </data>
+  <data name="ContentSelection_CancelDo" xml:space="preserve">
+    <value>Undo</value>
+  </data>
+  <data name="ContentSelection_Exit" xml:space="preserve">
+    <value>Exit</value>
+  </data>
+  <data name="ContentSelection_Output" xml:space="preserve">
+    <value>Output</value>
+  </data>
+  <data name="Convert_Progress" xml:space="preserve">
+    <value>Progress</value>
+  </data>
+  <data name="Corp_Customize" xml:space="preserve">
+    <value>Select Area</value>
+  </data>
+  <data name="Corp_Customize_PRM" xml:space="preserve">
+    <value>The page cannot be restored to original state after you have cropped it. Are you sure you want to crop the page?</value>
+  </data>
+  <data name="FileInfo_Location" xml:space="preserve">
+    <value>Location</value>
+  </data>
+  <data name="FileInfo_Size" xml:space="preserve">
+    <value>Size</value>
+  </data>
+  <data name="Main_AddFile" xml:space="preserve">
+    <value>Add Files</value>
+  </data>
+  <data name="Main_Cancel" xml:space="preserve">
+    <value>Cancel</value>
+  </data>
+  <data name="Main_CompletedState" xml:space="preserve">
+    <value>Completed</value>
+  </data>
+  <data name="Main_Copy" xml:space="preserve">
+    <value>Copy</value>
+  </data>
+  <data name="Main_Crop" xml:space="preserve">
+    <value>Crop</value>
+  </data>
+  <data name="Main_Delete" xml:space="preserve">
+    <value>Delete</value>
+  </data>
+  <data name="Main_FailedState" xml:space="preserve">
+    <value>Failed</value>
+  </data>
+  <data name="Main_FileName" xml:space="preserve">
+    <value>File Name</value>
+  </data>
+  <data name="Main_HintWarningTitle" xml:space="preserve">
+    <value>Hint</value>
+  </data>
+  <data name="Main_Interrupt" xml:space="preserve">
+    <value>Interrupt</value>
+  </data>
+  <data name="Main_MenuHelp_About" xml:space="preserve">
+    <value>About Us</value>
+  </data>
+  <data name="Main_No" xml:space="preserve">
+    <value>No</value>
+  </data>
+  <data name="Main_NoSelectedFilesWarning" xml:space="preserve">
+    <value>No file selected</value>
+  </data>
+  <data name="Main_Ok" xml:space="preserve">
+    <value>OK</value>
+  </data>
+  <data name="Main_OpenFolderNoteWarning" xml:space="preserve">
+    <value>Please select a folder</value>
+  </data>
+  <data name="Main_Print" xml:space="preserve">
+    <value>Print</value>
+  </data>
+  <data name="Main_RemoveAll" xml:space="preserve">
+    <value>Remove All Files</value>
+  </data>
+  <data name="Main_Yes" xml:space="preserve">
+    <value>Yes</value>
+  </data>
+  <data name="Merge_MoveDown" xml:space="preserve">
+    <value>Move Down</value>
+  </data>
+  <data name="Merge_MoveUp" xml:space="preserve">
+    <value>Move Up</value>
+  </data>
+  <data name="Merge_TotalPage" xml:space="preserve">
+    <value>{0} file(s) in total</value>
+  </data>
+</root>

+ 234 - 0
Demo/Examples/Compdfkit.Controls/Strings/Compress.zh.resx

@@ -0,0 +1,234 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" use="required" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <data name="CompressInterruptWarning" xml:space="preserve">
+    <value>确定要中断压缩吗?</value>
+  </data>
+  <data name="CompressStr" xml:space="preserve">
+    <value>压缩</value>
+  </data>
+  <data name="Compress_Custom" xml:space="preserve">
+    <value>自定义</value>
+  </data>
+  <data name="Compress_High" xml:space="preserve">
+    <value>高</value>
+  </data>
+  <data name="Compress_Low" xml:space="preserve">
+    <value>低</value>
+  </data>
+  <data name="Compress_Medium" xml:space="preserve">
+    <value>标准</value>
+  </data>
+  <data name="Compress_NumberErrorWarning" xml:space="preserve">
+    <value>输入的文件大小错误,请重试</value>
+  </data>
+  <data name="Compress_OKWarning" xml:space="preserve">
+    <value>压缩文件成功!</value>
+  </data>
+  <data name="Compress_OptimizationQuality" xml:space="preserve">
+    <value>优化选项</value>
+  </data>
+  <data name="ContentSelection_CancelDo" xml:space="preserve">
+    <value>撤销</value>
+  </data>
+  <data name="ContentSelection_Exit" xml:space="preserve">
+    <value>退出</value>
+  </data>
+  <data name="ContentSelection_Output" xml:space="preserve">
+    <value>导出</value>
+  </data>
+  <data name="Convert_Progress" xml:space="preserve">
+    <value>进度</value>
+  </data>
+  <data name="Corp_Customize" xml:space="preserve">
+    <value>自定义裁剪区域</value>
+  </data>
+  <data name="Corp_Customize_PRM" xml:space="preserve">
+    <value>裁剪后的页面无法恢复到原始状态,是否继续裁剪?</value>
+  </data>
+  <data name="FileInfo_Location" xml:space="preserve">
+    <value>位置</value>
+  </data>
+  <data name="FileInfo_Size" xml:space="preserve">
+    <value>大小</value>
+  </data>
+  <data name="Main_AddFile" xml:space="preserve">
+    <value>添加文档</value>
+  </data>
+  <data name="Main_Cancel" xml:space="preserve">
+    <value>取消</value>
+  </data>
+  <data name="Main_CompletedState" xml:space="preserve">
+    <value>完成</value>
+  </data>
+  <data name="Main_Copy" xml:space="preserve">
+    <value>复制</value>
+  </data>
+  <data name="Main_Crop" xml:space="preserve">
+    <value>裁剪</value>
+  </data>
+  <data name="Main_Delete" xml:space="preserve">
+    <value>删除</value>
+  </data>
+  <data name="Main_FailedState" xml:space="preserve">
+    <value>失败</value>
+  </data>
+  <data name="Main_FileName" xml:space="preserve">
+    <value>文件名</value>
+  </data>
+  <data name="Main_HintWarningTitle" xml:space="preserve">
+    <value>提示</value>
+  </data>
+  <data name="Main_Interrupt" xml:space="preserve">
+    <value>中断</value>
+  </data>
+  <data name="Main_MenuHelp_About" xml:space="preserve">
+    <value>关于</value>
+  </data>
+  <data name="Main_No" xml:space="preserve">
+    <value>否</value>
+  </data>
+  <data name="Main_NoSelectedFilesWarning" xml:space="preserve">
+    <value>没有选择文件</value>
+  </data>
+  <data name="Main_Ok" xml:space="preserve">
+    <value>确认</value>
+  </data>
+  <data name="Main_OpenFolderNoteWarning" xml:space="preserve">
+    <value>请选择文件夹</value>
+  </data>
+  <data name="Main_Print" xml:space="preserve">
+    <value>打印</value>
+  </data>
+  <data name="Main_RemoveAll" xml:space="preserve">
+    <value>移除全部文件</value>
+  </data>
+  <data name="Main_Yes" xml:space="preserve">
+    <value>是</value>
+  </data>
+  <data name="Merge_MoveDown" xml:space="preserve">
+    <value>下移</value>
+  </data>
+  <data name="Merge_MoveUp" xml:space="preserve">
+    <value>上移</value>
+  </data>
+  <data name="Merge_TotalPage" xml:space="preserve">
+    <value>共{0}个文件</value>
+  </data>
+</root>

+ 18 - 0
Demo/Examples/Compdfkit.Controls/Strings/PropertyPanel.Designer.cs

@@ -735,6 +735,15 @@ namespace ComPDFKit.Controls.Strings {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to Line and Border Shape.
+        /// </summary>
+        internal static string Property_LineShape {
+            get {
+                return ResourceManager.GetString("Property_LineShape", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to Line and Border Style.
         /// </summary>
@@ -1248,6 +1257,15 @@ namespace ComPDFKit.Controls.Strings {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to Cloud.
+        /// </summary>
+        internal static string Title_Cloud {
+            get {
+                return ResourceManager.GetString("Title_Cloud", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to Combo Button.
         /// </summary>

+ 0 - 0
Demo/Examples/Compdfkit.Controls/Strings/PropertyPanel.resx


Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä